Coverage Report

Created: 2020-02-25 14:32

/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
17.0M
State::~State() {}
19
20
OptionalDiagnostic State::FFDiag(SourceLocation Loc, diag::kind DiagId,
21
156k
                                 unsigned ExtraNotes) {
22
156k
  return diag(Loc, DiagId, ExtraNotes, false);
23
156k
}
24
25
OptionalDiagnostic State::FFDiag(const Expr *E, diag::kind DiagId,
26
4.02M
                                 unsigned ExtraNotes) {
27
4.02M
  if (getEvalStatus().Diag)
28
434k
    return diag(E->getExprLoc(), DiagId, ExtraNotes, false);
29
3.58M
  setActiveDiagnostic(false);
30
3.58M
  return OptionalDiagnostic();
31
3.58M
}
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
30.4k
                                  unsigned ExtraNotes) {
43
30.4k
  // Don't override a previous diagnostic. Don't bother collecting
44
30.4k
  // diagnostics if we're evaluating for overflow.
45
30.4k
  if (!getEvalStatus().Diag || 
!getEvalStatus().Diag->empty()1.92k
) {
46
28.8k
    setActiveDiagnostic(false);
47
28.8k
    return OptionalDiagnostic();
48
28.8k
  }
49
1.64k
  return diag(Loc, DiagId, ExtraNotes, true);
50
1.64k
}
51
52
OptionalDiagnostic State::CCEDiag(const Expr *E, diag::kind DiagId,
53
30.2k
                                  unsigned ExtraNotes) {
54
30.2k
  return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes);
55
30.2k
}
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
2.77M
OptionalDiagnostic State::Note(SourceLocation Loc, diag::kind DiagId) {
63
2.77M
  if (!hasActiveDiagnostic())
64
2.34M
    return OptionalDiagnostic();
65
422k
  return OptionalDiagnostic(&addDiag(Loc, DiagId));
66
422k
}
67
68
79.1k
void State::addNotes(ArrayRef<PartialDiagnosticAt> Diags) {
69
79.1k
  if (hasActiveDiagnostic()) {
70
9.54k
    getEvalStatus().Diag->insert(getEvalStatus().Diag->end(), Diags.begin(),
71
9.54k
                                 Diags.end());
72
9.54k
  }
73
79.1k
}
74
75
43
DiagnosticBuilder State::report(SourceLocation Loc, diag::kind DiagId) {
76
43
  return getCtx().getDiagnostics().Report(Loc, DiagId);
77
43
}
78
79
/// Add a diagnostic to the diagnostics list.
80
895k
PartialDiagnostic &State::addDiag(SourceLocation Loc, diag::kind DiagId) {
81
895k
  PartialDiagnostic PD(DiagId, getCtx().getDiagAllocator());
82
895k
  getEvalStatus().Diag->push_back(std::make_pair(Loc, PD));
83
895k
  return getEvalStatus().Diag->back().second;
84
895k
}
85
86
OptionalDiagnostic State::diag(SourceLocation Loc, diag::kind DiagId,
87
592k
                               unsigned ExtraNotes, bool IsCCEDiag) {
88
592k
  Expr::EvalStatus &EvalStatus = getEvalStatus();
89
592k
  if (EvalStatus.Diag) {
90
472k
    if (hasPriorDiagnostic()) {
91
785
      return OptionalDiagnostic();
92
785
    }
93
471k
94
471k
    unsigned CallStackNotes = getCallStackDepth() - 1;
95
471k
    unsigned Limit = getCtx().getDiagnostics().getConstexprBacktraceLimit();
96
471k
    if (Limit)
97
471k
      CallStackNotes = std::min(CallStackNotes, Limit + 1);
98
471k
    if (checkingPotentialConstantExpression())
99
168
      CallStackNotes = 0;
100
471k
101
471k
    setActiveDiagnostic(true);
102
471k
    setFoldFailureDiagnostic(!IsCCEDiag);
103
471k
    EvalStatus.Diag->clear();
104
471k
    EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes);
105
471k
    addDiag(Loc, DiagId);
106
471k
    if (!checkingPotentialConstantExpression()) {
107
471k
      addCallStack(Limit);
108
471k
    }
109
471k
    return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second);
110
471k
  }
111
120k
  setActiveDiagnostic(false);
112
120k
  return OptionalDiagnostic();
113
120k
}
114
115
12.2M
const LangOptions &State::getLangOpts() const { return getCtx().getLangOpts(); }
116
117
471k
void State::addCallStack(unsigned Limit) {
118
471k
  // Determine which calls to skip, if any.
119
471k
  unsigned ActiveCalls = getCallStackDepth() - 1;
120
471k
  unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart;
121
471k
  if (Limit && 
Limit < ActiveCalls471k
) {
122
7
    SkipStart = Limit / 2 + Limit % 2;
123
7
    SkipEnd = ActiveCalls - Limit / 2;
124
7
  }
125
471k
126
471k
  // Walk the call stack and add the diagnostics.
127
471k
  unsigned CallIdx = 0;
128
471k
  Frame *Top = getCurrentFrame();
129
471k
  const Frame *Bottom = getBottomFrame();
130
472k
  for (Frame *F = Top; F != Bottom; 
F = F->getCaller(), ++CallIdx1.81k
) {
131
1.81k
    SourceLocation CallLocation = F->getCallLocation();
132
1.81k
133
1.81k
    // Skip this call?
134
1.81k
    if (CallIdx >= SkipStart && 
CallIdx < SkipEnd623
) {
135
596
      if (CallIdx == SkipStart) {
136
7
        // Note that we're skipping calls.
137
7
        addDiag(CallLocation, diag::note_constexpr_calls_suppressed)
138
7
            << unsigned(ActiveCalls - Limit);
139
7
      }
140
596
      continue;
141
596
    }
142
1.22k
143
1.22k
    // Use a different note for an inheriting constructor, because from the
144
1.22k
    // user's perspective it's not really a function at all.
145
1.22k
    if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(F->getCallee())) {
146
131
      if (CD->isInheritingConstructor()) {
147
0
        addDiag(CallLocation, diag::note_constexpr_inherited_ctor_call_here)
148
0
            << CD->getParent();
149
0
        continue;
150
0
      }
151
1.22k
    }
152
1.22k
153
1.22k
    SmallVector<char, 128> Buffer;
154
1.22k
    llvm::raw_svector_ostream Out(Buffer);
155
1.22k
    F->describe(Out);
156
1.22k
    addDiag(CallLocation, diag::note_constexpr_call_here) << Out.str();
157
1.22k
  }
158
471k
}