Coverage Report

Created: 2022-01-22 13:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/Interp/State.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- State.cpp - State chain for the VM and AST Walker ------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "State.h"
10
#include "Frame.h"
11
#include "Program.h"
12
#include "clang/AST/ASTContext.h"
13
#include "clang/AST/CXXInheritance.h"
14
15
using namespace clang;
16
using namespace clang::interp;
17
18
19.1M
State::~State() {}
19
20
OptionalDiagnostic State::FFDiag(SourceLocation Loc, diag::kind DiagId,
21
119k
                                 unsigned ExtraNotes) {
22
119k
  return diag(Loc, DiagId, ExtraNotes, false);
23
119k
}
24
25
OptionalDiagnostic State::FFDiag(const Expr *E, diag::kind DiagId,
26
5.86M
                                 unsigned ExtraNotes) {
27
5.86M
  if (getEvalStatus().Diag)
28
689k
    return diag(E->getExprLoc(), DiagId, ExtraNotes, false);
29
5.17M
  setActiveDiagnostic(false);
30
5.17M
  return OptionalDiagnostic();
31
5.86M
}
32
33
OptionalDiagnostic State::FFDiag(const SourceInfo &SI, diag::kind DiagId,
34
0
                                 unsigned ExtraNotes) {
35
0
  if (getEvalStatus().Diag)
36
0
    return diag(SI.getLoc(), DiagId, ExtraNotes, false);
37
0
  setActiveDiagnostic(false);
38
0
  return OptionalDiagnostic();
39
0
}
40
41
OptionalDiagnostic State::CCEDiag(SourceLocation Loc, diag::kind DiagId,
42
34.5k
                                  unsigned ExtraNotes) {
43
  // Don't override a previous diagnostic. Don't bother collecting
44
  // diagnostics if we're evaluating for overflow.
45
34.5k
  if (!getEvalStatus().Diag || 
!getEvalStatus().Diag->empty()6.94k
) {
46
28.3k
    setActiveDiagnostic(false);
47
28.3k
    return OptionalDiagnostic();
48
28.3k
  }
49
6.15k
  return diag(Loc, DiagId, ExtraNotes, true);
50
34.5k
}
51
52
OptionalDiagnostic State::CCEDiag(const Expr *E, diag::kind DiagId,
53
32.6k
                                  unsigned ExtraNotes) {
54
32.6k
  return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes);
55
32.6k
}
56
57
OptionalDiagnostic State::CCEDiag(const SourceInfo &SI, diag::kind DiagId,
58
0
                                  unsigned ExtraNotes) {
59
0
  return CCEDiag(SI.getLoc(), DiagId, ExtraNotes);
60
0
}
61
62
4.31M
OptionalDiagnostic State::Note(SourceLocation Loc, diag::kind DiagId) {
63
4.31M
  if (!hasActiveDiagnostic())
64
3.60M
    return OptionalDiagnostic();
65
715k
  return OptionalDiagnostic(&addDiag(Loc, DiagId));
66
4.31M
}
67
68
0
void State::addNotes(ArrayRef<PartialDiagnosticAt> Diags) {
69
0
  if (hasActiveDiagnostic()) {
70
0
    getEvalStatus().Diag->insert(getEvalStatus().Diag->end(), Diags.begin(),
71
0
                                 Diags.end());
72
0
  }
73
0
}
74
75
108
DiagnosticBuilder State::report(SourceLocation Loc, diag::kind DiagId) {
76
108
  return getCtx().getDiagnostics().Report(Loc, DiagId);
77
108
}
78
79
/// Add a diagnostic to the diagnostics list.
80
1.47M
PartialDiagnostic &State::addDiag(SourceLocation Loc, diag::kind DiagId) {
81
1.47M
  PartialDiagnostic PD(DiagId, getCtx().getDiagAllocator());
82
1.47M
  getEvalStatus().Diag->push_back(std::make_pair(Loc, PD));
83
1.47M
  return getEvalStatus().Diag->back().second;
84
1.47M
}
85
86
OptionalDiagnostic State::diag(SourceLocation Loc, diag::kind DiagId,
87
815k
                               unsigned ExtraNotes, bool IsCCEDiag) {
88
815k
  Expr::EvalStatus &EvalStatus = getEvalStatus();
89
815k
  if (EvalStatus.Diag) {
90
762k
    if (hasPriorDiagnostic()) {
91
3.15k
      return OptionalDiagnostic();
92
3.15k
    }
93
94
758k
    unsigned CallStackNotes = getCallStackDepth() - 1;
95
758k
    unsigned Limit = getCtx().getDiagnostics().getConstexprBacktraceLimit();
96
758k
    if (Limit)
97
756k
      CallStackNotes = std::min(CallStackNotes, Limit + 1);
98
758k
    if (checkingPotentialConstantExpression())
99
331
      CallStackNotes = 0;
100
101
758k
    setActiveDiagnostic(true);
102
758k
    setFoldFailureDiagnostic(!IsCCEDiag);
103
758k
    EvalStatus.Diag->clear();
104
758k
    EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes);
105
758k
    addDiag(Loc, DiagId);
106
758k
    if (!checkingPotentialConstantExpression()) {
107
758k
      addCallStack(Limit);
108
758k
    }
109
758k
    return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second);
110
762k
  }
111
53.5k
  setActiveDiagnostic(false);
112
53.5k
  return OptionalDiagnostic();
113
815k
}
114
115
23.0M
const LangOptions &State::getLangOpts() const { return getCtx().getLangOpts(); }
116
117
758k
void State::addCallStack(unsigned Limit) {
118
  // Determine which calls to skip, if any.
119
758k
  unsigned ActiveCalls = getCallStackDepth() - 1;
120
758k
  unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart;
121
758k
  if (Limit && 
Limit < ActiveCalls756k
) {
122
8
    SkipStart = Limit / 2 + Limit % 2;
123
8
    SkipEnd = ActiveCalls - Limit / 2;
124
8
  }
125
126
  // Walk the call stack and add the diagnostics.
127
758k
  unsigned CallIdx = 0;
128
758k
  Frame *Top = getCurrentFrame();
129
758k
  const Frame *Bottom = getBottomFrame();
130
761k
  for (Frame *F = Top; F != Bottom; 
F = F->getCaller(), ++CallIdx2.86k
) {
131
2.86k
    SourceLocation CallLocation = F->getCallLocation();
132
133
    // Skip this call?
134
2.86k
    if (CallIdx >= SkipStart && 
CallIdx < SkipEnd746
) {
135
714
      if (CallIdx == SkipStart) {
136
        // Note that we're skipping calls.
137
8
        addDiag(CallLocation, diag::note_constexpr_calls_suppressed)
138
8
            << unsigned(ActiveCalls - Limit);
139
8
      }
140
714
      continue;
141
714
    }
142
143
    // Use a different note for an inheriting constructor, because from the
144
    // user's perspective it's not really a function at all.
145
2.14k
    if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(F->getCallee())) {
146
465
      if (CD->isInheritingConstructor()) {
147
0
        addDiag(CallLocation, diag::note_constexpr_inherited_ctor_call_here)
148
0
            << CD->getParent();
149
0
        continue;
150
0
      }
151
465
    }
152
153
2.14k
    SmallString<128> Buffer;
154
2.14k
    llvm::raw_svector_ostream Out(Buffer);
155
2.14k
    F->describe(Out);
156
2.14k
    addDiag(CallLocation, diag::note_constexpr_call_here) << Out.str();
157
2.14k
  }
158
758k
}