Coverage Report

Created: 2021-08-24 07:12

/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.4M
State::~State() {}
19
20
OptionalDiagnostic State::FFDiag(SourceLocation Loc, diag::kind DiagId,
21
117k
                                 unsigned ExtraNotes) {
22
117k
  return diag(Loc, DiagId, ExtraNotes, false);
23
117k
}
24
25
OptionalDiagnostic State::FFDiag(const Expr *E, diag::kind DiagId,
26
6.24M
                                 unsigned ExtraNotes) {
27
6.24M
  if (getEvalStatus().Diag)
28
691k
    return diag(E->getExprLoc(), DiagId, ExtraNotes, false);
29
5.54M
  setActiveDiagnostic(false);
30
5.54M
  return OptionalDiagnostic();
31
6.24M
}
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
45.7k
                                  unsigned ExtraNotes) {
43
  // Don't override a previous diagnostic. Don't bother collecting
44
  // diagnostics if we're evaluating for overflow.
45
45.7k
  if (!getEvalStatus().Diag || 
!getEvalStatus().Diag->empty()21.1k
) {
46
39.1k
    setActiveDiagnostic(false);
47
39.1k
    return OptionalDiagnostic();
48
39.1k
  }
49
6.58k
  return diag(Loc, DiagId, ExtraNotes, true);
50
45.7k
}
51
52
OptionalDiagnostic State::CCEDiag(const Expr *E, diag::kind DiagId,
53
30.1k
                                  unsigned ExtraNotes) {
54
30.1k
  return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes);
55
30.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.30M
OptionalDiagnostic State::Note(SourceLocation Loc, diag::kind DiagId) {
63
4.30M
  if (!hasActiveDiagnostic())
64
3.59M
    return OptionalDiagnostic();
65
715k
  return OptionalDiagnostic(&addDiag(Loc, DiagId));
66
4.30M
}
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
816k
                               unsigned ExtraNotes, bool IsCCEDiag) {
88
816k
  Expr::EvalStatus &EvalStatus = getEvalStatus();
89
816k
  if (EvalStatus.Diag) {
90
764k
    if (hasPriorDiagnostic()) {
91
3.46k
      return OptionalDiagnostic();
92
3.46k
    }
93
94
760k
    unsigned CallStackNotes = getCallStackDepth() - 1;
95
760k
    unsigned Limit = getCtx().getDiagnostics().getConstexprBacktraceLimit();
96
760k
    if (Limit)
97
758k
      CallStackNotes = std::min(CallStackNotes, Limit + 1);
98
760k
    if (checkingPotentialConstantExpression())
99
542
      CallStackNotes = 0;
100
101
760k
    setActiveDiagnostic(true);
102
760k
    setFoldFailureDiagnostic(!IsCCEDiag);
103
760k
    EvalStatus.Diag->clear();
104
760k
    EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes);
105
760k
    addDiag(Loc, DiagId);
106
760k
    if (!checkingPotentialConstantExpression()) {
107
760k
      addCallStack(Limit);
108
760k
    }
109
760k
    return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second);
110
764k
  }
111
51.7k
  setActiveDiagnostic(false);
112
51.7k
  return OptionalDiagnostic();
113
816k
}
114
115
23.8M
const LangOptions &State::getLangOpts() const { return getCtx().getLangOpts(); }
116
117
760k
void State::addCallStack(unsigned Limit) {
118
  // Determine which calls to skip, if any.
119
760k
  unsigned ActiveCalls = getCallStackDepth() - 1;
120
760k
  unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart;
121
760k
  if (Limit && 
Limit < ActiveCalls758k
) {
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
760k
  unsigned CallIdx = 0;
128
760k
  Frame *Top = getCurrentFrame();
129
760k
  const Frame *Bottom = getBottomFrame();
130
763k
  for (Frame *F = Top; F != Bottom; 
F = F->getCaller(), ++CallIdx2.81k
) {
131
2.81k
    SourceLocation CallLocation = F->getCallLocation();
132
133
    // Skip this call?
134
2.81k
    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.09k
    if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(F->getCallee())) {
146
454
      if (CD->isInheritingConstructor()) {
147
0
        addDiag(CallLocation, diag::note_constexpr_inherited_ctor_call_here)
148
0
            << CD->getParent();
149
0
        continue;
150
0
      }
151
454
    }
152
153
2.09k
    SmallString<128> Buffer;
154
2.09k
    llvm::raw_svector_ostream Out(Buffer);
155
2.09k
    F->describe(Out);
156
2.09k
    addDiag(CallLocation, diag::note_constexpr_call_here) << Out.str();
157
2.09k
  }
158
760k
}