Index: head/devel/llvm60/Makefile =================================================================== --- head/devel/llvm60/Makefile +++ head/devel/llvm60/Makefile @@ -2,7 +2,7 @@ PORTNAME= llvm DISTVERSION= 6.0.1 -PORTREVISION= 4 +PORTREVISION= 5 CATEGORIES= devel lang MASTER_SITES= http://${PRE_}releases.llvm.org/${LLVM_RELEASE}/${RCDIR} PKGNAMESUFFIX= ${LLVM_SUFFIX} Index: head/devel/llvm60/files/clang/patch-stable12-r342281.diff =================================================================== --- head/devel/llvm60/files/clang/patch-stable12-r342281.diff +++ head/devel/llvm60/files/clang/patch-stable12-r342281.diff @@ -0,0 +1,834 @@ +r342281 | dim | 2018-12-20 19:28:53 +0100 (Thu, 20 Dec 2018) | 24 lines + +Pull in r329671 from upstream clang trunk (by Akira Hatanaka): + + [ExprConstant] Use an AST node and a version number as a key to + create an APValue and retrieve it from map Temporaries. + + The version number is needed when a single AST node is visited + multiple times and is used to create APValues that are required to be + distinct from each other (for example, MaterializeTemporaryExprs in + default arguments and VarDecls in loops). + + rdar://problem/36505742 + + Differential Revision: https://reviews.llvm.org/D42776 + +This should fix 'Assertion failed: (Result.isUninit() && "temporary +created multiple times"), function createTemporary' errors (if +assertions are enabled, otherwise the compiler internal state might go +bad), when building the graphics/rawtherapee port. + +Direct commit to stable/11 and stable/12, since head already has clang +7.0.1, which includes this change. + +PR: 234144 + +Index: tools/clang/include/clang/AST/APValue.h +=================================================================== +--- tools/clang/include/clang/AST/APValue.h (revision 342280) ++++ tools/clang/include/clang/AST/APValue.h (revision 342281) +@@ -53,7 +53,58 @@ class APValue { + MemberPointer, + AddrLabelDiff + }; +- typedef llvm::PointerUnion LValueBase; ++ ++ class LValueBase { ++ public: ++ typedef llvm::PointerUnion PtrTy; ++ ++ LValueBase() : CallIndex(0), Version(0) {} ++ ++ template ++ LValueBase(T P, unsigned I = 0, unsigned V = 0) ++ : Ptr(P), CallIndex(I), Version(V) {} ++ ++ template ++ bool is() const { return Ptr.is(); } ++ ++ template ++ T get() const { return Ptr.get(); } ++ ++ template ++ T dyn_cast() const { return Ptr.dyn_cast(); } ++ ++ void *getOpaqueValue() const; ++ ++ bool isNull() const; ++ ++ explicit operator bool () const; ++ ++ PtrTy getPointer() const { ++ return Ptr; ++ } ++ ++ unsigned getCallIndex() const { ++ return CallIndex; ++ } ++ ++ void setCallIndex(unsigned Index) { ++ CallIndex = Index; ++ } ++ ++ unsigned getVersion() const { ++ return Version; ++ } ++ ++ bool operator==(const LValueBase &Other) const { ++ return Ptr == Other.Ptr && CallIndex == Other.CallIndex && ++ Version == Other.Version; ++ } ++ ++ private: ++ PtrTy Ptr; ++ unsigned CallIndex, Version; ++ }; ++ + typedef llvm::PointerIntPair BaseOrMemberType; + union LValuePathEntry { + /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item +@@ -135,15 +186,15 @@ class APValue { + } + APValue(const APValue &RHS); + APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); } +- APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex, ++ APValue(LValueBase B, const CharUnits &O, NoLValuePath N, + bool IsNullPtr = false) + : Kind(Uninitialized) { +- MakeLValue(); setLValue(B, O, N, CallIndex, IsNullPtr); ++ MakeLValue(); setLValue(B, O, N, IsNullPtr); + } + APValue(LValueBase B, const CharUnits &O, ArrayRef Path, +- bool OnePastTheEnd, unsigned CallIndex, bool IsNullPtr = false) ++ bool OnePastTheEnd, bool IsNullPtr = false) + : Kind(Uninitialized) { +- MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex, IsNullPtr); ++ MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); + } + APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { + MakeArray(InitElts, Size); +@@ -255,6 +306,7 @@ class APValue { + bool hasLValuePath() const; + ArrayRef getLValuePath() const; + unsigned getLValueCallIndex() const; ++ unsigned getLValueVersion() const; + bool isNullPointer() const; + + APValue &getVectorElt(unsigned I) { +@@ -376,10 +428,10 @@ class APValue { + ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); + } + void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, +- unsigned CallIndex, bool IsNullPtr); ++ bool IsNullPtr); + void setLValue(LValueBase B, const CharUnits &O, + ArrayRef Path, bool OnePastTheEnd, +- unsigned CallIndex, bool IsNullPtr); ++ bool IsNullPtr); + void setUnion(const FieldDecl *Field, const APValue &Value) { + assert(isUnion() && "Invalid accessor"); + ((UnionData*)(char*)Data.buffer)->Field = Field; +@@ -451,4 +503,14 @@ class APValue { + + } // end namespace clang. + ++namespace llvm { ++template<> struct DenseMapInfo { ++ static clang::APValue::LValueBase getEmptyKey(); ++ static clang::APValue::LValueBase getTombstoneKey(); ++ static unsigned getHashValue(const clang::APValue::LValueBase &Base); ++ static bool isEqual(const clang::APValue::LValueBase &LHS, ++ const clang::APValue::LValueBase &RHS); ++}; ++} ++ + #endif +Index: tools/clang/lib/AST/APValue.cpp +=================================================================== +--- tools/clang/lib/AST/APValue.cpp (revision 342280) ++++ tools/clang/lib/AST/APValue.cpp (revision 342281) +@@ -23,14 +23,57 @@ using namespace clang; + + namespace { + struct LVBase { +- llvm::PointerIntPair BaseAndIsOnePastTheEnd; ++ APValue::LValueBase Base; + CharUnits Offset; + unsigned PathLength; +- unsigned CallIndex; +- bool IsNullPtr; ++ bool IsNullPtr : 1; ++ bool IsOnePastTheEnd : 1; + }; + } + ++void *APValue::LValueBase::getOpaqueValue() const { ++ return Ptr.getOpaqueValue(); ++} ++ ++bool APValue::LValueBase::isNull() const { ++ return Ptr.isNull(); ++} ++ ++APValue::LValueBase::operator bool () const { ++ return static_cast(Ptr); ++} ++ ++clang::APValue::LValueBase ++llvm::DenseMapInfo::getEmptyKey() { ++ return clang::APValue::LValueBase( ++ DenseMapInfo::getEmptyKey(), ++ DenseMapInfo::getEmptyKey(), ++ DenseMapInfo::getEmptyKey()); ++} ++ ++clang::APValue::LValueBase ++llvm::DenseMapInfo::getTombstoneKey() { ++ return clang::APValue::LValueBase( ++ DenseMapInfo::getTombstoneKey(), ++ DenseMapInfo::getTombstoneKey(), ++ DenseMapInfo::getTombstoneKey()); ++} ++ ++unsigned llvm::DenseMapInfo::getHashValue( ++ const clang::APValue::LValueBase &Base) { ++ llvm::FoldingSetNodeID ID; ++ ID.AddPointer(Base.getOpaqueValue()); ++ ID.AddInteger(Base.getCallIndex()); ++ ID.AddInteger(Base.getVersion()); ++ return ID.ComputeHash(); ++} ++ ++bool llvm::DenseMapInfo::isEqual( ++ const clang::APValue::LValueBase &LHS, ++ const clang::APValue::LValueBase &RHS) { ++ return LHS == RHS; ++} ++ + struct APValue::LV : LVBase { + static const unsigned InlinePathSpace = + (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry); +@@ -150,11 +193,10 @@ APValue::APValue(const APValue &RHS) : Kind(Uninit + MakeLValue(); + if (RHS.hasLValuePath()) + setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), +- RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex(), +- RHS.isNullPointer()); ++ RHS.isLValueOnePastTheEnd(), RHS.isNullPointer()); + else + setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), +- RHS.getLValueCallIndex(), RHS.isNullPointer()); ++ RHS.isNullPointer()); + break; + case Array: + MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); +@@ -552,12 +594,12 @@ std::string APValue::getAsString(ASTContext &Ctx, + + const APValue::LValueBase APValue::getLValueBase() const { + assert(isLValue() && "Invalid accessor"); +- return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getPointer(); ++ return ((const LV*)(const void*)Data.buffer)->Base; + } + + bool APValue::isLValueOnePastTheEnd() const { + assert(isLValue() && "Invalid accessor"); +- return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getInt(); ++ return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd; + } + + CharUnits &APValue::getLValueOffset() { +@@ -578,9 +620,14 @@ ArrayRef APValue::getLVa + + unsigned APValue::getLValueCallIndex() const { + assert(isLValue() && "Invalid accessor"); +- return ((const LV*)(const char*)Data.buffer)->CallIndex; ++ return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex(); + } + ++unsigned APValue::getLValueVersion() const { ++ assert(isLValue() && "Invalid accessor"); ++ return ((const LV*)(const char*)Data.buffer)->Base.getVersion(); ++} ++ + bool APValue::isNullPointer() const { + assert(isLValue() && "Invalid usage"); + return ((const LV*)(const char*)Data.buffer)->IsNullPtr; +@@ -587,13 +634,12 @@ bool APValue::isNullPointer() const { + } + + void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, +- unsigned CallIndex, bool IsNullPtr) { ++ bool IsNullPtr) { + assert(isLValue() && "Invalid accessor"); + LV &LVal = *((LV*)(char*)Data.buffer); +- LVal.BaseAndIsOnePastTheEnd.setPointer(B); +- LVal.BaseAndIsOnePastTheEnd.setInt(false); ++ LVal.Base = B; ++ LVal.IsOnePastTheEnd = false; + LVal.Offset = O; +- LVal.CallIndex = CallIndex; + LVal.resizePath((unsigned)-1); + LVal.IsNullPtr = IsNullPtr; + } +@@ -600,13 +646,12 @@ void APValue::setLValue(LValueBase B, const CharUn + + void APValue::setLValue(LValueBase B, const CharUnits &O, + ArrayRef Path, bool IsOnePastTheEnd, +- unsigned CallIndex, bool IsNullPtr) { ++ bool IsNullPtr) { + assert(isLValue() && "Invalid accessor"); + LV &LVal = *((LV*)(char*)Data.buffer); +- LVal.BaseAndIsOnePastTheEnd.setPointer(B); +- LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd); ++ LVal.Base = B; ++ LVal.IsOnePastTheEnd = IsOnePastTheEnd; + LVal.Offset = O; +- LVal.CallIndex = CallIndex; + LVal.resizePath(Path.size()); + memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); + LVal.IsNullPtr = IsNullPtr; +Index: tools/clang/lib/AST/ExprConstant.cpp +=================================================================== +--- tools/clang/lib/AST/ExprConstant.cpp (revision 342280) ++++ tools/clang/lib/AST/ExprConstant.cpp (revision 342281) +@@ -446,8 +446,8 @@ namespace { + + // Note that we intentionally use std::map here so that references to + // values are stable. +- typedef std::map MapTy; +- typedef MapTy::const_iterator temp_iterator; ++ typedef std::pair MapKeyTy; ++ typedef std::map MapTy; + /// Temporaries - Temporary lvalues materialized within this stack frame. + MapTy Temporaries; + +@@ -457,6 +457,20 @@ namespace { + /// Index - The call index of this call. + unsigned Index; + ++ /// The stack of integers for tracking version numbers for temporaries. ++ SmallVector TempVersionStack = {1}; ++ unsigned CurTempVersion = TempVersionStack.back(); ++ ++ unsigned getTempVersion() const { return TempVersionStack.back(); } ++ ++ void pushTempVersion() { ++ TempVersionStack.push_back(++CurTempVersion); ++ } ++ ++ void popTempVersion() { ++ TempVersionStack.pop_back(); ++ } ++ + // FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact + // on the overall stack usage of deeply-recursing constexpr evaluataions. + // (We should cache this map rather than recomputing it repeatedly.) +@@ -473,10 +487,36 @@ namespace { + APValue *Arguments); + ~CallStackFrame(); + +- APValue *getTemporary(const void *Key) { +- MapTy::iterator I = Temporaries.find(Key); +- return I == Temporaries.end() ? nullptr : &I->second; ++ // Return the temporary for Key whose version number is Version. ++ APValue *getTemporary(const void *Key, unsigned Version) { ++ MapKeyTy KV(Key, Version); ++ auto LB = Temporaries.lower_bound(KV); ++ if (LB != Temporaries.end() && LB->first == KV) ++ return &LB->second; ++ // Pair (Key,Version) wasn't found in the map. Check that no elements ++ // in the map have 'Key' as their key. ++ assert((LB == Temporaries.end() || LB->first.first != Key) && ++ (LB == Temporaries.begin() || std::prev(LB)->first.first != Key) && ++ "Element with key 'Key' found in map"); ++ return nullptr; + } ++ ++ // Return the current temporary for Key in the map. ++ APValue *getCurrentTemporary(const void *Key) { ++ auto UB = Temporaries.upper_bound(MapKeyTy(Key, UINT_MAX)); ++ if (UB != Temporaries.begin() && std::prev(UB)->first.first == Key) ++ return &std::prev(UB)->second; ++ return nullptr; ++ } ++ ++ // Return the version number of the current temporary for Key. ++ unsigned getCurrentTemporaryVersion(const void *Key) const { ++ auto UB = Temporaries.upper_bound(MapKeyTy(Key, UINT_MAX)); ++ if (UB != Temporaries.begin() && std::prev(UB)->first.first == Key) ++ return std::prev(UB)->first.second; ++ return 0; ++ } ++ + APValue &createTemporary(const void *Key, bool IsLifetimeExtended); + }; + +@@ -606,7 +646,8 @@ namespace { + + /// EvaluatingObject - Pair of the AST node that an lvalue represents and + /// the call index that that lvalue was allocated in. +- typedef std::pair EvaluatingObject; ++ typedef std::pair> ++ EvaluatingObject; + + /// EvaluatingConstructors - Set of objects that are currently being + /// constructed. +@@ -625,8 +666,10 @@ namespace { + } + }; + +- bool isEvaluatingConstructor(APValue::LValueBase Decl, unsigned CallIndex) { +- return EvaluatingConstructors.count(EvaluatingObject(Decl, CallIndex)); ++ bool isEvaluatingConstructor(APValue::LValueBase Decl, unsigned CallIndex, ++ unsigned Version) { ++ return EvaluatingConstructors.count( ++ EvaluatingObject(Decl, {CallIndex, Version})); + } + + /// The current array initialization index, if we're performing array +@@ -722,7 +765,7 @@ namespace { + void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { + EvaluatingDecl = Base; + EvaluatingDeclValue = &Value; +- EvaluatingConstructors.insert({Base, 0}); ++ EvaluatingConstructors.insert({Base, {0, 0}}); + } + + const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); } +@@ -1086,11 +1129,16 @@ namespace { + unsigned OldStackSize; + public: + ScopeRAII(EvalInfo &Info) +- : Info(Info), OldStackSize(Info.CleanupStack.size()) {} ++ : Info(Info), OldStackSize(Info.CleanupStack.size()) { ++ // Push a new temporary version. This is needed to distinguish between ++ // temporaries created in different iterations of a loop. ++ Info.CurrentCall->pushTempVersion(); ++ } + ~ScopeRAII() { + // Body moved to a static method to encourage the compiler to inline away + // instances of this class. + cleanup(Info, OldStackSize); ++ Info.CurrentCall->popTempVersion(); + } + private: + static void cleanup(EvalInfo &Info, unsigned OldStackSize) { +@@ -1170,7 +1218,8 @@ CallStackFrame::~CallStackFrame() { + + APValue &CallStackFrame::createTemporary(const void *Key, + bool IsLifetimeExtended) { +- APValue &Result = Temporaries[Key]; ++ unsigned Version = Info.CurrentCall->getTempVersion(); ++ APValue &Result = Temporaries[MapKeyTy(Key, Version)]; + assert(Result.isUninit() && "temporary created multiple times"); + Info.CleanupStack.push_back(Cleanup(&Result, IsLifetimeExtended)); + return Result; +@@ -1262,27 +1311,27 @@ namespace { + struct LValue { + APValue::LValueBase Base; + CharUnits Offset; +- unsigned InvalidBase : 1; +- unsigned CallIndex : 31; + SubobjectDesignator Designator; +- bool IsNullPtr; ++ bool IsNullPtr : 1; ++ bool InvalidBase : 1; + + const APValue::LValueBase getLValueBase() const { return Base; } + CharUnits &getLValueOffset() { return Offset; } + const CharUnits &getLValueOffset() const { return Offset; } +- unsigned getLValueCallIndex() const { return CallIndex; } + SubobjectDesignator &getLValueDesignator() { return Designator; } + const SubobjectDesignator &getLValueDesignator() const { return Designator;} + bool isNullPointer() const { return IsNullPtr;} + ++ unsigned getLValueCallIndex() const { return Base.getCallIndex(); } ++ unsigned getLValueVersion() const { return Base.getVersion(); } ++ + void moveInto(APValue &V) const { + if (Designator.Invalid) +- V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex, +- IsNullPtr); ++ V = APValue(Base, Offset, APValue::NoLValuePath(), IsNullPtr); + else { + assert(!InvalidBase && "APValues can't handle invalid LValue bases"); + V = APValue(Base, Offset, Designator.Entries, +- Designator.IsOnePastTheEnd, CallIndex, IsNullPtr); ++ Designator.IsOnePastTheEnd, IsNullPtr); + } + } + void setFrom(ASTContext &Ctx, const APValue &V) { +@@ -1290,12 +1339,11 @@ namespace { + Base = V.getLValueBase(); + Offset = V.getLValueOffset(); + InvalidBase = false; +- CallIndex = V.getLValueCallIndex(); + Designator = SubobjectDesignator(Ctx, V); + IsNullPtr = V.isNullPointer(); + } + +- void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) { ++ void set(APValue::LValueBase B, bool BInvalid = false) { + #ifndef NDEBUG + // We only allow a few types of invalid bases. Enforce that here. + if (BInvalid) { +@@ -1308,7 +1356,6 @@ namespace { + Base = B; + Offset = CharUnits::fromQuantity(0); + InvalidBase = BInvalid; +- CallIndex = I; + Designator = SubobjectDesignator(getType(B)); + IsNullPtr = false; + } +@@ -1317,13 +1364,12 @@ namespace { + Base = (Expr *)nullptr; + Offset = CharUnits::fromQuantity(TargetVal); + InvalidBase = false; +- CallIndex = 0; + Designator = SubobjectDesignator(PointerTy->getPointeeType()); + IsNullPtr = true; + } + + void setInvalid(APValue::LValueBase B, unsigned I = 0) { +- set(B, I, true); ++ set(B, true); + } + + // Check that this LValue is not based on a null pointer. If it is, produce +@@ -1525,6 +1571,15 @@ static bool EvaluateAsRValue(EvalInfo &Info, const + // Misc utilities + //===----------------------------------------------------------------------===// + ++/// A helper function to create a temporary and set an LValue. ++template ++static APValue &createTemporary(const KeyTy *Key, bool IsLifetimeExtended, ++ LValue &LV, CallStackFrame &Frame) { ++ LV.set({Key, Frame.Info.CurrentCall->Index, ++ Frame.Info.CurrentCall->getTempVersion()}); ++ return Frame.createTemporary(Key, IsLifetimeExtended); ++} ++ + /// Negate an APSInt in place, converting it to a signed form if necessary, and + /// preserving its value (by extending by up to one bit as needed). + static void negateAsSigned(APSInt &Int) { +@@ -1854,7 +1909,7 @@ static const ValueDecl *GetLValueBaseDecl(const LV + } + + static bool IsLiteralLValue(const LValue &Value) { +- if (Value.CallIndex) ++ if (Value.getLValueCallIndex()) + return false; + const Expr *E = Value.Base.dyn_cast(); + return E && !isa(E); +@@ -2404,7 +2459,7 @@ static bool handleLValueToRValueConversion(EvalInf + /// \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, +- APValue *&Result) { ++ APValue *&Result, const LValue *LVal) { + + // If this is a parameter to an active constexpr function call, perform + // argument substitution. +@@ -2423,7 +2478,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, co + + // If this is a local variable, dig out its value. + if (Frame) { +- Result = Frame->getTemporary(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 +@@ -3000,8 +3056,8 @@ static CompleteObject findCompleteObject(EvalInfo + } + + CallStackFrame *Frame = nullptr; +- if (LVal.CallIndex) { +- Frame = Info.getCallFrame(LVal.CallIndex); ++ if (LVal.getLValueCallIndex()) { ++ Frame = Info.getCallFrame(LVal.getLValueCallIndex()); + if (!Frame) { + Info.FFDiag(E, diag::note_constexpr_lifetime_ended, 1) + << AK << LVal.Base.is(); +@@ -3113,7 +3169,7 @@ static CompleteObject findCompleteObject(EvalInfo + } + } + +- if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal)) ++ if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal, &LVal)) + return CompleteObject(); + } else { + const Expr *Base = LVal.Base.dyn_cast(); +@@ -3155,7 +3211,7 @@ static CompleteObject findCompleteObject(EvalInfo + return CompleteObject(); + } + } else { +- BaseVal = Frame->getTemporary(Base); ++ BaseVal = Frame->getTemporary(Base, LVal.Base.getVersion()); + assert(BaseVal && "missing value for temporary"); + } + +@@ -3175,7 +3231,9 @@ static CompleteObject findCompleteObject(EvalInfo + // During the construction of an object, it is not yet 'const'. + // FIXME: This doesn't do quite the right thing for const subobjects of the + // object under construction. +- if (Info.isEvaluatingConstructor(LVal.getLValueBase(), LVal.CallIndex)) { ++ if (Info.isEvaluatingConstructor(LVal.getLValueBase(), ++ LVal.getLValueCallIndex(), ++ LVal.getLValueVersion())) { + BaseType = Info.Ctx.getCanonicalType(BaseType); + BaseType.removeLocalConst(); + } +@@ -3212,7 +3270,7 @@ static bool handleLValueToRValueConversion(EvalInf + + // Check for special cases where there is no existing APValue to look at. + const Expr *Base = LVal.Base.dyn_cast(); +- if (Base && !LVal.CallIndex && !Type.isVolatileQualified()) { ++ if (Base && !LVal.getLValueCallIndex() && !Type.isVolatileQualified()) { + if (const CompoundLiteralExpr *CLE = dyn_cast(Base)) { + // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the + // initializer until now for such expressions. Such an expression can't be +@@ -3715,8 +3773,7 @@ static bool EvaluateVarDecl(EvalInfo &Info, const + return true; + + LValue Result; +- Result.set(VD, Info.CurrentCall->Index); +- APValue &Val = Info.CurrentCall->createTemporary(VD, true); ++ APValue &Val = createTemporary(VD, true, Result, *Info.CurrentCall); + + const Expr *InitE = VD->getInit(); + if (!InitE) { +@@ -3772,6 +3829,19 @@ struct StmtResult { + /// The location containing the result, if any (used to support RVO). + const LValue *Slot; + }; ++ ++struct TempVersionRAII { ++ CallStackFrame &Frame; ++ ++ TempVersionRAII(CallStackFrame &Frame) : Frame(Frame) { ++ Frame.pushTempVersion(); ++ } ++ ++ ~TempVersionRAII() { ++ Frame.popTempVersion(); ++ } ++}; ++ + } + + static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, +@@ -4329,7 +4399,8 @@ static bool HandleConstructorCall(const Expr *E, c + } + + EvalInfo::EvaluatingConstructorRAII EvalObj( +- Info, {This.getLValueBase(), This.CallIndex}); ++ Info, {This.getLValueBase(), ++ {This.getLValueCallIndex(), This.getLValueVersion()}}); + CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues); + + // FIXME: Creating an APValue just to hold a nonexistent return value is +@@ -4578,9 +4649,12 @@ class ExprEvaluatorBase + { return StmtVisitorTy::Visit(E->getResultExpr()); } + bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) + { return StmtVisitorTy::Visit(E->getReplacement()); } +- bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) +- { return StmtVisitorTy::Visit(E->getExpr()); } ++ bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { ++ TempVersionRAII RAII(*Info.CurrentCall); ++ return StmtVisitorTy::Visit(E->getExpr()); ++ } + bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { ++ TempVersionRAII RAII(*Info.CurrentCall); + // The initializer may not have been parsed yet, or might be erroneous. + if (!E->getExpr()) + return Error(E); +@@ -4658,7 +4732,7 @@ class ExprEvaluatorBase + } + + bool VisitOpaqueValueExpr(const OpaqueValueExpr *E) { +- if (APValue *Value = Info.CurrentCall->getTemporary(E)) ++ if (APValue *Value = Info.CurrentCall->getCurrentTemporary(E)) + return DerivedSuccess(*Value, E); + + const Expr *Source = E->getSourceExpr(); +@@ -5216,7 +5290,8 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr + + if (!VD->getType()->isReferenceType()) { + if (Frame) { +- Result.set(VD, Frame->Index); ++ Result.set({VD, Frame->Index, ++ Info.CurrentCall->getCurrentTemporaryVersion(VD)}); + return true; + } + return Success(VD); +@@ -5223,7 +5298,7 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr + } + + APValue *V; +- if (!evaluateVarDeclInit(Info, E, VD, Frame, V)) ++ if (!evaluateVarDeclInit(Info, E, VD, Frame, V, nullptr)) + return false; + if (V->isUninit()) { + if (!Info.checkingPotentialConstantExpression()) +@@ -5255,9 +5330,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporar + *Value = APValue(); + Result.set(E); + } else { +- Value = &Info.CurrentCall-> +- createTemporary(E, E->getStorageDuration() == SD_Automatic); +- Result.set(E, Info.CurrentCall->Index); ++ Value = &createTemporary(E, E->getStorageDuration() == SD_Automatic, Result, ++ *Info.CurrentCall); + } + + QualType Type = Inner->getType(); +@@ -5736,7 +5810,6 @@ bool PointerExprEvaluator::VisitCastExpr(const Cas + Result.Base = (Expr*)nullptr; + Result.InvalidBase = false; + Result.Offset = CharUnits::fromQuantity(N); +- Result.CallIndex = 0; + Result.Designator.setInvalid(); + Result.IsNullPtr = false; + return true; +@@ -5752,9 +5825,9 @@ bool PointerExprEvaluator::VisitCastExpr(const Cas + if (!evaluateLValue(SubExpr, Result)) + return false; + } else { +- Result.set(SubExpr, Info.CurrentCall->Index); +- if (!EvaluateInPlace(Info.CurrentCall->createTemporary(SubExpr, false), +- Info, Result, SubExpr)) ++ APValue &Value = createTemporary(SubExpr, false, Result, ++ *Info.CurrentCall); ++ if (!EvaluateInPlace(Value, Info, Result, SubExpr)) + return false; + } + // The result is a pointer to the first element of the array. +@@ -6520,9 +6593,8 @@ class TemporaryExprEvaluator + + /// Visit an expression which constructs the value of this temporary. + bool VisitConstructExpr(const Expr *E) { +- Result.set(E, Info.CurrentCall->Index); +- return EvaluateInPlace(Info.CurrentCall->createTemporary(E, false), +- Info, Result, E); ++ APValue &Value = createTemporary(E, false, Result, *Info.CurrentCall); ++ return EvaluateInPlace(Value, Info, Result, E); + } + + bool VisitCastExpr(const CastExpr *E) { +@@ -8007,7 +8079,8 @@ static bool HasSameBase(const LValue &A, const LVa + } + + return IsGlobalLValue(A.getLValueBase()) || +- A.getLValueCallIndex() == B.getLValueCallIndex(); ++ (A.getLValueCallIndex() == B.getLValueCallIndex() && ++ A.getLValueVersion() == B.getLValueVersion()); + } + + /// \brief Determine whether this is a pointer past the end of the complete +@@ -9941,15 +10014,13 @@ static bool Evaluate(APValue &Result, EvalInfo &In + return true; + } else if (T->isArrayType()) { + LValue LV; +- LV.set(E, Info.CurrentCall->Index); +- APValue &Value = Info.CurrentCall->createTemporary(E, false); ++ APValue &Value = createTemporary(E, false, LV, *Info.CurrentCall); + if (!EvaluateArray(E, LV, Value, Info)) + return false; + Result = Value; + } else if (T->isRecordType()) { + LValue LV; +- LV.set(E, Info.CurrentCall->Index); +- APValue &Value = Info.CurrentCall->createTemporary(E, false); ++ APValue &Value = createTemporary(E, false, LV, *Info.CurrentCall); + if (!EvaluateRecord(E, LV, Value, Info)) + return false; + Result = Value; +@@ -9963,8 +10034,7 @@ static bool Evaluate(APValue &Result, EvalInfo &In + QualType Unqual = T.getAtomicUnqualifiedType(); + if (Unqual->isArrayType() || Unqual->isRecordType()) { + LValue LV; +- LV.set(E, Info.CurrentCall->Index); +- APValue &Value = Info.CurrentCall->createTemporary(E, false); ++ APValue &Value = createTemporary(E, false, LV, *Info.CurrentCall); + if (!EvaluateAtomic(E, &LV, Value, Info)) + return false; + } else { +@@ -10786,7 +10856,7 @@ bool Expr::isPotentialConstantExpr(const FunctionD + // is a temporary being used as the 'this' pointer. + LValue This; + ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy); +- This.set(&VIE, Info.CurrentCall->Index); ++ This.set({&VIE, Info.CurrentCall->Index}); + + ArrayRef Args; + +Index: tools/clang/test/SemaCXX/constant-expression-cxx1y.cpp +=================================================================== +--- tools/clang/test/SemaCXX/constant-expression-cxx1y.cpp (revision 342280) ++++ tools/clang/test/SemaCXX/constant-expression-cxx1y.cpp (revision 342281) +@@ -852,7 +852,6 @@ namespace Lifetime { + static_assert(h(2) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} + static_assert(h(3) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} + +- // FIXME: This function should be treated as non-constant. + constexpr void lifetime_versus_loops() { + int *p = 0; + for (int i = 0; i != 2; ++i) { +@@ -862,10 +861,10 @@ namespace Lifetime { + if (i) + // This modifies the 'n' from the previous iteration of the loop outside + // its lifetime. +- ++*q; ++ ++*q; // expected-note {{increment of object outside its lifetime}} + } + } +- static_assert((lifetime_versus_loops(), true), ""); ++ static_assert((lifetime_versus_loops(), true), ""); // expected-error {{constant expression}} expected-note {{in call}} + } + + namespace Bitfields { +Index: tools/clang/test/SemaCXX/constexpr-default-arg.cpp +=================================================================== +--- tools/clang/test/SemaCXX/constexpr-default-arg.cpp (nonexistent) ++++ tools/clang/test/SemaCXX/constexpr-default-arg.cpp (revision 342281) +@@ -0,0 +1,38 @@ ++// RUN: %clang_cc1 -std=c++1y -S -o - -emit-llvm -verify %s ++ ++namespace default_arg_temporary { ++ ++constexpr bool equals(const float& arg = 1.0f) { ++ return arg == 1.0f; ++} ++ ++constexpr const int &x(const int &p = 0) { ++ return p; ++} ++ ++struct S { ++ constexpr S(const int &a = 0) {} ++}; ++ ++void test_default_arg2() { ++ // This piece of code used to cause an assertion failure in ++ // CallStackFrame::createTemporary because the same MTE is used to initilize ++ // both elements of the array (see PR33140). ++ constexpr S s[2] = {}; ++ ++ // This piece of code used to cause an assertion failure in ++ // CallStackFrame::createTemporary because multiple CXXDefaultArgExpr share ++ // the same MTE (see PR33140). ++ static_assert(equals() && equals(), ""); ++ ++ // Test that constant expression evaluation produces distinct lvalues for ++ // each call. ++ static_assert(&x() != &x(), ""); ++} ++ ++// Check that multiple CXXDefaultInitExprs don't cause an assertion failure. ++struct A { int &&r = 0; }; // expected-warning {{binding reference member}} // expected-note {{reference member declared here}} ++struct B { A x, y; }; ++B b = {}; ++ ++}