State.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. #include "State.h"
  9. #include "Frame.h"
  10. #include "Program.h"
  11. #include "clang/AST/ASTContext.h"
  12. #include "clang/AST/CXXInheritance.h"
  13. using namespace clang;
  14. using namespace clang::interp;
  15. State::~State() {}
  16. OptionalDiagnostic State::FFDiag(SourceLocation Loc, diag::kind DiagId,
  17. unsigned ExtraNotes) {
  18. return diag(Loc, DiagId, ExtraNotes, false);
  19. }
  20. OptionalDiagnostic State::FFDiag(const Expr *E, diag::kind DiagId,
  21. unsigned ExtraNotes) {
  22. if (getEvalStatus().Diag)
  23. return diag(E->getExprLoc(), DiagId, ExtraNotes, false);
  24. setActiveDiagnostic(false);
  25. return OptionalDiagnostic();
  26. }
  27. OptionalDiagnostic State::FFDiag(const SourceInfo &SI, diag::kind DiagId,
  28. unsigned ExtraNotes) {
  29. if (getEvalStatus().Diag)
  30. return diag(SI.getLoc(), DiagId, ExtraNotes, false);
  31. setActiveDiagnostic(false);
  32. return OptionalDiagnostic();
  33. }
  34. OptionalDiagnostic State::CCEDiag(SourceLocation Loc, diag::kind DiagId,
  35. unsigned ExtraNotes) {
  36. // Don't override a previous diagnostic. Don't bother collecting
  37. // diagnostics if we're evaluating for overflow.
  38. if (!getEvalStatus().Diag || !getEvalStatus().Diag->empty()) {
  39. setActiveDiagnostic(false);
  40. return OptionalDiagnostic();
  41. }
  42. return diag(Loc, DiagId, ExtraNotes, true);
  43. }
  44. OptionalDiagnostic State::CCEDiag(const Expr *E, diag::kind DiagId,
  45. unsigned ExtraNotes) {
  46. return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes);
  47. }
  48. OptionalDiagnostic State::CCEDiag(const SourceInfo &SI, diag::kind DiagId,
  49. unsigned ExtraNotes) {
  50. return CCEDiag(SI.getLoc(), DiagId, ExtraNotes);
  51. }
  52. OptionalDiagnostic State::Note(SourceLocation Loc, diag::kind DiagId) {
  53. if (!hasActiveDiagnostic())
  54. return OptionalDiagnostic();
  55. return OptionalDiagnostic(&addDiag(Loc, DiagId));
  56. }
  57. void State::addNotes(ArrayRef<PartialDiagnosticAt> Diags) {
  58. if (hasActiveDiagnostic()) {
  59. getEvalStatus().Diag->insert(getEvalStatus().Diag->end(), Diags.begin(),
  60. Diags.end());
  61. }
  62. }
  63. DiagnosticBuilder State::report(SourceLocation Loc, diag::kind DiagId) {
  64. return getCtx().getDiagnostics().Report(Loc, DiagId);
  65. }
  66. /// Add a diagnostic to the diagnostics list.
  67. PartialDiagnostic &State::addDiag(SourceLocation Loc, diag::kind DiagId) {
  68. PartialDiagnostic PD(DiagId, getCtx().getDiagAllocator());
  69. getEvalStatus().Diag->push_back(std::make_pair(Loc, PD));
  70. return getEvalStatus().Diag->back().second;
  71. }
  72. OptionalDiagnostic State::diag(SourceLocation Loc, diag::kind DiagId,
  73. unsigned ExtraNotes, bool IsCCEDiag) {
  74. Expr::EvalStatus &EvalStatus = getEvalStatus();
  75. if (EvalStatus.Diag) {
  76. if (hasPriorDiagnostic()) {
  77. return OptionalDiagnostic();
  78. }
  79. unsigned CallStackNotes = getCallStackDepth() - 1;
  80. unsigned Limit = getCtx().getDiagnostics().getConstexprBacktraceLimit();
  81. if (Limit)
  82. CallStackNotes = std::min(CallStackNotes, Limit + 1);
  83. if (checkingPotentialConstantExpression())
  84. CallStackNotes = 0;
  85. setActiveDiagnostic(true);
  86. setFoldFailureDiagnostic(!IsCCEDiag);
  87. EvalStatus.Diag->clear();
  88. EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes);
  89. addDiag(Loc, DiagId);
  90. if (!checkingPotentialConstantExpression()) {
  91. addCallStack(Limit);
  92. }
  93. return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second);
  94. }
  95. setActiveDiagnostic(false);
  96. return OptionalDiagnostic();
  97. }
  98. const LangOptions &State::getLangOpts() const { return getCtx().getLangOpts(); }
  99. void State::addCallStack(unsigned Limit) {
  100. // Determine which calls to skip, if any.
  101. unsigned ActiveCalls = getCallStackDepth() - 1;
  102. unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart;
  103. if (Limit && Limit < ActiveCalls) {
  104. SkipStart = Limit / 2 + Limit % 2;
  105. SkipEnd = ActiveCalls - Limit / 2;
  106. }
  107. // Walk the call stack and add the diagnostics.
  108. unsigned CallIdx = 0;
  109. Frame *Top = getCurrentFrame();
  110. const Frame *Bottom = getBottomFrame();
  111. for (Frame *F = Top; F != Bottom; F = F->getCaller(), ++CallIdx) {
  112. SourceLocation CallLocation = F->getCallLocation();
  113. // Skip this call?
  114. if (CallIdx >= SkipStart && CallIdx < SkipEnd) {
  115. if (CallIdx == SkipStart) {
  116. // Note that we're skipping calls.
  117. addDiag(CallLocation, diag::note_constexpr_calls_suppressed)
  118. << unsigned(ActiveCalls - Limit);
  119. }
  120. continue;
  121. }
  122. // Use a different note for an inheriting constructor, because from the
  123. // user's perspective it's not really a function at all.
  124. if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(F->getCallee())) {
  125. if (CD->isInheritingConstructor()) {
  126. addDiag(CallLocation, diag::note_constexpr_inherited_ctor_call_here)
  127. << CD->getParent();
  128. continue;
  129. }
  130. }
  131. SmallString<128> Buffer;
  132. llvm::raw_svector_ostream Out(Buffer);
  133. F->describe(Out);
  134. addDiag(CallLocation, diag::note_constexpr_call_here) << Out.str();
  135. }
  136. }