Tyker updated this revision to Diff 195055.
Tyker added a comment.

i changed the way arguments are stored. to make it more controllable.
added an argument call stack where it is needed.
this version slows down compilation by around 0.5% in average over 200 run for 
SemaDecl -fsyntax-only


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60561/new/

https://reviews.llvm.org/D60561

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/test/SemaCXX/constant-expression-cxx1y.cpp

Index: clang/test/SemaCXX/constant-expression-cxx1y.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx1y.cpp
+++ clang/test/SemaCXX/constant-expression-cxx1y.cpp
@@ -1159,3 +1159,32 @@
 enum class InEnum3 {
   THREE = indirect_builtin_constant_p("abc")
 };
+
+constexpr int f1(int i, int b) {
+  i += 4;
+  b -= 4;
+  // expected-note@+1 {{negative shift count -7}}
+  return i << b;
+}
+
+constexpr int f2(int i) {
+  int b = 0;
+  i += 1;
+  b -= 1;
+  // expected-note@+1 {{in call to 'f1(3, -3)'}}
+  return f1(i + 2, b -= 2);
+}
+
+constexpr int f(int i) {
+  i -= 1;
+  //expected-note@+1 {{negative shift count -1}}
+  return 1 << i;
+}
+
+// expected-error@+2 {{constant expression}}
+// expected-note@+1 {{in call to 'f2(0)'}}
+constexpr int val = f2(0);
+
+// expected-error@+2 {{constant expression}}
+// expected-note@+1 {{in call to 'f(0)'}}
+static_assert(f(0), "");
\ No newline at end of file
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -661,6 +661,10 @@
     /// CurrentCall - The top of the constexpr call stack.
     CallStackFrame *CurrentCall;
 
+    /// ArgumentCallStack - Used to store Arguments to function calls
+    /// only required if diagnostics should produce a callstack
+    SmallVectorImpl<APValue> *ArgumentCallStack;
+
     /// CallStackDepth - The number of calls in the call stack right now.
     unsigned CallStackDepth;
 
@@ -789,14 +793,14 @@
     bool checkingForOverflow() { return EvalMode == EM_EvaluateForOverflow; }
 
     EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode)
-      : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr),
-        CallStackDepth(0), NextCallIndex(1),
-        StepsLeft(getLangOpts().ConstexprStepLimit),
-        BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
-        EvaluatingDecl((const ValueDecl *)nullptr),
-        EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
-        HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false),
-        InConstantContext(false), EvalMode(Mode) {}
+        : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr),
+          ArgumentCallStack(nullptr), CallStackDepth(0), NextCallIndex(1),
+          StepsLeft(getLangOpts().ConstexprStepLimit),
+          BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
+          EvaluatingDecl((const ValueDecl *)nullptr),
+          EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
+          HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false),
+          InConstantContext(false), EvalMode(Mode) {}
 
     void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
       EvaluatingDecl = Base;
@@ -1240,10 +1244,20 @@
       Arguments(Arguments), CallLoc(CallLoc), Index(Info.NextCallIndex++) {
   Info.CurrentCall = this;
   ++Info.CallStackDepth;
+  if (Info.ArgumentCallStack) {
+    Info.ArgumentCallStack->reserve(Info.ArgumentCallStack->size() +
+                                    Callee->param_size());
+    std::copy(Arguments, Arguments + Callee->param_size(),
+              std::back_inserter(*Info.ArgumentCallStack));
+  }
 }
 
 CallStackFrame::~CallStackFrame() {
   assert(Info.CurrentCall == this && "calls retired out of order");
+  if (Info.ArgumentCallStack && Caller) {
+    Info.ArgumentCallStack->resize(Info.ArgumentCallStack->size() -
+                                   Callee->param_size());
+  }
   --Info.CallStackDepth;
   Info.CurrentCall = Caller;
 }
@@ -1257,9 +1271,12 @@
   return Result;
 }
 
-static void describeCall(CallStackFrame *Frame, raw_ostream &Out);
+static void describeCall(CallStackFrame *Frame, raw_ostream &Out,
+                         SmallVectorImpl<APValue> *ArgumentCallStack,
+                         unsigned &Pos);
 
 void EvalInfo::addCallStack(unsigned Limit) {
+  assert(ArgumentCallStack && "needed to produce a call stack");
   // Determine which calls to skip, if any.
   unsigned ActiveCalls = CallStackDepth - 1;
   unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart;
@@ -1270,8 +1287,10 @@
 
   // Walk the call stack and add the diagnostics.
   unsigned CallIdx = 0;
+  unsigned Pos = ArgumentCallStack->size();
   for (CallStackFrame *Frame = CurrentCall; Frame != &BottomFrame;
        Frame = Frame->Caller, ++CallIdx) {
+    Pos -= Frame->Callee->param_size();
     // Skip this call?
     if (CallIdx >= SkipStart && CallIdx < SkipEnd) {
       if (CallIdx == SkipStart) {
@@ -1294,7 +1313,7 @@
 
     SmallVector<char, 128> Buffer;
     llvm::raw_svector_ostream Out(Buffer);
-    describeCall(Frame, Out);
+    describeCall(Frame, Out, ArgumentCallStack, Pos);
     addDiag(Frame->CallLoc, diag::note_constexpr_call_here) << Out.str();
   }
 }
@@ -1654,7 +1673,9 @@
 }
 
 /// Produce a string describing the given constexpr call.
-static void describeCall(CallStackFrame *Frame, raw_ostream &Out) {
+static void describeCall(CallStackFrame *Frame, raw_ostream &Out,
+                         SmallVectorImpl<APValue> *ArgumentCallStack,
+                         unsigned &Pos) {
   unsigned ArgIndex = 0;
   bool IsMemberCall = isa<CXXMethodDecl>(Frame->Callee) &&
                       !isa<CXXConstructorDecl>(Frame->Callee) &&
@@ -1679,7 +1700,7 @@
       Out << ", ";
 
     const ParmVarDecl *Param = *I;
-    const APValue &Arg = Frame->Arguments[ArgIndex];
+    const APValue &Arg = (*ArgumentCallStack)[Pos + ArgIndex];
     Arg.printPretty(Out, Frame->Info.Ctx, Param->getType());
 
     if (ArgIndex == 0 && IsMemberCall)
@@ -11076,6 +11097,8 @@
 bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
                             bool InConstantContext) const {
   EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
+  SmallVector<APValue, 24> ArgumentCallStack;
+  Info.ArgumentCallStack = &ArgumentCallStack;
   Info.InConstantContext = InConstantContext;
   return ::EvaluateAsRValue(this, Result, Ctx, Info);
 }
@@ -11115,7 +11138,6 @@
 
 bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const {
   EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold);
-
   LValue LV;
   if (!EvaluateLValue(this, LV, Info) || Result.HasSideEffects ||
       !CheckLValueConstantExpression(Info, getExprLoc(),
@@ -11131,6 +11153,8 @@
                                   const ASTContext &Ctx) const {
   EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression;
   EvalInfo Info(Ctx, Result, EM);
+  SmallVector<APValue, 24> ArgumentCallStack;
+  Info.ArgumentCallStack = &ArgumentCallStack;
   Info.InConstantContext = true;
   if (!::Evaluate(Result.Val, Info, this))
     return false;
@@ -11156,7 +11180,8 @@
                                       : EvalInfo::EM_ConstantFold);
   InitInfo.setEvaluatingDecl(VD, Value);
   InitInfo.InConstantContext = true;
-
+  SmallVector<APValue, 8> ArgumentCallStack;
+  InitInfo.ArgumentCallStack = &ArgumentCallStack;
   LValue LVal;
   LVal.set(VD);
 
@@ -11751,6 +11776,8 @@
   SmallVector<PartialDiagnosticAt, 8> Diags;
   Status.Diag = &Diags;
   EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression);
+  SmallVector<APValue, 24> ArgumentCallStack;
+  Info.ArgumentCallStack = &ArgumentCallStack;
 
   APValue Scratch;
   bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to