Coverage Report

Created: 2022-07-16 07:03

/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
20.7M
State::~State() {}
19
20
OptionalDiagnostic State::FFDiag(SourceLocation Loc, diag::kind DiagId,
21
128k
                                 unsigned ExtraNotes) {
22
128k
  return diag(Loc, DiagId, ExtraNotes, false);
23
128k
}
24
25
OptionalDiagnostic State::FFDiag(const Expr *E, diag::kind DiagId,
26
6.36M
                                 unsigned ExtraNotes) {
27
6.36M
  if (getEvalStatus().Diag)
28
749k
    return diag(E->getExprLoc(), DiagId, ExtraNotes, false);
29
5.61M
  setActiveDiagnostic(false);
30
5.61M
  return OptionalDiagnostic();
31
6.36M
}
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
38.0k
                                  unsigned ExtraNotes) {
43
  // Don't override a previous diagnostic. Don't bother collecting
44
  // diagnostics if we're evaluating for overflow.
45
38.0k
  if (!getEvalStatus().Diag || 
!getEvalStatus().Diag->empty()8.33k
) {
46
30.5k
    setActiveDiagnostic(false);
47
30.5k
    return OptionalDiagnostic();
48
30.5k
  }
49
7.51k
  return diag(Loc, DiagId, ExtraNotes, true);
50
38.0k
}
51
52
OptionalDiagnostic State::CCEDiag(const Expr *E, diag::kind DiagId,
53
36.1k
                                  unsigned ExtraNotes) {
54
36.1k
  return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes);
55
36.1k
}
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.72M
OptionalDiagnostic State::Note(SourceLocation Loc, diag::kind DiagId) {
63
4.72M
  if (!hasActiveDiagnostic())
64
3.94M
    return OptionalDiagnostic();
65
776k
  return OptionalDiagnostic(&addDiag(Loc, DiagId));
66
4.72M
}
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.60M
PartialDiagnostic &State::addDiag(SourceLocation Loc, diag::kind DiagId) {
81
1.60M
  PartialDiagnostic PD(DiagId, getCtx().getDiagAllocator());
82
1.60M
  getEvalStatus().Diag->push_back(std::make_pair(Loc, PD));
83
1.60M
  return getEvalStatus().Diag->back().second;
84
1.60M
}
85
86
OptionalDiagnostic State::diag(SourceLocation Loc, diag::kind DiagId,
87
885k
                               unsigned ExtraNotes, bool IsCCEDiag) {
88
885k
  Expr::EvalStatus &EvalStatus = getEvalStatus();
89
885k
  if (EvalStatus.Diag) {
90
826k
    if (hasPriorDiagnostic()) {
91
4.20k
      return OptionalDiagnostic();
92
4.20k
    }
93
94
822k
    unsigned CallStackNotes = getCallStackDepth() - 1;
95
822k
    unsigned Limit = getCtx().getDiagnostics().getConstexprBacktraceLimit();
96
822k
    if (Limit)
97
819k
      CallStackNotes = std::min(CallStackNotes, Limit + 1);
98
822k
    if (checkingPotentialConstantExpression())
99
352
      CallStackNotes = 0;
100
101
822k
    setActiveDiagnostic(true);
102
822k
    setFoldFailureDiagnostic(!IsCCEDiag);
103
822k
    EvalStatus.Diag->clear();
104
822k
    EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes);
105
822k
    addDiag(Loc, DiagId);
106
822k
    if (!checkingPotentialConstantExpression()) {
107
822k
      addCallStack(Limit);
108
822k
    }
109
822k
    return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second);
110
826k
  }
111
59.0k
  setActiveDiagnostic(false);
112
59.0k
  return OptionalDiagnostic();
113
885k
}
114
115
26.6M
const LangOptions &State::getLangOpts() const { return getCtx().getLangOpts(); }
116
117
822k
void State::addCallStack(unsigned Limit) {
118
  // Determine which calls to skip, if any.
119
822k
  unsigned ActiveCalls = getCallStackDepth() - 1;
120
822k
  unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart;
121
822k
  if (Limit && 
Limit < ActiveCalls819k
) {
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
822k
  unsigned CallIdx = 0;
128
822k
  Frame *Top = getCurrentFrame();
129
822k
  const Frame *Bottom = getBottomFrame();
130
825k
  for (Frame *F = Top; F != Bottom; 
F = F->getCaller(), ++CallIdx3.13k
) {
131
3.13k
    SourceLocation CallLocation = F->getCallLocation();
132
133
    // Skip this call?
134
3.13k
    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.42k
    if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(F->getCallee())) {
146
473
      if (CD->isInheritingConstructor()) {
147
0
        addDiag(CallLocation, diag::note_constexpr_inherited_ctor_call_here)
148
0
            << CD->getParent();
149
0
        continue;
150
0
      }
151
473
    }
152
153
2.42k
    SmallString<128> Buffer;
154
2.42k
    llvm::raw_svector_ostream Out(Buffer);
155
2.42k
    F->describe(Out);
156
2.42k
    addDiag(CallLocation, diag::note_constexpr_call_here) << Out.str();
157
2.42k
  }
158
822k
}