[clang] 69f7c00 - Revert "PR47805: Use a single object for a function parameter in the caller and"

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 13 19:32:17 PDT 2020


Author: Richard Smith
Date: 2020-10-13T19:32:03-07:00
New Revision: 69f7c006ff72167231b569a0fd2d7955ca597ffa

URL: https://github.com/llvm/llvm-project/commit/69f7c006ff72167231b569a0fd2d7955ca597ffa
DIFF: https://github.com/llvm/llvm-project/commit/69f7c006ff72167231b569a0fd2d7955ca597ffa.diff

LOG: Revert "PR47805: Use a single object for a function parameter in the caller and"

Breaks a clangd unit test.

This reverts commit 8f8b9f2cca0b73314342c721186ae9c860ca273c.

Added: 
    

Modified: 
    clang/lib/AST/ExprConstant.cpp
    clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
    clang/test/CXX/except/except.spec/p1.cpp
    clang/test/CXX/expr/expr.const/p2-0x.cpp
    clang/test/OpenMP/critical_messages.cpp
    clang/test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp
    clang/test/OpenMP/distribute_simd_safelen_messages.cpp
    clang/test/OpenMP/distribute_simd_simdlen_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp
    clang/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp
    clang/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp
    clang/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp
    clang/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp
    clang/test/OpenMP/teams_distribute_simd_safelen_messages.cpp
    clang/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp
    clang/test/Sema/builtin-expect-with-probability-avr.cpp
    clang/test/Sema/builtin-expect-with-probability.cpp
    clang/test/Sema/c89.c
    clang/test/SemaCUDA/constexpr-variables.cu
    clang/test/SemaCXX/c99-variable-length-array-cxx11.cpp
    clang/test/SemaCXX/c99-variable-length-array.cpp
    clang/test/SemaCXX/constant-expression-cxx11.cpp
    clang/test/SemaCXX/constant-expression-cxx2a.cpp
    clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
    clang/test/SemaCXX/cxx2a-consteval.cpp
    clang/test/SemaCXX/integer-overflow.cpp
    clang/test/SemaCXX/vla-construct.cpp
    clang/test/SemaCXX/warn-vla.cpp
    clang/test/SemaTemplate/typo-dependent-name.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 74ec7040564f..1327aa6876e4 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -490,39 +490,6 @@ namespace {
     }
   };
 
-  /// A scope at the end of which an object can need to be destroyed.
-  enum class ScopeKind {
-    Block,
-    FullExpression,
-    Call
-  };
-
-  /// A reference to a particular call and its arguments.
-  struct CallRef {
-    CallRef() : OrigCallee(), CallIndex(0), Version() {}
-    CallRef(const FunctionDecl *Callee, unsigned CallIndex, unsigned Version)
-        : OrigCallee(Callee), CallIndex(CallIndex), Version(Version) {}
-
-    explicit operator bool() const { return OrigCallee; }
-
-    /// Get the parameter that the caller initialized, corresponding to the
-    /// given parameter in the callee.
-    const ParmVarDecl *getOrigParam(const ParmVarDecl *PVD) const {
-      return OrigCallee ? OrigCallee->getParamDecl(PVD->getFunctionScopeIndex())
-                        : PVD;
-    }
-
-    /// The callee at the point where the arguments were evaluated. This might
-    /// be 
diff erent from the actual callee (a 
diff erent redeclaration, or a
-    /// virtual override), but this function's parameters are the ones that
-    /// appear in the parameter map.
-    const FunctionDecl *OrigCallee;
-    /// The call index of the frame that holds the argument values.
-    unsigned CallIndex;
-    /// The version of the parameters corresponding to this call.
-    unsigned Version;
-  };
-
   /// A stack frame in the constexpr call stack.
   class CallStackFrame : public interp::Frame {
   public:
@@ -537,10 +504,9 @@ namespace {
     /// This - The binding for the this pointer in this call, if any.
     const LValue *This;
 
-    /// Information on how to find the arguments to this call. Our arguments
-    /// are stored in our parent's CallStackFrame, using the ParmVarDecl* as a
-    /// key and this value as the version.
-    CallRef Arguments;
+    /// Arguments - Parameter bindings for this function call, indexed by
+    /// parameters' function scope indices.
+    APValue *Arguments;
 
     /// Source location information about the default argument or default
     /// initializer expression we're evaluating, if any.
@@ -573,10 +539,6 @@ namespace {
       TempVersionStack.pop_back();
     }
 
-    CallRef createCall(const FunctionDecl *Callee) {
-      return {Callee, Index, ++CurTempVersion};
-    }
-
     // FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact
     // on the overall stack usage of deeply-recursing constexpr evaluations.
     // (We should cache this map rather than recomputing it repeatedly.)
@@ -590,7 +552,7 @@ namespace {
 
     CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
                    const FunctionDecl *Callee, const LValue *This,
-                   CallRef Arguments);
+                   APValue *Arguments);
     ~CallStackFrame();
 
     // Return the temporary for Key whose version number is Version.
@@ -629,10 +591,7 @@ namespace {
     /// bumping the temporary version number.
     template<typename KeyT>
     APValue &createTemporary(const KeyT *Key, QualType T,
-                             ScopeKind Scope, LValue &LV);
-
-    /// Allocate storage for a parameter of a function call made in this frame.
-    APValue &createParam(CallRef Args, const ParmVarDecl *PVD, LValue &LV);
+                             bool IsLifetimeExtended, LValue &LV);
 
     void describe(llvm::raw_ostream &OS) override;
 
@@ -646,10 +605,6 @@ namespace {
           return true;
       return false;
     }
-
-  private:
-    APValue &createLocal(APValue::LValueBase Base, const void *Key, QualType T,
-                         ScopeKind Scope);
   };
 
   /// Temporarily override 'this'.
@@ -678,20 +633,16 @@ static bool HandleDestruction(EvalInfo &Info, SourceLocation Loc,
 namespace {
   /// A cleanup, and a flag indicating whether it is lifetime-extended.
   class Cleanup {
-    llvm::PointerIntPair<APValue*, 2, ScopeKind> Value;
+    llvm::PointerIntPair<APValue*, 1, bool> Value;
     APValue::LValueBase Base;
     QualType T;
 
   public:
     Cleanup(APValue *Val, APValue::LValueBase Base, QualType T,
-            ScopeKind Scope)
-        : Value(Val, Scope), Base(Base), T(T) {}
+            bool IsLifetimeExtended)
+        : Value(Val, IsLifetimeExtended), Base(Base), T(T) {}
 
-    /// Determine whether this cleanup should be performed at the end of the
-    /// given kind of scope.
-    bool isDestroyedAtEndOf(ScopeKind K) const {
-      return (int)Value.getInt() >= (int)K;
-    }
+    bool isLifetimeExtended() const { return Value.getInt(); }
     bool endLifetime(EvalInfo &Info, bool RunDestructors) {
       if (RunDestructors) {
         SourceLocation Loc;
@@ -977,7 +928,7 @@ namespace {
           CallStackDepth(0), NextCallIndex(1),
           StepsLeft(C.getLangOpts().ConstexprStepLimit),
           EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp),
-          BottomFrame(*this, SourceLocation(), nullptr, nullptr, CallRef()),
+          BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
           EvaluatingDecl((const ValueDecl *)nullptr),
           EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
           HasFoldFailureDiagnostic(false), InConstantContext(false),
@@ -1046,13 +997,6 @@ namespace {
       return Result;
     }
 
-    /// Get the allocated storage for the given parameter of the given call.
-    APValue *getParamSlot(CallRef Call, const ParmVarDecl *PVD) {
-      CallStackFrame *Frame = getCallFrameAndDepth(Call.CallIndex).first;
-      return Frame ? Frame->getTemporary(Call.getOrigParam(PVD), Call.Version)
-                   : nullptr;
-    }
-
     /// Information about a stack frame for std::allocator<T>::[de]allocate.
     struct StdAllocatorCaller {
       unsigned FrameIndex;
@@ -1088,13 +1032,10 @@ namespace {
 
     void performLifetimeExtension() {
       // Disable the cleanups for lifetime-extended temporaries.
-      CleanupStack.erase(std::remove_if(CleanupStack.begin(),
-                                        CleanupStack.end(),
-                                        [](Cleanup &C) {
-                                          return !C.isDestroyedAtEndOf(
-                                              ScopeKind::FullExpression);
-                                        }),
-                         CleanupStack.end());
+      CleanupStack.erase(
+          std::remove_if(CleanupStack.begin(), CleanupStack.end(),
+                         [](Cleanup &C) { return C.isLifetimeExtended(); }),
+          CleanupStack.end());
      }
 
     /// Throw away any remaining cleanups at the end of evaluation. If any
@@ -1343,7 +1284,7 @@ namespace {
 
   /// RAII object wrapping a full-expression or block scope, and handling
   /// the ending of the lifetime of temporaries created within it.
-  template<ScopeKind Kind>
+  template<bool IsFullExpression>
   class ScopeRAII {
     EvalInfo &Info;
     unsigned OldStackSize;
@@ -1376,7 +1317,8 @@ namespace {
       // for a full-expression scope.
       bool Success = true;
       for (unsigned I = Info.CleanupStack.size(); I > OldStackSize; --I) {
-        if (Info.CleanupStack[I - 1].isDestroyedAtEndOf(Kind)) {
+        if (!(IsFullExpression &&
+              Info.CleanupStack[I - 1].isLifetimeExtended())) {
           if (!Info.CleanupStack[I - 1].endLifetime(Info, RunDestructors)) {
             Success = false;
             break;
@@ -1384,20 +1326,18 @@ namespace {
         }
       }
 
-      // Compact any retained cleanups.
+      // Compact lifetime-extended cleanups.
       auto NewEnd = Info.CleanupStack.begin() + OldStackSize;
-      if (Kind != ScopeKind::Block)
+      if (IsFullExpression)
         NewEnd =
-            std::remove_if(NewEnd, Info.CleanupStack.end(), [](Cleanup &C) {
-              return C.isDestroyedAtEndOf(Kind);
-            });
+            std::remove_if(NewEnd, Info.CleanupStack.end(),
+                           [](Cleanup &C) { return !C.isLifetimeExtended(); });
       Info.CleanupStack.erase(NewEnd, Info.CleanupStack.end());
       return Success;
     }
   };
-  typedef ScopeRAII<ScopeKind::Block> BlockScopeRAII;
-  typedef ScopeRAII<ScopeKind::FullExpression> FullExpressionRAII;
-  typedef ScopeRAII<ScopeKind::Call> CallScopeRAII;
+  typedef ScopeRAII<false> BlockScopeRAII;
+  typedef ScopeRAII<true> FullExpressionRAII;
 }
 
 bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E,
@@ -1440,9 +1380,9 @@ void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
 
 CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
                                const FunctionDecl *Callee, const LValue *This,
-                               CallRef Call)
+                               APValue *Arguments)
     : Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This),
-      Arguments(Call), CallLoc(CallLoc), Index(Info.NextCallIndex++) {
+      Arguments(Arguments), CallLoc(CallLoc), Index(Info.NextCallIndex++) {
   Info.CurrentCall = this;
   ++Info.CallStackDepth;
 }
@@ -1855,33 +1795,14 @@ static void negateAsSigned(APSInt &Int) {
 
 template<typename KeyT>
 APValue &CallStackFrame::createTemporary(const KeyT *Key, QualType T,
-                                         ScopeKind Scope, LValue &LV) {
+                                         bool IsLifetimeExtended, LValue &LV) {
   unsigned Version = getTempVersion();
   APValue::LValueBase Base(Key, Index, Version);
   LV.set(Base);
-  return createLocal(Base, Key, T, Scope);
-}
-
-/// Allocate storage for a parameter of a function call made in this frame.
-APValue &CallStackFrame::createParam(CallRef Args, const ParmVarDecl *PVD,
-                                     LValue &LV) {
-  assert(Args.CallIndex == Index && "creating parameter in wrong frame");
-  APValue::LValueBase Base(PVD, Index, Args.Version);
-  LV.set(Base);
-  // We always destroy parameters at the end of the call, even if we'd allow
-  // them to live to the end of the full-expression at runtime, in order to
-  // give portable results and match other compilers.
-  return createLocal(Base, PVD, PVD->getType(), ScopeKind::Call);
-}
-
-APValue &CallStackFrame::createLocal(APValue::LValueBase Base, const void *Key,
-                                     QualType T, ScopeKind Scope) {
-  assert(Base.getCallIndex() == Index && "lvalue for wrong frame");
-  unsigned Version = Base.getVersion();
   APValue &Result = Temporaries[MapKeyTy(Key, Version)];
-  assert(Result.isAbsent() && "local created multiple times");
+  assert(Result.isAbsent() && "temporary created multiple times");
 
-  // If we're creating a local immediately in the operand of a speculative
+  // If we're creating a temporary immediately in the operand of a speculative
   // evaluation, don't register a cleanup to be run outside the speculative
   // evaluation context, since we won't actually be able to initialize this
   // object.
@@ -1889,7 +1810,7 @@ APValue &CallStackFrame::createLocal(APValue::LValueBase Base, const void *Key,
     if (T.isDestructedType())
       Info.noteSideEffect();
   } else {
-    Info.CleanupStack.push_back(Cleanup(&Result, Base, T, Scope));
+    Info.CleanupStack.push_back(Cleanup(&Result, Base, T, IsLifetimeExtended));
   }
   return Result;
 }
@@ -1935,11 +1856,12 @@ void CallStackFrame::describe(raw_ostream &Out) {
       Out << ", ";
 
     const ParmVarDecl *Param = *I;
-    APValue *V = Info.getParamSlot(Arguments, Param);
-    if (V)
-      V->printPretty(Out, Info.Ctx, Param->getType());
-    else
+    if (Arguments) {
+      const APValue &Arg = Arguments[ArgIndex];
+      Arg.printPretty(Out, Info.Ctx, Param->getType());
+    } else {
       Out << "<...>";
+    }
 
     if (ArgIndex == 0 && IsMemberCall)
       Out << "->" << *Callee << '(';
@@ -2070,22 +1992,6 @@ static bool HasSameBase(const LValue &A, const LValue &B) {
 static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) {
   assert(Base && "no location for a null lvalue");
   const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>();
-
-  // For a parameter, find the corresponding call stack frame (if it still
-  // exists), and point at the parameter of the function definition we actually
-  // invoked.
-  if (auto *PVD = dyn_cast_or_null<ParmVarDecl>(VD)) {
-    unsigned Idx = PVD->getFunctionScopeIndex();
-    for (CallStackFrame *F = Info.CurrentCall; F; F = F->Caller) {
-      if (F->Arguments.CallIndex == Base.getCallIndex() &&
-          F->Arguments.Version == Base.getVersion() && F->Callee &&
-          Idx < F->Callee->getNumParams()) {
-        VD = F->Callee->getParamDecl(Idx);
-        break;
-      }
-    }
-  }
-
   if (VD)
     Info.Note(VD->getLocation(), diag::note_declared_at);
   else if (const Expr *E = Base.dyn_cast<const Expr*>())
@@ -3171,22 +3077,33 @@ static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E,
 /// \param Info   Information about the ongoing evaluation.
 /// \param E      An expression to be used when printing diagnostics.
 /// \param VD     The variable whose initializer should be obtained.
-/// \param Version The version of the variable within the frame.
 /// \param Frame  The frame in which the variable was created. Must be null
 ///               if this variable is not local to the evaluation.
 /// \param Result Filled in with a pointer to the value of the variable.
 static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
                                 const VarDecl *VD, CallStackFrame *Frame,
-                                unsigned Version, APValue *&Result) {
-  APValue::LValueBase Base(VD, Frame ? Frame->Index : 0, Version);
+                                APValue *&Result, const LValue *LVal) {
+
+  // If this is a parameter to an active constexpr function call, perform
+  // argument substitution.
+  if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD)) {
+    // Assume arguments of a potential constant expression are unknown
+    // constant expressions.
+    if (Info.checkingPotentialConstantExpression())
+      return false;
+    if (!Frame || !Frame->Arguments) {
+      Info.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << VD;
+      return false;
+    }
+    Result = &Frame->Arguments[PVD->getFunctionScopeIndex()];
+    return true;
+  }
 
   // If this is a local variable, dig out its value.
   if (Frame) {
-    Result = Frame->getTemporary(VD, Version);
-    if (Result)
-      return true;
-
-    if (!isa<ParmVarDecl>(VD)) {
+    Result = LVal ? Frame->getTemporary(VD, LVal->getLValueVersion())
+                  : Frame->getCurrentTemporary(VD);
+    if (!Result) {
       // Assume variables referenced within a lambda's call operator that were
       // not declared within the call operator are captures and during checking
       // of a potential constant expression, assume they are unknown constant
@@ -3196,30 +3113,13 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
              "missing value for local variable");
       if (Info.checkingPotentialConstantExpression())
         return false;
-      // FIXME: This diagnostic is bogus; we do support captures. Is this code
-      // still reachable at all?
+      // FIXME: implement capture evaluation during constant expr evaluation.
       Info.FFDiag(E->getBeginLoc(),
                   diag::note_unimplemented_constexpr_lambda_feature_ast)
           << "captures not currently allowed";
       return false;
     }
-  }
-
-  if (isa<ParmVarDecl>(VD)) {
-    // Assume parameters of a potential constant expression are usable in
-    // constant expressions.
-    if (!Info.checkingPotentialConstantExpression() ||
-        !Info.CurrentCall->Callee ||
-        !Info.CurrentCall->Callee->Equals(VD->getDeclContext())) {
-      if (Info.getLangOpts().CPlusPlus11) {
-        Info.FFDiag(E, diag::note_constexpr_function_param_value_unknown)
-            << VD;
-        NoteLValueLocation(Info, Base);
-      } else {
-        Info.FFDiag(E);
-      }
-    }
-    return false;
+    return true;
   }
 
   // Dig out the initializer, and use the declaration which it's attached to.
@@ -3232,7 +3132,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
     if (!Info.checkingPotentialConstantExpression()) {
       Info.FFDiag(E, diag::note_constexpr_var_init_unknown, 1)
         << VD;
-      NoteLValueLocation(Info, Base);
+      Info.Note(VD->getLocation(), diag::note_declared_at);
     }
     return false;
   }
@@ -3249,7 +3149,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
                          ? diag::note_constexpr_ltor_non_constexpr
                          : diag::note_constexpr_ltor_non_integral, 1)
           << VD << VD->getType();
-      NoteLValueLocation(Info, Base);
+      Info.Note(VD->getLocation(), diag::note_declared_at);
     }
     return false;
   }
@@ -3268,7 +3168,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
   if (!VD->evaluateValue(Notes)) {
     Info.FFDiag(E, diag::note_constexpr_var_init_non_constant,
               Notes.size() + 1) << VD;
-    NoteLValueLocation(Info, Base);
+    Info.Note(VD->getLocation(), diag::note_declared_at);
     Info.addNotes(Notes);
     return false;
   }
@@ -3277,7 +3177,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
   if (!VD->checkInitIsICE()) {
     Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant,
                  Notes.size() + 1) << VD;
-    NoteLValueLocation(Info, Base);
+    Info.Note(VD->getLocation(), diag::note_declared_at);
     Info.addNotes(Notes);
   }
 
@@ -3285,7 +3185,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
   // folding. We can't be sure that this is the definition that will be used.
   if (VD->isWeak()) {
     Info.FFDiag(E, diag::note_constexpr_var_init_weak) << VD;
-    NoteLValueLocation(Info, Base);
+    Info.Note(VD->getLocation(), diag::note_declared_at);
     return false;
   }
 
@@ -3999,11 +3899,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
     // Unless we're looking at a local variable or argument in a constexpr call,
     // the variable we're reading must be const.
     if (!Frame) {
-      if (isa<ParmVarDecl>(VD)) {
-        // Allow evaluateVarDeclInit to diagnose this (or permit it during
-        // potential constant expression checking).
-      } else if (Info.getLangOpts().CPlusPlus14 &&
-                 lifetimeStartedInEvaluation(Info, LVal.Base)) {
+      if (Info.getLangOpts().CPlusPlus14 &&
+          lifetimeStartedInEvaluation(Info, LVal.Base)) {
         // OK, we can read and modify an object if we're in the process of
         // evaluating its initializer, because its lifetime began in this
         // evaluation.
@@ -4060,7 +3957,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
       }
     }
 
-    if (!evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(), BaseVal))
+    if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal, &LVal))
       return CompleteObject();
   } else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) {
     Optional<DynAlloc*> Alloc = Info.lookupDynamicAlloc(DA);
@@ -4129,19 +4026,13 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
   }
 
   // In C++14, we can't safely access any mutable state when we might be
-  // evaluating after an unmodeled side effect. Parameters are modeled as state
-  // in the caller, but aren't visible once the call returns, so they can be
-  // modified in a speculatively-evaluated call.
+  // evaluating after an unmodeled side effect.
   //
   // FIXME: Not all local state is mutable. Allow local constant subobjects
   // to be read here (but take care with 'mutable' fields).
-  unsigned VisibleDepth = Depth;
-  if (llvm::isa_and_nonnull<ParmVarDecl>(
-          LVal.Base.dyn_cast<const ValueDecl *>()))
-    ++VisibleDepth;
   if ((Frame && Info.getLangOpts().CPlusPlus14 &&
        Info.EvalStatus.HasSideEffects) ||
-      (isModification(AK) && VisibleDepth < Info.SpeculativeEvaluationDepth))
+      (isModification(AK) && Depth < Info.SpeculativeEvaluationDepth))
     return CompleteObject();
 
   return CompleteObject(LVal.getLValueBase(), BaseVal, BaseType);
@@ -4752,8 +4643,8 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
     return true;
 
   LValue Result;
-  APValue &Val = Info.CurrentCall->createTemporary(VD, VD->getType(),
-                                                   ScopeKind::Block, Result);
+  APValue &Val =
+      Info.CurrentCall->createTemporary(VD, VD->getType(), true, Result);
 
   const Expr *InitE = VD->getInit();
   if (!InitE)
@@ -5898,35 +5789,15 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
   return true;
 }
 
-static bool EvaluateCallArg(const ParmVarDecl *PVD, const Expr *Arg,
-                            CallRef Call, EvalInfo &Info,
-                            bool NonNull = false) {
-  LValue LV;
-  // Create the parameter slot and register its destruction. For a vararg
-  // argument, create a temporary.
-  // FIXME: For calling conventions that destroy parameters in the callee,
-  // should we consider performing destruction when the function returns
-  // instead?
-  APValue &V = PVD ? Info.CurrentCall->createParam(Call, PVD, LV)
-                   : Info.CurrentCall->createTemporary(Arg, Arg->getType(),
-                                                       ScopeKind::Call, LV);
-  if (!EvaluateInPlace(V, Info, LV, Arg))
-    return false;
-
-  // Passing a null pointer to an __attribute__((nonnull)) parameter results in
-  // undefined behavior, so is non-constant.
-  if (NonNull && V.isLValue() && V.isNullPointer()) {
-    Info.CCEDiag(Arg, diag::note_non_null_attribute_failed);
-    return false;
-  }
-
-  return true;
+namespace {
+typedef SmallVector<APValue, 8> ArgVector;
 }
 
-/// Evaluate the arguments to a function call.
-static bool EvaluateArgs(ArrayRef<const Expr *> Args, CallRef Call,
-                         EvalInfo &Info, const FunctionDecl *Callee,
-                         bool RightToLeft = false) {
+/// EvaluateArgs - Evaluate the arguments to a function call.
+static bool EvaluateArgs(ArrayRef<const Expr *> Args, ArgVector &ArgValues,
+                         EvalInfo &Info, const FunctionDecl *Callee) {
+  ArgValues.resize(Args.size());
+
   bool Success = true;
   llvm::SmallBitVector ForbiddenNullArgs;
   if (Callee->hasAttr<NonNullAttr>()) {
@@ -5944,53 +5815,36 @@ static bool EvaluateArgs(ArrayRef<const Expr *> Args, CallRef Call,
         }
     }
   }
-  for (unsigned I = 0; I < Args.size(); I++) {
-    unsigned Idx = RightToLeft ? Args.size() - I - 1 : I;
-    const ParmVarDecl *PVD =
-        Idx < Callee->getNumParams() ? Callee->getParamDecl(Idx) : nullptr;
-    bool NonNull = !ForbiddenNullArgs.empty() && ForbiddenNullArgs[Idx];
-    if (!EvaluateCallArg(PVD, Args[Idx], Call, Info, NonNull)) {
+  for (unsigned Idx = 0; Idx < Args.size(); Idx++) {
+    if (!Evaluate(ArgValues[Idx], Info, Args[Idx])) {
       // If we're checking for a potential constant expression, evaluate all
       // initializers even if some of them fail.
       if (!Info.noteFailure())
         return false;
       Success = false;
+    } else if (!ForbiddenNullArgs.empty() &&
+               ForbiddenNullArgs[Idx] &&
+               ArgValues[Idx].isLValue() &&
+               ArgValues[Idx].isNullPointer()) {
+      Info.CCEDiag(Args[Idx], diag::note_non_null_attribute_failed);
+      if (!Info.noteFailure())
+        return false;
+      Success = false;
     }
   }
   return Success;
 }
 
-/// Perform a trivial copy from Param, which is the parameter of a copy or move
-/// constructor or assignment operator.
-static bool handleTrivialCopy(EvalInfo &Info, const ParmVarDecl *Param,
-                              const Expr *E, APValue &Result,
-                              bool CopyObjectRepresentation) {
-  // Find the reference argument.
-  CallStackFrame *Frame = Info.CurrentCall;
-  APValue *RefValue = Info.getParamSlot(Frame->Arguments, Param);
-  if (!RefValue) {
-    Info.FFDiag(E);
-    return false;
-  }
-
-  // Copy out the contents of the RHS object.
-  LValue RefLValue;
-  RefLValue.setFrom(Info.Ctx, *RefValue);
-  return handleLValueToRValueConversion(
-      Info, E, Param->getType().getNonReferenceType(), RefLValue, Result,
-      CopyObjectRepresentation);
-}
-
 /// Evaluate a function call.
 static bool HandleFunctionCall(SourceLocation CallLoc,
                                const FunctionDecl *Callee, const LValue *This,
-                               ArrayRef<const Expr *> Args, CallRef Call,
+                               ArrayRef<const Expr *> Args, APValue *ArgValues,
                                const Stmt *Body, EvalInfo &Info,
                                APValue &Result, const LValue *ResultSlot) {
   if (!Info.CheckCallLimit(CallLoc))
     return false;
 
-  CallStackFrame Frame(Info, CallLoc, Callee, This, Call);
+  CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues);
 
   // For a trivial copy or move assignment, perform an APValue copy. This is
   // essential for unions, where the operations performed by the assignment
@@ -6005,9 +5859,11 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
         isReadByLvalueToRvalueConversion(MD->getParent())))) {
     assert(This &&
            (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));
+    LValue RHS;
+    RHS.setFrom(Info.Ctx, ArgValues[0]);
     APValue RHSValue;
-    if (!handleTrivialCopy(Info, MD->getParamDecl(0), Args[0], RHSValue,
-                           MD->getParent()->isUnion()))
+    if (!handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), RHS,
+                                        RHSValue, MD->getParent()->isUnion()))
       return false;
     if (Info.getLangOpts().CPlusPlus20 && MD->isTrivial() &&
         !HandleUnionActiveMemberChange(Info, Args[0], *This))
@@ -6041,7 +5897,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
 
 /// Evaluate a constructor call.
 static bool HandleConstructorCall(const Expr *E, const LValue &This,
-                                  CallRef Call,
+                                  APValue *ArgValues,
                                   const CXXConstructorDecl *Definition,
                                   EvalInfo &Info, APValue &Result) {
   SourceLocation CallLoc = E->getExprLoc();
@@ -6058,7 +5914,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
       Info,
       ObjectUnderConstruction{This.getLValueBase(), This.Designator.Entries},
       RD->getNumBases());
-  CallStackFrame Frame(Info, CallLoc, Definition, &This, Call);
+  CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues);
 
   // FIXME: Creating an APValue just to hold a nonexistent return value is
   // wasteful.
@@ -6089,8 +5945,11 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
       (Definition->getParent()->isUnion() ||
        (Definition->isTrivial() &&
         isReadByLvalueToRvalueConversion(Definition->getParent())))) {
-    return handleTrivialCopy(Info, Definition->getParamDecl(0), E, Result,
-                             Definition->getParent()->isUnion());
+    LValue RHS;
+    RHS.setFrom(Info.Ctx, ArgValues[0]);
+    return handleLValueToRValueConversion(
+        Info, E, Definition->getParamDecl(0)->getType().getNonReferenceType(),
+        RHS, Result, Definition->getParent()->isUnion());
   }
 
   // Reserve space for the struct members.
@@ -6249,13 +6108,12 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
                                   ArrayRef<const Expr*> Args,
                                   const CXXConstructorDecl *Definition,
                                   EvalInfo &Info, APValue &Result) {
-  CallScopeRAII CallScope(Info);
-  CallRef Call = Info.CurrentCall->createCall(Definition);
-  if (!EvaluateArgs(Args, Call, Info, Definition))
+  ArgVector ArgValues(Args.size());
+  if (!EvaluateArgs(Args, ArgValues, Info, Definition))
     return false;
 
-  return HandleConstructorCall(E, This, Call, Definition, Info, Result) &&
-         CallScope.destroy();
+  return HandleConstructorCall(E, This, ArgValues.data(), Definition,
+                               Info, Result);
 }
 
 static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
@@ -6351,7 +6209,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
   if (!CheckConstexprFunction(Info, CallLoc, DD, Definition, Body))
     return false;
 
-  CallStackFrame Frame(Info, CallLoc, Definition, &This, CallRef());
+  CallStackFrame Frame(Info, CallLoc, Definition, &This, nullptr);
 
   // We're now in the period of destruction of this object.
   unsigned BasesLeft = RD->getNumBases();
@@ -7339,8 +7197,8 @@ class ExprEvaluatorBase
     LValue CommonLV;
     if (!Evaluate(Info.CurrentCall->createTemporary(
                       E->getOpaqueValue(),
-                      getStorageType(Info.Ctx, E->getOpaqueValue()),
-                      ScopeKind::FullExpression, CommonLV),
+                      getStorageType(Info.Ctx, E->getOpaqueValue()), false,
+                      CommonLV),
                   Info, E->getCommon()))
       return false;
 
@@ -7404,8 +7262,7 @@ class ExprEvaluatorBase
 
         LValue LV;
         if (!Evaluate(Info.CurrentCall->createTemporary(
-                          OVE, getStorageType(Info.Ctx, OVE),
-                          ScopeKind::FullExpression, LV),
+                          OVE, getStorageType(Info.Ctx, OVE), false, LV),
                       Info, OVE->getSourceExpr()))
           return false;
       } else if (SemE == E->getResultExpr()) {
@@ -7428,8 +7285,6 @@ class ExprEvaluatorBase
 
   bool handleCallExpr(const CallExpr *E, APValue &Result,
                      const LValue *ResultSlot) {
-    CallScopeRAII CallScope(Info);
-
     const Expr *Callee = E->getCallee()->IgnoreParens();
     QualType CalleeType = Callee->getType();
 
@@ -7438,8 +7293,7 @@ class ExprEvaluatorBase
     auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
     bool HasQualifier = false;
 
-    CallRef Call;
-    bool EvaluatedArgs = false;
+    ArgVector ArgValues;
 
     // Extract function decl and 'this' pointer from the callee.
     if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
@@ -7472,14 +7326,14 @@ class ExprEvaluatorBase
         return Error(Callee);
       FD = Member;
     } else if (CalleeType->isFunctionPointerType()) {
-      LValue CalleeLV;
-      if (!EvaluatePointer(Callee, CalleeLV, Info))
+      LValue Call;
+      if (!EvaluatePointer(Callee, Call, Info))
         return false;
 
-      if (!CalleeLV.getLValueOffset().isZero())
+      if (!Call.getLValueOffset().isZero())
         return Error(Callee);
       FD = dyn_cast_or_null<FunctionDecl>(
-          CalleeLV.getLValueBase().dyn_cast<const ValueDecl *>());
+                             Call.getLValueBase().dyn_cast<const ValueDecl*>());
       if (!FD)
         return Error(Callee);
       // Don't call function pointers which have been cast to some other type.
@@ -7494,11 +7348,15 @@ class ExprEvaluatorBase
       auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);
       if (OCE && OCE->isAssignmentOp()) {
         assert(Args.size() == 2 && "wrong number of arguments in assignment");
-        Call = Info.CurrentCall->createCall(FD);
-        if (!EvaluateArgs(isa<CXXMethodDecl>(FD) ? Args.slice(1) : Args, Call,
-                          Info, FD, /*RightToLeft=*/true))
-          return false;
-        EvaluatedArgs = true;
+        if (isa<CXXMethodDecl>(FD)) {
+          // Args[0] is the object argument.
+          if (!EvaluateArgs({Args[1]}, ArgValues, Info, FD))
+            return false;
+        } else {
+          if (!EvaluateArgs({Args[1], Args[0]}, ArgValues, Info, FD))
+            return false;
+          std::swap(ArgValues[0], ArgValues[1]);
+        }
       }
 
       // Overloaded operator calls to member functions are represented as normal
@@ -7555,20 +7413,18 @@ class ExprEvaluatorBase
           if (!HandleOperatorNewCall(Info, E, Ptr))
             return false;
           Ptr.moveInto(Result);
-          return CallScope.destroy();
+          return true;
         } else {
-          return HandleOperatorDeleteCall(Info, E) && CallScope.destroy();
+          return HandleOperatorDeleteCall(Info, E);
         }
       }
     } else
       return Error(E);
 
     // Evaluate the arguments now if we've not already done so.
-    if (!Call) {
-      Call = Info.CurrentCall->createCall(FD);
-      if (!EvaluateArgs(Args, Call, Info, FD))
-        return false;
-    }
+    if (ArgValues.empty() && !Args.empty() &&
+        !EvaluateArgs(Args, ArgValues, Info, FD))
+      return false;
 
     SmallVector<QualType, 4> CovariantAdjustmentPath;
     if (This) {
@@ -7591,17 +7447,17 @@ class ExprEvaluatorBase
     // Destructor calls are 
diff erent enough that they have their own codepath.
     if (auto *DD = dyn_cast<CXXDestructorDecl>(FD)) {
       assert(This && "no 'this' pointer for destructor call");
+      assert(ArgValues.empty() && "unexpected destructor arguments");
       return HandleDestruction(Info, E, *This,
-                               Info.Ctx.getRecordType(DD->getParent())) &&
-             CallScope.destroy();
+                               Info.Ctx.getRecordType(DD->getParent()));
     }
 
     const FunctionDecl *Definition = nullptr;
     Stmt *Body = FD->getBody(Definition);
 
     if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
-        !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Call,
-                            Body, Info, Result, ResultSlot))
+        !HandleFunctionCall(E->getExprLoc(), Definition, This, Args,
+                            ArgValues.data(), Body, Info, Result, ResultSlot))
       return false;
 
     if (!CovariantAdjustmentPath.empty() &&
@@ -7609,7 +7465,7 @@ class ExprEvaluatorBase
                                          CovariantAdjustmentPath))
       return false;
 
-    return CallScope.destroy();
+    return true;
   }
 
   bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
@@ -8073,45 +7929,31 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
       return true;
     }
   }
-
   CallStackFrame *Frame = nullptr;
-  unsigned Version = 0;
-  if (VD->hasLocalStorage()) {
+  if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) {
     // Only if a local variable was declared in the function currently being
     // evaluated, do we expect to be able to find its value in the current
     // frame. (Otherwise it was likely declared in an enclosing context and
     // could either have a valid evaluatable value (for e.g. a constexpr
     // variable) or be ill-formed (and trigger an appropriate evaluation
     // diagnostic)).
-    CallStackFrame *CurrFrame = Info.CurrentCall;
-    if (CurrFrame->Callee && CurrFrame->Callee->Equals(VD->getDeclContext())) {
-      // Function parameters are stored in some caller's frame. (Usually the
-      // immediate caller, but for an inherited constructor they may be more
-      // distant.)
-      if (auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
-        if (CurrFrame->Arguments) {
-          VD = CurrFrame->Arguments.getOrigParam(PVD);
-          Frame =
-              Info.getCallFrameAndDepth(CurrFrame->Arguments.CallIndex).first;
-          Version = CurrFrame->Arguments.Version;
-        }
-      } else {
-        Frame = CurrFrame;
-        Version = CurrFrame->getCurrentTemporaryVersion(VD);
-      }
+    if (Info.CurrentCall->Callee &&
+        Info.CurrentCall->Callee->Equals(VD->getDeclContext())) {
+      Frame = Info.CurrentCall;
     }
   }
 
   if (!VD->getType()->isReferenceType()) {
     if (Frame) {
-      Result.set({VD, Frame->Index, Version});
+      Result.set({VD, Frame->Index,
+                  Info.CurrentCall->getCurrentTemporaryVersion(VD)});
       return true;
     }
     return Success(VD);
   }
 
   APValue *V;
-  if (!evaluateVarDeclInit(Info, E, VD, Frame, Version, V))
+  if (!evaluateVarDeclInit(Info, E, VD, Frame, V, nullptr))
     return false;
   if (!V->hasValue()) {
     // FIXME: Is it possible for V to be indeterminate here? If so, we should
@@ -8141,16 +7983,12 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr(
   // value for use outside this evaluation.
   APValue *Value;
   if (E->getStorageDuration() == SD_Static) {
-    // FIXME: What about SD_Thread?
     Value = E->getOrCreateValue(true);
     *Value = APValue();
     Result.set(E);
   } else {
     Value = &Info.CurrentCall->createTemporary(
-        E, E->getType(),
-        E->getStorageDuration() == SD_FullExpression ? ScopeKind::FullExpression
-                                                     : ScopeKind::Block,
-        Result);
+        E, E->getType(), E->getStorageDuration() == SD_Automatic, Result);
   }
 
   QualType Type = Inner->getType();
@@ -8704,7 +8542,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
         return false;
     } else {
       APValue &Value = Info.CurrentCall->createTemporary(
-          SubExpr, SubExpr->getType(), ScopeKind::FullExpression, Result);
+          SubExpr, SubExpr->getType(), false, Result);
       if (!EvaluateInPlace(Value, Info, Result, SubExpr))
         return false;
     }
@@ -9957,8 +9795,8 @@ class TemporaryExprEvaluator
 
   /// Visit an expression which constructs the value of this temporary.
   bool VisitConstructExpr(const Expr *E) {
-    APValue &Value = Info.CurrentCall->createTemporary(
-        E, E->getType(), ScopeKind::FullExpression, Result);
+    APValue &Value =
+        Info.CurrentCall->createTemporary(E, E->getType(), false, Result);
     return EvaluateInPlace(Value, Info, Result, E);
   }
 
@@ -10395,8 +10233,8 @@ bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
   if (E->getCommonExpr() &&
       !Evaluate(Info.CurrentCall->createTemporary(
                     E->getCommonExpr(),
-                    getStorageType(Info.Ctx, E->getCommonExpr()),
-                    ScopeKind::FullExpression, CommonLV),
+                    getStorageType(Info.Ctx, E->getCommonExpr()), false,
+                    CommonLV),
                 Info, E->getCommonExpr()->getSourceExpr()))
     return false;
 
@@ -14388,14 +14226,13 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {
   } else if (T->isArrayType()) {
     LValue LV;
     APValue &Value =
-        Info.CurrentCall->createTemporary(E, T, ScopeKind::FullExpression, LV);
+        Info.CurrentCall->createTemporary(E, T, false, LV);
     if (!EvaluateArray(E, LV, Value, Info))
       return false;
     Result = Value;
   } else if (T->isRecordType()) {
     LValue LV;
-    APValue &Value =
-        Info.CurrentCall->createTemporary(E, T, ScopeKind::FullExpression, LV);
+    APValue &Value = Info.CurrentCall->createTemporary(E, T, false, LV);
     if (!EvaluateRecord(E, LV, Value, Info))
       return false;
     Result = Value;
@@ -14409,8 +14246,7 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {
     QualType Unqual = T.getAtomicUnqualifiedType();
     if (Unqual->isArrayType() || Unqual->isRecordType()) {
       LValue LV;
-      APValue &Value = Info.CurrentCall->createTemporary(
-          E, Unqual, ScopeKind::FullExpression, LV);
+      APValue &Value = Info.CurrentCall->createTemporary(E, Unqual, false, LV);
       if (!EvaluateAtomic(E, &LV, Value, Info))
         return false;
     } else {
@@ -15419,20 +15255,14 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
     Info.EvalStatus.HasSideEffects = false;
   }
 
-  CallRef Call = Info.CurrentCall->createCall(Callee);
+  ArgVector ArgValues(Args.size());
   for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end();
        I != E; ++I) {
-    unsigned Idx = I - Args.begin();
-    if (Idx >= Callee->getNumParams())
-      break;
-    const ParmVarDecl *PVD = Callee->getParamDecl(Idx);
     if ((*I)->isValueDependent() ||
-        !EvaluateCallArg(PVD, *I, Call, Info) ||
-        Info.EvalStatus.HasSideEffects) {
+        !Evaluate(ArgValues[I - Args.begin()], Info, *I) ||
+        Info.EvalStatus.HasSideEffects)
       // If evaluation fails, throw away the argument entirely.
-      if (APValue *Slot = Info.getParamSlot(Call, PVD))
-        *Slot = APValue();
-    }
+      ArgValues[I - Args.begin()] = APValue();
 
     // Ignore any side-effects from a failed evaluation. This is safe because
     // they can't interfere with any other argument evaluation.
@@ -15445,7 +15275,8 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
   Info.EvalStatus.HasSideEffects = false;
 
   // Build fake call to Callee.
-  CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr, Call);
+  CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr,
+                       ArgValues.data());
   // FIXME: Missing ExprWithCleanups in enable_if conditions?
   FullExpressionRAII Scope(Info);
   return Evaluate(Value, Info, this) && Scope.destroy() &&
@@ -15503,7 +15334,8 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
   } else {
     SourceLocation Loc = FD->getLocation();
     HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr,
-                       Args, CallRef(), FD->getBody(), Info, Scratch, nullptr);
+                       Args, /*ArgValues*/ nullptr, FD->getBody(), Info,
+                       Scratch, nullptr);
   }
 
   return Diags.empty();
@@ -15525,7 +15357,8 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E,
   Info.CheckingPotentialConstantExpression = true;
 
   // Fabricate a call stack frame to give the arguments a plausible cover story.
-  CallStackFrame Frame(Info, SourceLocation(), FD, /*This*/ nullptr, CallRef());
+  CallStackFrame Frame(Info, SourceLocation(), FD, /*This*/ nullptr,
+                       /*ArgValues*/ nullptr);
 
   APValue ResultScratch;
   Evaluate(ResultScratch, Info, E);

diff  --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
index 00ef78426289..3b8274e27369 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
@@ -10,7 +10,7 @@ namespace M {
 
 struct NonLiteral {
   NonLiteral() {}
-  NonLiteral(int) {}
+  NonLiteral(int) {} // expected-note 2{{here}}
   operator int() const { return 0; }
 };
 struct Literal {
@@ -42,8 +42,8 @@ template<typename ...P> struct ConstexprCtor {
 };
 constexpr ConstexprCtor<> f1() { return {}; } // ok
 constexpr ConstexprCtor<int> f2() { return 0; } // ok
-constexpr ConstexprCtor<NonLiteral> f3() { return { 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-literal type 'NonLiteral}}
-constexpr ConstexprCtor<int, NonLiteral> f4() { return { 0, 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-literal type 'NonLiteral}}
+constexpr ConstexprCtor<NonLiteral> f3() { return { 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-constexpr constructor 'NonLiteral}}
+constexpr ConstexprCtor<int, NonLiteral> f4() { return { 0, 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-constexpr constructor 'NonLiteral}}
 
 struct VirtBase : virtual S {}; // expected-note {{here}}
 

diff  --git a/clang/test/CXX/except/except.spec/p1.cpp b/clang/test/CXX/except/except.spec/p1.cpp
index ef7c828bc7f2..03d75326a643 100644
--- a/clang/test/CXX/except/except.spec/p1.cpp
+++ b/clang/test/CXX/except/except.spec/p1.cpp
@@ -55,7 +55,7 @@ namespace noex {
   struct A {};
 
   void g1() noexcept(A()); // expected-error {{not contextually convertible}}
-  void g2(bool b) noexcept(b); // expected-error {{argument to noexcept specifier must be a constant expression}} expected-note {{function parameter 'b' with unknown value}} expected-note {{here}}
+  void g2(bool b) noexcept(b); // expected-error {{argument to noexcept specifier must be a constant expression}} expected-note {{read of non-const variable 'b'}} expected-note {{here}}
 
 }
 

diff  --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index e7b6929199ff..2ab629a6d0dd 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -62,11 +62,11 @@ namespace NonConstExprReturn {
   constexpr const int *address_of(const int &a) {
     return &a;
   }
-  constexpr const int *return_param(int n) {
+  constexpr const int *return_param(int n) { // expected-note {{declared here}}
     return address_of(n);
   }
   struct S {
-    int n : *return_param(0); // expected-error {{constant expression}} expected-note {{read of object outside its lifetime}}
+    int n : *return_param(0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}}
   };
 }
 
@@ -427,12 +427,13 @@ namespace PseudoDtor {
     int n : (k.~I(), 1); // expected-error {{constant expression}} expected-note {{visible outside that expression}}
   };
 
-  constexpr int f(int a = 1) { // cxx11-error {{constant expression}} expected-note {{destroying object 'a' whose lifetime has already ended}}
+  // FIXME: It's unclear whether this should be accepted in C++20 mode. The parameter is destroyed twice here.
+  constexpr int f(int a = 1) { // cxx11-error {{constant expression}}
     return (
-        a.~I(), // cxx11-note {{pseudo-destructor}}
+        a.~I(), // cxx11-note 2{{pseudo-destructor}}
         0);
   }
-  static_assert(f() == 0, ""); // expected-error {{constant expression}}
+  static_assert(f() == 0, ""); // cxx11-error {{constant expression}} cxx11-note {{in call}}
 
   // This is OK in C++20: the union has no active member after the
   // pseudo-destructor call, so the union destructor has no effect.

diff  --git a/clang/test/OpenMP/critical_messages.cpp b/clang/test/OpenMP/critical_messages.cpp
index 8536caf224e3..4fc2b201c820 100644
--- a/clang/test/OpenMP/critical_messages.cpp
+++ b/clang/test/OpenMP/critical_messages.cpp
@@ -65,7 +65,7 @@ int tmain(int argc, char **argv) { // expected-note {{declared here}}
   foo();
   #pragma omp critical (name2) hint(+ // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   foo();
-  #pragma omp critical (name2) hint(argc) // expected-error {{integral constant expression}} expected-note 0+{{constant expression}}
+  #pragma omp critical (name2) hint(argc) // expected-error {{integral constant expression}} expected-note {{read of non-const variable 'argc' is not allowed in a constant expression}}
   foo();
   #pragma omp critical (name) hint(N) // expected-error {{argument to 'hint' clause must be a strictly positive integer value}} expected-error {{constructs with the same name must have a 'hint' clause with the same value}} expected-note {{'hint' clause with value '4'}}
   foo();
@@ -128,7 +128,7 @@ int main(int argc, char **argv) { // expected-note {{declared here}}
   foo();
   #pragma omp critical (name2) hint(+ // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   foo();
-  #pragma omp critical (name2) hint(argc) // expected-error {{integral constant expression}} expected-note 0+{{constant expression}}
+  #pragma omp critical (name2) hint(argc) // expected-error {{integral constant expression}} expected-note {{read of non-const variable 'argc' is not allowed in a constant expression}}
   foo();
   #pragma omp critical (name) hint(23) // expected-note {{previous 'hint' clause with value '23'}}
   foo();

diff  --git a/clang/test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp
index 04f75e360577..eba65f733fcf 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp
@@ -39,7 +39,7 @@ T tmain(T argc, S **argv) {
 
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp distribute parallel for simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/OpenMP/distribute_simd_safelen_messages.cpp b/clang/test/OpenMP/distribute_simd_safelen_messages.cpp
index 8c3c009c2a81..51d677829486 100644
--- a/clang/test/OpenMP/distribute_simd_safelen_messages.cpp
+++ b/clang/test/OpenMP/distribute_simd_safelen_messages.cpp
@@ -39,7 +39,7 @@ T tmain(T argc, S **argv) {
 
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp distribute simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/OpenMP/distribute_simd_simdlen_messages.cpp b/clang/test/OpenMP/distribute_simd_simdlen_messages.cpp
index 8c3c009c2a81..51d677829486 100644
--- a/clang/test/OpenMP/distribute_simd_simdlen_messages.cpp
+++ b/clang/test/OpenMP/distribute_simd_simdlen_messages.cpp
@@ -39,7 +39,7 @@ T tmain(T argc, S **argv) {
 
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp distribute simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp
index 3061dff6709b..31dfb7c8024e 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp
@@ -31,7 +31,7 @@ T tmain(T argc, S **argv) {
 #pragma omp target teams distribute parallel for simd safelen () // expected-error {{expected expression}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
-#pragma omp target teams distribute parallel for simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp target teams distribute parallel for simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp
index b67ca29634dc..14865e593129 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp
@@ -31,7 +31,7 @@ T tmain(T argc, S **argv) {
 #pragma omp target teams distribute parallel for simd safelen () // expected-error {{expected expression}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
-#pragma omp target teams distribute parallel for simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp target teams distribute parallel for simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++)
     argv[0][i] = argv[0][i] - argv[0][i-ST];
 

diff  --git a/clang/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp b/clang/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp
index 75a86e6890d5..a472b8eddee8 100644
--- a/clang/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp
@@ -31,7 +31,7 @@ T tmain(T argc, S **argv) {
 #pragma omp target teams distribute simd safelen () // expected-error {{expected expression}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
-#pragma omp target teams distribute simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp target teams distribute simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp b/clang/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp
index f84dd17f9fb0..489bb808db54 100644
--- a/clang/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp
@@ -31,7 +31,7 @@ T tmain(T argc, S **argv) {
 #pragma omp target teams distribute simd safelen () // expected-error {{expected expression}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
-#pragma omp target teams distribute simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp target teams distribute simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp
index 78d742c9b3ae..122b9cbe098b 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp
@@ -35,7 +35,7 @@ T tmain(T argc, S **argv) {
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
 #pragma omp target
-#pragma omp teams distribute parallel for simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp teams distribute parallel for simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp
index 78d742c9b3ae..122b9cbe098b 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp
@@ -35,7 +35,7 @@ T tmain(T argc, S **argv) {
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
 #pragma omp target
-#pragma omp teams distribute parallel for simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp teams distribute parallel for simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/OpenMP/teams_distribute_simd_safelen_messages.cpp b/clang/test/OpenMP/teams_distribute_simd_safelen_messages.cpp
index 3cf70dbdc9ef..4efede29baee 100644
--- a/clang/test/OpenMP/teams_distribute_simd_safelen_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_simd_safelen_messages.cpp
@@ -35,7 +35,7 @@ T tmain(T argc, S **argv) {
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
 #pragma omp target
-#pragma omp teams distribute simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp teams distribute simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp b/clang/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp
index 3cf70dbdc9ef..4efede29baee 100644
--- a/clang/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp
@@ -35,7 +35,7 @@ T tmain(T argc, S **argv) {
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
 #pragma omp target
-#pragma omp teams distribute simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
+#pragma omp teams distribute simd safelen (argc  // expected-note {{to match this '('}} expected-error 2 {{integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-note 0+{{constant expression}} expected-error {{expected ')'}}
   for (int i = ST; i < N; i++) 
     argv[0][i] = argv[0][i] - argv[0][i-ST];
   

diff  --git a/clang/test/Sema/builtin-expect-with-probability-avr.cpp b/clang/test/Sema/builtin-expect-with-probability-avr.cpp
index 1767480134a2..1dbb1d52396a 100644
--- a/clang/test/Sema/builtin-expect-with-probability-avr.cpp
+++ b/clang/test/Sema/builtin-expect-with-probability-avr.cpp
@@ -5,7 +5,7 @@ void test(int x, double p) { // expected-note {{declared here}}
   dummy = __builtin_expect_with_probability(x > 0, 1, 0.9);
   dummy = __builtin_expect_with_probability(x > 0, 1, 1.1); // expected-error {{probability argument to __builtin_expect_with_probability is outside the range [0.0, 1.0]}}
   dummy = __builtin_expect_with_probability(x > 0, 1, -1); // expected-error {{probability argument to __builtin_expect_with_probability is outside the range [0.0, 1.0]}}
-  dummy = __builtin_expect_with_probability(x > 0, 1, p); // expected-error {{probability argument to __builtin_expect_with_probability must be constant floating-point expression}} expected-note {{function parameter 'p' with unknown value}}
+  dummy = __builtin_expect_with_probability(x > 0, 1, p); // expected-error {{probability argument to __builtin_expect_with_probability must be constant floating-point expression}} expected-note {{read of non-constexpr variable 'p' is not allowed in a constant expression}}
   dummy = __builtin_expect_with_probability(x > 0, 1, "aa"); // expected-error {{cannot initialize a parameter of type 'double' with an lvalue of type 'const char [3]'}}
   dummy = __builtin_expect_with_probability(x > 0, 1, __builtin_nan("")); // expected-error {{probability argument to __builtin_expect_with_probability is outside the range [0.0, 1.0]}}
   dummy = __builtin_expect_with_probability(x > 0, 1, __builtin_inf()); // expected-error {{probability argument to __builtin_expect_with_probability is outside the range [0.0, 1.0]}}

diff  --git a/clang/test/Sema/builtin-expect-with-probability.cpp b/clang/test/Sema/builtin-expect-with-probability.cpp
index e05174f70673..3aa20cb0e6dd 100644
--- a/clang/test/Sema/builtin-expect-with-probability.cpp
+++ b/clang/test/Sema/builtin-expect-with-probability.cpp
@@ -43,7 +43,7 @@ void test(int x, double p) { // expected-note {{declared here}}
   dummy = __builtin_expect_with_probability(x > 0, 1, 0.9);
   dummy = __builtin_expect_with_probability(x > 0, 1, 1.1); // expected-error {{probability argument to __builtin_expect_with_probability is outside the range [0.0, 1.0]}}
   dummy = __builtin_expect_with_probability(x > 0, 1, -1); // expected-error {{probability argument to __builtin_expect_with_probability is outside the range [0.0, 1.0]}}
-  dummy = __builtin_expect_with_probability(x > 0, 1, p); // expected-error {{probability argument to __builtin_expect_with_probability must be constant floating-point expression}} expected-note {{function parameter 'p'}}
+  dummy = __builtin_expect_with_probability(x > 0, 1, p); // expected-error {{probability argument to __builtin_expect_with_probability must be constant floating-point expression}} expected-note {{read of non-constexpr variable 'p' is not allowed in a constant expression}}
   dummy = __builtin_expect_with_probability(x > 0, 1, "aa"); // expected-error {{cannot initialize a parameter of type 'double' with an lvalue of type 'const char [3]'}}
   dummy = __builtin_expect_with_probability(x > 0, 1, __builtin_nan("")); // expected-error {{probability argument to __builtin_expect_with_probability is outside the range [0.0, 1.0]}}
   dummy = __builtin_expect_with_probability(x > 0, 1, __builtin_inf()); // expected-error {{probability argument to __builtin_expect_with_probability is outside the range [0.0, 1.0]}}

diff  --git a/clang/test/Sema/c89.c b/clang/test/Sema/c89.c
index 89eda9362608..1c0494d8e5a3 100644
--- a/clang/test/Sema/c89.c
+++ b/clang/test/Sema/c89.c
@@ -65,7 +65,7 @@ void test10 (int x[*]); /* expected-warning {{variable length arrays are a C99 f
 void test11 (int x[static 4]); /* expected-warning {{static array size is a C99 feature}} */
 
 void test12 (int x[const 4]) { /* expected-warning {{qualifier in array size is a C99 feature}} */
-  int Y[x[1]]; /* expected-warning {{variable length arrays are a C99 feature}} */
+  int Y[x[1]]; /* expected-warning {{variable length arrays are a C99 feature}} expected-note {{parameter 'x'}} */
 }
 
 /* PR4074 */

diff  --git a/clang/test/SemaCUDA/constexpr-variables.cu b/clang/test/SemaCUDA/constexpr-variables.cu
index aa88cbadb73f..6e17a0856838 100644
--- a/clang/test/SemaCUDA/constexpr-variables.cu
+++ b/clang/test/SemaCUDA/constexpr-variables.cu
@@ -17,7 +17,7 @@ __host__ __device__ void foo(const T **a) {
   constexpr T e = sizeof(a);
   constexpr T f = **a;
   // expected-error at -1 {{constexpr variable 'f' must be initialized by a constant expression}}
-  // expected-note at -2 {{}}
+  // expected-note at -2 {{read of non-constexpr variable 'a' is not allowed in a constant expression}}
   a[0] = &b;
   a[1] = &c;
   a[2] = &d;
@@ -30,7 +30,7 @@ __device__ void device_fun(const int **a) {
   static constexpr int c = sizeof(a);
   constexpr int d = **a;
   // expected-error at -1 {{constexpr variable 'd' must be initialized by a constant expression}}
-  // expected-note at -2 {{}}
+  // expected-note at -2 {{read of non-constexpr variable 'a' is not allowed in a constant expression}}
   a[0] = &b;
   a[1] = &c;
   foo(a);
@@ -43,7 +43,7 @@ void host_fun(const int **a) {
   static constexpr int c = sizeof(a);
   constexpr int d = **a;
   // expected-error at -1 {{constexpr variable 'd' must be initialized by a constant expression}}
-  // expected-note at -2 {{}}
+  // expected-note at -2 {{read of non-constexpr variable 'a' is not allowed in a constant expression}}
   a[0] = &b;
   a[1] = &c;
   foo(a);
@@ -55,7 +55,7 @@ __host__ __device__ void host_device_fun(const int **a) {
   static constexpr int c = sizeof(a);
   constexpr int d = **a;
   // expected-error at -1 {{constexpr variable 'd' must be initialized by a constant expression}}
-  // expected-note at -2 {{}}
+  // expected-note at -2 {{read of non-constexpr variable 'a' is not allowed in a constant expression}}
   a[0] = &b;
   a[1] = &c;
   foo(a);

diff  --git a/clang/test/SemaCXX/c99-variable-length-array-cxx11.cpp b/clang/test/SemaCXX/c99-variable-length-array-cxx11.cpp
index 1360a20bfe8c..20eceec5032d 100644
--- a/clang/test/SemaCXX/c99-variable-length-array-cxx11.cpp
+++ b/clang/test/SemaCXX/c99-variable-length-array-cxx11.cpp
@@ -18,12 +18,12 @@ struct POD {
 
 // We allow VLAs of POD types, only.
 void vla(int N) { // expected-note 5{{here}}
-  int array1[N]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{parameter 'N'}}
-  POD array2[N]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{parameter 'N'}}
-  StillPOD array3[N]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{parameter 'N'}}
-  StillPOD2 array4[N][3]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{parameter 'N'}}
+  int array1[N]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{variable 'N'}}
+  POD array2[N]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{variable 'N'}}
+  StillPOD array3[N]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{variable 'N'}}
+  StillPOD2 array4[N][3]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{variable 'N'}}
   NonPOD array5[N]; // expected-error{{no matching constructor for initialization of 'NonPOD [N]'}}
-  // expected-warning at -1{{variable length arrays are a C99 feature}} expected-note at -1 {{parameter 'N'}}
+  // expected-warning at -1{{variable length arrays are a C99 feature}} expected-note at -1 {{variable 'N'}}
   // expected-note at -16{{candidate constructor not viable}}
   // expected-note at -18{{candidate constructor (the implicit copy constructor) not viable}}
   // expected-note at -19{{candidate constructor (the implicit move constructor) not viable}}

diff  --git a/clang/test/SemaCXX/c99-variable-length-array.cpp b/clang/test/SemaCXX/c99-variable-length-array.cpp
index 5f6337e1db06..d5c3845d1e2f 100644
--- a/clang/test/SemaCXX/c99-variable-length-array.cpp
+++ b/clang/test/SemaCXX/c99-variable-length-array.cpp
@@ -13,7 +13,6 @@ struct POD {
 };
 
 // expected-note@* 1+{{read of non-const variable}}
-// expected-note@* 1+{{function parameter}}
 // expected-note@* 1+{{declared here}}
 
 // We allow VLAs of POD types, only.

diff  --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index f40b42fa18e0..4b844177790a 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -217,11 +217,11 @@ namespace ParameterScopes {
 
   const int k = 42;
   constexpr const int &ObscureTheTruth(const int &a) { return a; }
-  constexpr const int &MaybeReturnJunk(bool b, const int a) {
+  constexpr const int &MaybeReturnJunk(bool b, const int a) { // expected-note 2{{declared here}}
     return ObscureTheTruth(b ? a : k);
   }
   static_assert(MaybeReturnJunk(false, 0) == 42, ""); // ok
-  constexpr int a = MaybeReturnJunk(true, 0); // expected-error {{constant expression}} expected-note {{read of object outside its lifetime}}
+  constexpr int a = MaybeReturnJunk(true, 0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}}
 
   constexpr const int MaybeReturnNonstaticRef(bool b, const int a) {
     return ObscureTheTruth(b ? a : k);
@@ -230,7 +230,7 @@ namespace ParameterScopes {
   constexpr int b = MaybeReturnNonstaticRef(true, 0); // ok
 
   constexpr int InternalReturnJunk(int n) {
-    return MaybeReturnJunk(true, n); // expected-note {{read of object outside its lifetime}}
+    return MaybeReturnJunk(true, n); // expected-note {{read of variable whose lifetime has ended}}
   }
   constexpr int n3 = InternalReturnJunk(0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'InternalReturnJunk(0)'}}
 
@@ -1568,7 +1568,7 @@ namespace RecursiveOpaqueExpr {
 namespace VLASizeof {
 
   void f(int k) { // expected-note {{here}}
-    int arr[k]; // expected-warning {{C99}} expected-note {{function parameter 'k'}}
+    int arr[k]; // expected-warning {{C99}} expected-note {{non-const variable 'k'}}
     constexpr int n = 1 +
         sizeof(arr) // expected-error {{constant expression}}
         * 3;
@@ -1928,9 +1928,9 @@ namespace Lifetime {
     int n = 0;
     constexpr int f() const { return 0; }
   };
-  constexpr Q *out_of_lifetime(Q q) { return &q; } // expected-warning {{address of stack}}
-  constexpr int k3 = out_of_lifetime({})->n; // expected-error {{constant expression}} expected-note {{read of object outside its lifetime}}
-  constexpr int k4 = out_of_lifetime({})->f(); // expected-error {{constant expression}} expected-note {{member call on object outside its lifetime}}
+  constexpr Q *out_of_lifetime(Q q) { return &q; } // expected-warning {{address of stack}} expected-note 2{{declared here}}
+  constexpr int k3 = out_of_lifetime({})->n; // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}}
+  constexpr int k4 = out_of_lifetime({})->f(); // expected-error {{constant expression}} expected-note {{member call on variable whose lifetime has ended}}
 
   constexpr int null = ((Q*)nullptr)->f(); // expected-error {{constant expression}} expected-note {{member call on dereferenced null pointer}}
 
@@ -2252,7 +2252,7 @@ namespace ns1 {
 void f(char c) { //expected-note2{{declared here}}
   struct X {
     static constexpr char f() { //expected-error{{never produces a constant expression}}
-      return c; //expected-error{{reference to local}} expected-note{{function parameter}}
+      return c; //expected-error{{reference to local}} expected-note{{non-const variable}}
     }
   };
   int I = X::f();
@@ -2312,7 +2312,7 @@ namespace array_size {
   template<typename T> void f1(T t) {
     constexpr int k = t.size();
   }
-  template<typename T> void f2(const T &t) { // expected-note {{declared here}}
+  template<typename T> void f2(const T &t) {
     constexpr int k = t.size(); // expected-error {{constant}} expected-note {{function parameter 't' with unknown value cannot be used in a constant expression}}
   }
   template<typename T> void f3(const T &t) {

diff  --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index 2aea2577d972..344797bafb11 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1415,16 +1415,3 @@ namespace PR45350 {
   //   decreasing address
   static_assert(f(6) == 543210);
 }
-
-namespace PR47805 {
-  struct A {
-    bool bad = true;
-    constexpr ~A() { if (bad) throw; }
-  };
-  constexpr bool f(A a) { a.bad = false; return true; }
-  constexpr bool b = f(A());
-
-  struct B { B *p = this; };
-  constexpr bool g(B b) { return &b == b.p; }
-  static_assert(g({}));
-}

diff  --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index 305cc3e976b0..2412c9d4db74 100644
--- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -17,7 +17,7 @@ namespace std {
 }
 
 template<typename T> constexpr bool has_type(...) { return false; }
-template<typename T> constexpr bool has_type(T&) { return true; }
+template<typename T> constexpr bool has_type(T) { return true; }
 
 std::initializer_list il = {1, 2, 3, 4, 5};
 

diff  --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index ecf8c1e0f5bd..3231107add09 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -238,7 +238,7 @@ constexpr int f_c(int i) {
 // expected-note at -1 {{declared here}}
   int t = f(i);
 // expected-error at -1 {{is not a constant expression}}
-// expected-note at -2 {{function parameter}}
+// expected-note at -2 {{read of non-const variable}}
   return f(0);  
 }
 
@@ -254,7 +254,7 @@ auto l1 = [](int i) constexpr {
 // expected-note at -1 {{declared here}}
   int t = f(i);
 // expected-error at -1 {{is not a constant expression}}
-// expected-note at -2 {{function parameter}}
+// expected-note at -2 {{read of non-const variable}}
   return f(0);  
 };
 

diff  --git a/clang/test/SemaCXX/integer-overflow.cpp b/clang/test/SemaCXX/integer-overflow.cpp
index c4d0d4084def..c6167b9c70ea 100644
--- a/clang/test/SemaCXX/integer-overflow.cpp
+++ b/clang/test/SemaCXX/integer-overflow.cpp
@@ -85,7 +85,8 @@ uint64_t check_integer_overflows(int i) { //expected-note 0+{{declared here}}
 // expected-warning at +1 {{overflow in expression; result is 537919488 with type 'int'}}
   case 1 + static_cast<uint64_t>(4609 * 1024 * 1024):
     return 7;
-// expected-error at +1 {{expression is not an integral constant expression}}
+// expected-error at +2 {{expression is not an integral constant expression}}
+// expected-note at +1 {{read of non-const variable 'i' is not allowed in a constant expression}}
   case ((uint64_t)(4608 * 1024 * 1024 * i)):
     return 8;
 // expected-warning at +1 {{overflow in expression; result is 536870912 with type 'int'}}

diff  --git a/clang/test/SemaCXX/vla-construct.cpp b/clang/test/SemaCXX/vla-construct.cpp
index 5a7d83342542..32526c24b0e0 100644
--- a/clang/test/SemaCXX/vla-construct.cpp
+++ b/clang/test/SemaCXX/vla-construct.cpp
@@ -23,8 +23,8 @@ void print(int n, int a, int b, int c, int d) {
 void test(int n) {
   S array_t[n][n+1];
 # ifdef PE
-   // expected-error at -2 {{variable length arrays are a C99 feature}} expected-note at -2 {{parameter}} expected-note at -3 {{here}}
-   // expected-error at -3 {{variable length arrays are a C99 feature}} expected-note at -3 {{parameter}} expected-note at -4 {{here}}
+   // expected-error at -2 {{variable length arrays are a C99 feature}} expected-note at -2 {{read of non-const}} expected-note at -3 {{here}}
+   // expected-error at -3 {{variable length arrays are a C99 feature}} expected-note at -3 {{read of non-const}} expected-note at -4 {{here}}
 # endif
   int sizeof_S = sizeof(S);
   int sizeof_array_t_0_0 = sizeof(array_t[0][0]);

diff  --git a/clang/test/SemaCXX/warn-vla.cpp b/clang/test/SemaCXX/warn-vla.cpp
index 00ac7c7a5c47..3514264efb2a 100644
--- a/clang/test/SemaCXX/warn-vla.cpp
+++ b/clang/test/SemaCXX/warn-vla.cpp
@@ -1,27 +1,27 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wvla %s
 
 void test1(int n) { // expected-note {{here}}
-  int v[n]; // expected-warning {{variable length array}} expected-note {{parameter 'n'}}
+  int v[n]; // expected-warning {{variable length array}} expected-note {{variable 'n'}}
 }
 
-void test2(int n, int v[n]) { // expected-warning {{variable length array}} expected-note {{parameter 'n'}} expected-note {{here}}
+void test2(int n, int v[n]) { // expected-warning {{variable length array}} expected-note {{variable 'n'}} expected-note {{here}}
 }
 
-void test3(int n, int v[n]); // expected-warning {{variable length array}} expected-note {{parameter 'n'}} expected-note {{here}}
+void test3(int n, int v[n]); // expected-warning {{variable length array}} expected-note {{variable 'n'}} expected-note {{here}}
 
 template<typename T>
 void test4(int n) { // expected-note {{here}}
-  int v[n]; // expected-warning {{variable length array}} expected-note {{parameter 'n'}}
+  int v[n]; // expected-warning {{variable length array}} expected-note {{variable 'n'}}
 }
 
 template<typename T>
-void test5(int n, int v[n]) { // expected-warning {{variable length array}} expected-note {{parameter 'n'}} expected-note {{here}}
+void test5(int n, int v[n]) { // expected-warning {{variable length array}} expected-note {{variable 'n'}} expected-note {{here}}
 }
 
 template<typename T>
-void test6(int n, int v[n]); // expected-warning {{variable length array}} expected-note {{parameter 'n'}} expected-note {{here}}
+void test6(int n, int v[n]); // expected-warning {{variable length array}} expected-note {{variable 'n'}} expected-note {{here}}
 
 template<typename T>
-void test7(int n, T v[n]) { // expected-warning {{variable length array}} expected-note {{parameter 'n'}} expected-note {{here}}
+void test7(int n, T v[n]) { // expected-warning {{variable length array}} expected-note {{variable 'n'}} expected-note {{here}}
 }
 

diff  --git a/clang/test/SemaTemplate/typo-dependent-name.cpp b/clang/test/SemaTemplate/typo-dependent-name.cpp
index 6a67e10dc868..88b2fc373b1f 100644
--- a/clang/test/SemaTemplate/typo-dependent-name.cpp
+++ b/clang/test/SemaTemplate/typo-dependent-name.cpp
@@ -34,13 +34,12 @@ struct Y {
   struct Inner : Y { // expected-note {{declared here}}
   };
 
-  bool f(T other) { // expected-note {{declared here}}
+  bool f(T other) {
     // We can determine that 'inner' does not exist at parse time, so can
     // perform typo correction in this case.
     return this->inner<other>::z; // expected-error {{no template named 'inner' in 'Y<T>'; did you mean 'Inner'?}}
-    // expected-error at -1 {{constant expression}} expected-note at -1 {{function parameter 'other'}}
   }
 };
 
 struct Q { constexpr operator int() { return 0; } };
-void use_y(Y<Q> x) { x.f(Q()); } // expected-note {{instantiation of}}
+void use_y(Y<Q> x) { x.f(Q()); }


        


More information about the cfe-commits mailing list