clang  19.0.0git
State.cpp
Go to the documentation of this file.
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"
15 
16 using namespace clang;
17 using namespace clang::interp;
18 
20 
22  unsigned ExtraNotes) {
23  return diag(Loc, DiagId, ExtraNotes, false);
24 }
25 
27  unsigned ExtraNotes) {
28  if (getEvalStatus().Diag)
29  return diag(E->getExprLoc(), DiagId, ExtraNotes, false);
30  setActiveDiagnostic(false);
31  return OptionalDiagnostic();
32 }
33 
35  unsigned ExtraNotes) {
36  if (getEvalStatus().Diag)
37  return diag(SI.getLoc(), DiagId, ExtraNotes, false);
38  setActiveDiagnostic(false);
39  return OptionalDiagnostic();
40 }
41 
43  unsigned ExtraNotes) {
44  // Don't override a previous diagnostic. Don't bother collecting
45  // diagnostics if we're evaluating for overflow.
46  if (!getEvalStatus().Diag || !getEvalStatus().Diag->empty()) {
47  setActiveDiagnostic(false);
48  return OptionalDiagnostic();
49  }
50  return diag(Loc, DiagId, ExtraNotes, true);
51 }
52 
54  unsigned ExtraNotes) {
55  return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes);
56 }
57 
59  unsigned ExtraNotes) {
60  return CCEDiag(SI.getLoc(), DiagId, ExtraNotes);
61 }
62 
64  if (!hasActiveDiagnostic())
65  return OptionalDiagnostic();
66  return OptionalDiagnostic(&addDiag(Loc, DiagId));
67 }
68 
70  if (hasActiveDiagnostic()) {
71  getEvalStatus().Diag->insert(getEvalStatus().Diag->end(), Diags.begin(),
72  Diags.end());
73  }
74 }
75 
77  return getCtx().getDiagnostics().Report(Loc, DiagId);
78 }
79 
80 /// Add a diagnostic to the diagnostics list.
81 PartialDiagnostic &State::addDiag(SourceLocation Loc, diag::kind DiagId) {
82  PartialDiagnostic PD(DiagId, getCtx().getDiagAllocator());
83  getEvalStatus().Diag->push_back(std::make_pair(Loc, PD));
84  return getEvalStatus().Diag->back().second;
85 }
86 
88  unsigned ExtraNotes, bool IsCCEDiag) {
89  Expr::EvalStatus &EvalStatus = getEvalStatus();
90  if (EvalStatus.Diag) {
91  if (hasPriorDiagnostic()) {
92  return OptionalDiagnostic();
93  }
94 
95  unsigned CallStackNotes = getCallStackDepth() - 1;
96  unsigned Limit = getCtx().getDiagnostics().getConstexprBacktraceLimit();
97  if (Limit)
98  CallStackNotes = std::min(CallStackNotes, Limit + 1);
100  CallStackNotes = 0;
101 
102  setActiveDiagnostic(true);
103  setFoldFailureDiagnostic(!IsCCEDiag);
104  EvalStatus.Diag->clear();
105  EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes);
106  addDiag(Loc, DiagId);
108  addCallStack(Limit);
109  }
110  return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second);
111  }
112  setActiveDiagnostic(false);
113  return OptionalDiagnostic();
114 }
115 
116 const LangOptions &State::getLangOpts() const { return getCtx().getLangOpts(); }
117 
118 void State::addCallStack(unsigned Limit) {
119  // Determine which calls to skip, if any.
120  unsigned ActiveCalls = getCallStackDepth() - 1;
121  unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart;
122  if (Limit && Limit < ActiveCalls) {
123  SkipStart = Limit / 2 + Limit % 2;
124  SkipEnd = ActiveCalls - Limit / 2;
125  }
126 
127  // Walk the call stack and add the diagnostics.
128  unsigned CallIdx = 0;
129  const Frame *Top = getCurrentFrame();
130  const Frame *Bottom = getBottomFrame();
131  for (const Frame *F = Top; F != Bottom; F = F->getCaller(), ++CallIdx) {
132  SourceRange CallRange = F->getCallRange();
133 
134  // Skip this call?
135  if (CallIdx >= SkipStart && CallIdx < SkipEnd) {
136  if (CallIdx == SkipStart) {
137  // Note that we're skipping calls.
138  addDiag(CallRange.getBegin(), diag::note_constexpr_calls_suppressed)
139  << unsigned(ActiveCalls - Limit);
140  }
141  continue;
142  }
143 
144  // Use a different note for an inheriting constructor, because from the
145  // user's perspective it's not really a function at all.
146  if (const auto *CD =
147  dyn_cast_if_present<CXXConstructorDecl>(F->getCallee());
148  CD && CD->isInheritingConstructor()) {
149  addDiag(CallRange.getBegin(),
150  diag::note_constexpr_inherited_ctor_call_here)
151  << CD->getParent();
152  continue;
153  }
154 
155  SmallString<128> Buffer;
156  llvm::raw_svector_ostream Out(Buffer);
157  F->describe(Out);
158  if (!Buffer.empty())
159  addDiag(CallRange.getBegin(), diag::note_constexpr_call_here)
160  << Out.str() << CallRange;
161  }
162 }
Defines the clang::ASTContext interface.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Implements a partial diagnostic which may not be emitted.
SourceLocation Loc
Definition: SemaObjC.cpp:755
__DEVICE__ int min(int __a, int __b)
const LangOptions & getLangOpts() const
Definition: ASTContext.h:778
DiagnosticsEngine & getDiagnostics() const
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1277
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1553
unsigned getConstexprBacktraceLimit() const
Retrieve the maximum number of constexpr evaluation notes to emit along with a given diagnostic.
Definition: Diagnostic.h:649
This represents one expression.
Definition: Expr.h:110
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:482
A partial diagnostic which we might know in advance that we are not going to emit.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
Base class for stack frames, shared between VM and walker.
Definition: Frame.h:25
virtual Frame * getCaller() const =0
Returns a pointer to the caller frame.
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:72
SourceLocation getLoc() const
Definition: Source.cpp:15
virtual Frame * getCurrentFrame()=0
virtual bool hasActiveDiagnostic()=0
virtual void setActiveDiagnostic(bool Flag)=0
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
Definition: State.cpp:63
virtual bool checkingPotentialConstantExpression() const =0
DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId)
Directly reports a diagnostic message.
Definition: State.cpp:76
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Definition: State.cpp:21
virtual unsigned getCallStackDepth()=0
virtual const Frame * getBottomFrame() const =0
virtual ASTContext & getCtx() const =0
void addNotes(ArrayRef< PartialDiagnosticAt > Diags)
Add a stack of notes to a prior diagnostic.
Definition: State.cpp:69
const LangOptions & getLangOpts() const
Definition: State.cpp:116
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
Definition: State.cpp:42
virtual void setFoldFailureDiagnostic(bool Flag)=0
virtual bool hasPriorDiagnostic()=0
virtual Expr::EvalStatus & getEvalStatus() const =0
virtual ~State()
Definition: State.cpp:19
The JSON file list parser is used to communicate input to InstallAPI.
EvalStatus is a struct with detailed info about an evaluation in progress.
Definition: Expr.h:606
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition: Expr.h:630