diff options
Diffstat (limited to 'devel/llvm60/files/clang/patch-stable12-r342281.diff')
-rw-r--r-- | devel/llvm60/files/clang/patch-stable12-r342281.diff | 834 |
1 files changed, 0 insertions, 834 deletions
diff --git a/devel/llvm60/files/clang/patch-stable12-r342281.diff b/devel/llvm60/files/clang/patch-stable12-r342281.diff deleted file mode 100644 index 4a6e9f615889..000000000000 --- a/devel/llvm60/files/clang/patch-stable12-r342281.diff +++ /dev/null @@ -1,834 +0,0 @@ -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<const ValueDecl *, const Expr *> LValueBase; -+ -+ class LValueBase { -+ public: -+ typedef llvm::PointerUnion<const ValueDecl *, const Expr *> PtrTy; -+ -+ LValueBase() : CallIndex(0), Version(0) {} -+ -+ template <class T> -+ LValueBase(T P, unsigned I = 0, unsigned V = 0) -+ : Ptr(P), CallIndex(I), Version(V) {} -+ -+ template <class T> -+ bool is() const { return Ptr.is<T>(); } -+ -+ template <class T> -+ T get() const { return Ptr.get<T>(); } -+ -+ template <class T> -+ T dyn_cast() const { return Ptr.dyn_cast<T>(); } -+ -+ 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<const Decl *, 1, bool> 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<LValuePathEntry> 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<LValuePathEntry> 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<LValuePathEntry> 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<clang::APValue::LValueBase> { -+ 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<APValue::LValueBase, 1, bool> 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<bool>(Ptr); -+} -+ -+clang::APValue::LValueBase -+llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() { -+ return clang::APValue::LValueBase( -+ DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getEmptyKey(), -+ DenseMapInfo<unsigned>::getEmptyKey(), -+ DenseMapInfo<unsigned>::getEmptyKey()); -+} -+ -+clang::APValue::LValueBase -+llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() { -+ return clang::APValue::LValueBase( -+ DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getTombstoneKey(), -+ DenseMapInfo<unsigned>::getTombstoneKey(), -+ DenseMapInfo<unsigned>::getTombstoneKey()); -+} -+ -+unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::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<clang::APValue::LValueBase>::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::LValuePathEntry> 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<LValuePathEntry> 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<const void*, APValue> MapTy; -- typedef MapTy::const_iterator temp_iterator; -+ typedef std::pair<const void *, unsigned> MapKeyTy; -+ typedef std::map<MapKeyTy, APValue> 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<unsigned, 2> 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<APValue::LValueBase, unsigned> EvaluatingObject; -+ typedef std::pair<APValue::LValueBase, std::pair<unsigned, unsigned>> -+ 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 <class KeyTy> -+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<const Expr*>(); - return E && !isa<MaterializeTemporaryExpr>(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<const ValueDecl*>(); -@@ -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<const Expr*>(); -@@ -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<const Expr*>(); -- if (Base && !LVal.CallIndex && !Type.isVolatileQualified()) { -+ if (Base && !LVal.getLValueCallIndex() && !Type.isVolatileQualified()) { - if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(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<const Expr*> 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 = {}; -+ -+} |