diff options
Diffstat (limited to 'devel/llvm60/files/clang')
12 files changed, 1209 insertions, 0 deletions
diff --git a/devel/llvm60/files/clang/patch-fformat_extensions.diff b/devel/llvm60/files/clang/patch-fformat_extensions.diff new file mode 100644 index 000000000000..69093d923b6f --- /dev/null +++ b/devel/llvm60/files/clang/patch-fformat_extensions.diff @@ -0,0 +1,44 @@ +diff -ruN tools/clang/include/clang/Basic/LangOptions.def tools/clang/include/clang/Basic/LangOptions.def +--- tools/clang/include/clang/Basic/LangOptions.def 2015-07-30 22:47:41 UTC ++++ tools/clang/include/clang/Basic/LangOptions.def +@@ -114,6 +114,7 @@ + LANGOPT(RTTIData , 1, 1, "emit run-time type information data") + LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout") + LANGOPT(Freestanding, 1, 0, "freestanding implementation") ++LANGOPT(FormatExtensions , 1, 0, "FreeBSD format extensions") + LANGOPT(NoBuiltin , 1, 0, "disable builtin functions") + LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions") + LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly") +diff -ruN tools/clang/include/clang/Driver/Options.td tools/clang/include/clang/Driver/Options.td +--- tools/clang/include/clang/Driver/Options.td 2015-07-30 22:47:41 UTC ++++ tools/clang/include/clang/Driver/Options.td +@@ -644,6 +644,8 @@ + + def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Assert that the compilation takes place in a freestanding environment">; ++def fformat_extensions: Flag<["-"], "fformat-extensions">, Group<f_Group>, Flags<[CC1Option]>, ++ HelpText<"Enable FreeBSD kernel specific format string extensions">; + def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Allow GNU-extension keywords regardless of language standard">; + def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>, +--- tools/clang/lib/Driver/ToolChains/Clang.cpp.orig 2017-09-14 19:36:28.212240000 +0100 ++++ tools/clang/lib/Driver/ToolChains/Clang.cpp 2017-09-14 19:35:59.296165000 +0100 +@@ -3202,6 +3202,7 @@ + + // Forward -f (flag) options which we can pass directly. + Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls); ++ Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions); + Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); + Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names); + // Emulated TLS is enabled by default on Android and OpenBSD, and can be enabled +diff -ruN tools/clang/lib/Frontend/CompilerInvocation.cpp tools/clang/lib/Frontend/CompilerInvocation.cpp +--- tools/clang/lib/Frontend/CompilerInvocation.cpp 2015-07-30 22:47:41 UTC ++++ tools/clang/lib/Frontend/CompilerInvocation.cpp +@@ -1543,6 +1543,7 @@ + Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false); + Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); + Opts.Freestanding = Args.hasArg(OPT_ffreestanding); ++ Opts.FormatExtensions = Args.hasArg(OPT_fformat_extensions); + Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; + Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); + Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); diff --git a/devel/llvm60/files/clang/patch-fopenmp.diff b/devel/llvm60/files/clang/patch-fopenmp.diff new file mode 100644 index 000000000000..18932bd0d19c --- /dev/null +++ b/devel/llvm60/files/clang/patch-fopenmp.diff @@ -0,0 +1,14 @@ +--- tools/clang/lib/Driver/ToolChains/CommonArgs.cpp.orig 2017-05-10 17:18:56.000000000 +0000 ++++ tools/clang/lib/Driver/ToolChains/CommonArgs.cpp 2017-05-10 23:01:17.087686000 +0000 +@@ -441,7 +441,10 @@ + + switch (TC.getDriver().getOpenMPRuntime(Args)) { + case Driver::OMPRT_OMP: +- CmdArgs.push_back("-lomp"); ++ if (TC.getTriple().getOS() != llvm::Triple::FreeBSD || TC.isCrossCompiling() || !llvm::sys::fs::exists("%%LLVM_PREFIX%%/lib/libomp.so")) ++ CmdArgs.push_back("-lomp"); ++ else ++ CmdArgs.push_back("%%LLVM_PREFIX%%/lib/libomp.so"); + break; + case Driver::OMPRT_GOMP: + CmdArgs.push_back("-lgomp"); diff --git a/devel/llvm60/files/clang/patch-head-r331066.diff b/devel/llvm60/files/clang/patch-head-r331066.diff new file mode 100644 index 000000000000..7296a087bfb0 --- /dev/null +++ b/devel/llvm60/files/clang/patch-head-r331066.diff @@ -0,0 +1,40 @@ +r331066 | dim | 2018-03-16 19:04:13 +0100 (Fri, 16 Mar 2018) | 19 lines + +Pull in r321999 from upstream clang trunk (by Ivan A. Kosarev): + + [CodeGen] Fix TBAA info for accesses to members of base classes + + Resolves: + Bug 35724 - regression (r315984): fatal error: error in backend: + Broken function found (Did not see access type in access path!) + https://bugs.llvm.org/show_bug.cgi?id=35724 + + Differential Revision: https://reviews.llvm.org/D41547 + +This fixes "Did not see access type in access path" fatal errors when +building the devel/gdb port (version 8.1). + +Reported by: jbeich +PR: 226658 +MFC after: 3 months +X-MFC-With: r327952 + +Index: tools/clang/lib/CodeGen/CGExpr.cpp +=================================================================== +--- tools/clang/lib/CodeGen/CGExpr.cpp (revision 331065) ++++ tools/clang/lib/CodeGen/CGExpr.cpp (revision 331066) +@@ -1034,8 +1034,12 @@ Address CodeGenFunction::EmitPointerWithAlignment( + // Derived-to-base conversions. + case CK_UncheckedDerivedToBase: + case CK_DerivedToBase: { +- Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo, +- TBAAInfo); ++ // TODO: Support accesses to members of base classes in TBAA. For now, we ++ // conservatively pretend that the complete object is of the base class ++ // type. ++ if (TBAAInfo) ++ *TBAAInfo = CGM.getTBAAAccessInfo(E->getType()); ++ Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo); + auto Derived = CE->getSubExpr()->getType()->getPointeeCXXRecordDecl(); + return GetAddressOfBaseClass(Addr, Derived, + CE->path_begin(), CE->path_end(), diff --git a/devel/llvm60/files/clang/patch-head-r336227.diff b/devel/llvm60/files/clang/patch-head-r336227.diff new file mode 100644 index 000000000000..fd543dc38489 --- /dev/null +++ b/devel/llvm60/files/clang/patch-head-r336227.diff @@ -0,0 +1,42 @@ +r336227 | dim | 2018-07-12 21:02:59 +0200 (Thu, 12 Jul 2018) | 27 lines + +Pull in r336008 from upstream clang trunk: + + Request init/fini array on FreeBSD 12 and later + + Summary: + + It seems a bad idea to change the default in the middle of a release + branch due to possible changes in global ctor / dtor ordering between + .ctors and .init_array. With FreeBSD 11.0's release imminent lets + change the default now for FreeBSD 12 (the current development + stream) and later. + + FreeBSD rtld has supported .init_array / .fini_array for many years. + As of Jan 1 2017 all supported FreeBSD releases and branches will + have support. + + Reviewers: dim, brooks, arichardson + + Reviewed By: dim, brooks, arichardson + + Subscribers: bsdjhb, krytarowski, emaste, cfe-commits + + Differential Revision: https://reviews.llvm.org/D24867 + +Requested by: jhb +MFC after: 3 days + +Index: tools/clang/lib/Driver/ToolChains/Gnu.cpp +=================================================================== +--- tools/clang/lib/Driver/ToolChains/Gnu.cpp (revision 336226) ++++ tools/clang/lib/Driver/ToolChains/Gnu.cpp (revision 336227) +@@ -2375,6 +2375,8 @@ void Generic_ELF::addClangTargetOptions(const ArgL + bool UseInitArrayDefault = + getTriple().getArch() == llvm::Triple::aarch64 || + getTriple().getArch() == llvm::Triple::aarch64_be || ++ (getTriple().getOS() == llvm::Triple::FreeBSD && ++ getTriple().getOSMajorVersion() >= 12) || + (getTriple().getOS() == llvm::Triple::Linux && + ((!GCCInstallation.isValid() || !V.isOlderThan(4, 7, 0)) || + getTriple().isAndroid())) || diff --git a/devel/llvm60/files/clang/patch-head-r338697.diff b/devel/llvm60/files/clang/patch-head-r338697.diff new file mode 100644 index 000000000000..eb7f11e83fcf --- /dev/null +++ b/devel/llvm60/files/clang/patch-head-r338697.diff @@ -0,0 +1,104 @@ +r338697 | dim | 2018-09-15 23:22:50 +0200 (Sat, 15 Sep 2018) | 21 lines + +Pull in r325478 from upstream clang trunk (by Ivan A. Kosarev): + + [CodeGen] Initialize large arrays by copying from a global + + Currently, clang compiles explicit initializers for array elements + into series of store instructions. For large arrays of built-in types + this results in bloated output code and significant amount of time + spent on the instruction selection phase. This patch fixes the issue + by initializing such arrays with global constants that store the + binary image of the initializer. + + Differential Revision: https://reviews.llvm.org/D43181 + +This should fix a compiler hang (and excessive memory usage) while +building the science/rmg port. + +Approved by: re (kib) +Reported by: yuri@tsoft.com +See also: https://bugs.llvm.org/show_bug.cgi?id=38798 +MFC after: 3 days + +Index: tools/clang/lib/CodeGen/CGExprAgg.cpp +=================================================================== +--- tools/clang/lib/CodeGen/CGExprAgg.cpp (revision 338696) ++++ tools/clang/lib/CodeGen/CGExprAgg.cpp (revision 338697) +@@ -14,6 +14,7 @@ + #include "CodeGenFunction.h" + #include "CGObjCRuntime.h" + #include "CodeGenModule.h" ++#include "ConstantEmitter.h" + #include "clang/AST/ASTContext.h" + #include "clang/AST/DeclCXX.h" + #include "clang/AST/DeclTemplate.h" +@@ -85,7 +86,7 @@ class AggExprEmitter : public StmtVisitor<AggExprE + void EmitMoveFromReturnSlot(const Expr *E, RValue Src); + + void EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, +- QualType elementType, InitListExpr *E); ++ QualType ArrayQTy, InitListExpr *E); + + AggValueSlot::NeedsGCBarriers_t needsGC(QualType T) { + if (CGF.getLangOpts().getGC() && TypeRequiresGCollection(T)) +@@ -392,12 +393,15 @@ static bool isTrivialFiller(Expr *E) { + + /// \brief Emit initialization of an array from an initializer list. + void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, +- QualType elementType, InitListExpr *E) { ++ QualType ArrayQTy, InitListExpr *E) { + uint64_t NumInitElements = E->getNumInits(); + + uint64_t NumArrayElements = AType->getNumElements(); + assert(NumInitElements <= NumArrayElements); + ++ QualType elementType = ++ CGF.getContext().getAsArrayType(ArrayQTy)->getElementType(); ++ + // DestPtr is an array*. Construct an elementType* by drilling + // down a level. + llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); +@@ -409,6 +413,29 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr + CharUnits elementAlign = + DestPtr.getAlignment().alignmentOfArrayElement(elementSize); + ++ // Consider initializing the array by copying from a global. For this to be ++ // more efficient than per-element initialization, the size of the elements ++ // with explicit initializers should be large enough. ++ if (NumInitElements * elementSize.getQuantity() > 16 && ++ elementType.isTriviallyCopyableType(CGF.getContext())) { ++ CodeGen::CodeGenModule &CGM = CGF.CGM; ++ ConstantEmitter Emitter(CGM); ++ LangAS AS = ArrayQTy.getAddressSpace(); ++ if (llvm::Constant *C = Emitter.tryEmitForInitializer(E, AS, ArrayQTy)) { ++ auto GV = new llvm::GlobalVariable( ++ CGM.getModule(), C->getType(), ++ CGM.isTypeConstant(ArrayQTy, /* ExcludeCtorDtor= */ true), ++ llvm::GlobalValue::PrivateLinkage, C, "constinit", ++ /* InsertBefore= */ nullptr, llvm::GlobalVariable::NotThreadLocal, ++ CGM.getContext().getTargetAddressSpace(AS)); ++ Emitter.finalize(GV); ++ CharUnits Align = CGM.getContext().getTypeAlignInChars(ArrayQTy); ++ GV->setAlignment(Align.getQuantity()); ++ EmitFinalDestCopy(ArrayQTy, CGF.MakeAddrLValue(GV, ArrayQTy, Align)); ++ return; ++ } ++ } ++ + // Exception safety requires us to destroy all the + // already-constructed members if an initializer throws. + // For that, we'll need an EH cleanup. +@@ -1156,11 +1183,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExp + + // Handle initialization of an array. + if (E->getType()->isArrayType()) { +- QualType elementType = +- CGF.getContext().getAsArrayType(E->getType())->getElementType(); +- + auto AType = cast<llvm::ArrayType>(Dest.getAddress().getElementType()); +- EmitArrayInit(Dest.getAddress(), AType, elementType, E); ++ EmitArrayInit(Dest.getAddress(), AType, E->getType(), E); + return; + } + diff --git a/devel/llvm60/files/clang/patch-head-r339019.diff b/devel/llvm60/files/clang/patch-head-r339019.diff new file mode 100644 index 000000000000..240772d184c2 --- /dev/null +++ b/devel/llvm60/files/clang/patch-head-r339019.diff @@ -0,0 +1,30 @@ +r339019 | emaste | 2018-09-29 22:01:23 +0200 (Sat, 29 Sep 2018) | 15 lines + +clang: allow ifunc resolvers to accept arguments + +Previously Clang required ifunc resolution functions to take no +arguments, presumably because GCC documented ifunc resolvers as taking +no arguments. However, GCC accepts resolvers accepting arguments, and +our rtld passes CPU ID information (cpuid, hwcap, etc.) to ifunc +resolvers. Just remove the check from the in-tree compiler for our in- +tree compiler; a different (per-OS) approach may be required upstream. + +Reported by: mjg +Approved by: re (rgrimes) +MFC after: 1 week +Relnotes: Yes +Sponsored by: The FreeBSD Foundation + +Index: tools/clang/lib/CodeGen/CodeGenModule.cpp +=================================================================== +--- tools/clang/lib/CodeGen/CodeGenModule.cpp (revision 339018) ++++ tools/clang/lib/CodeGen/CodeGenModule.cpp (revision 339019) +@@ -321,8 +321,6 @@ void CodeGenModule::checkAliases() { + assert(FTy); + if (!FTy->getReturnType()->isPointerTy()) + Diags.Report(Location, diag::err_ifunc_resolver_return); +- if (FTy->getNumParams()) +- Diags.Report(Location, diag::err_ifunc_resolver_params); + } + + llvm::Constant *Aliasee = Alias->getIndirectSymbol(); diff --git a/devel/llvm60/files/clang/patch-stable12-r342281.diff b/devel/llvm60/files/clang/patch-stable12-r342281.diff new file mode 100644 index 000000000000..4a6e9f615889 --- /dev/null +++ b/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<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 = {}; ++ ++} diff --git a/devel/llvm60/files/clang/patch-tools_clang_lib_Headers_CMakeLists.txt b/devel/llvm60/files/clang/patch-tools_clang_lib_Headers_CMakeLists.txt new file mode 100644 index 000000000000..17043c6072cf --- /dev/null +++ b/devel/llvm60/files/clang/patch-tools_clang_lib_Headers_CMakeLists.txt @@ -0,0 +1,32 @@ +--- tools/clang/lib/Headers/CMakeLists.txt.orig ++++ tools/clang/lib/Headers/CMakeLists.txt +@@ -56,7 +56,6 @@ + intrin.h + inttypes.h + iso646.h +- limits.h + lwpintrin.h + lzcntintrin.h + mm3dnow.h +@@ -76,21 +75,13 @@ + s390intrin.h + shaintrin.h + smmintrin.h +- stdalign.h +- stdarg.h +- stdatomic.h +- stdbool.h +- stddef.h + __stddef_max_align_t.h +- stdint.h +- stdnoreturn.h + tbmintrin.h + tgmath.h + tmmintrin.h + unwind.h + vadefs.h + vaesintrin.h +- varargs.h + vecintrin.h + vpclmulqdqintrin.h + wmmintrin.h diff --git a/devel/llvm60/files/clang/patch-tools_clang_tools_clang-format_clang-format-sublime.py b/devel/llvm60/files/clang/patch-tools_clang_tools_clang-format_clang-format-sublime.py new file mode 100644 index 000000000000..2c8909f1e1d1 --- /dev/null +++ b/devel/llvm60/files/clang/patch-tools_clang_tools_clang-format_clang-format-sublime.py @@ -0,0 +1,14 @@ + +$FreeBSD$ + +--- tools/clang/tools/clang-format/clang-format-sublime.py.orig ++++ tools/clang/tools/clang-format/clang-format-sublime.py +@@ -18,7 +18,7 @@ + import subprocess + + # Change this to the full path if clang-format is not on the path. +-binary = 'clang-format' ++binary = 'clang-format%%LLVM_SUFFIX%%' + + # Change this to format according to other formatting styles. See the output of + # 'clang-format --help' for a list of supported styles. The default looks for diff --git a/devel/llvm60/files/clang/patch-tools_clang_tools_clang-format_clang-format.py b/devel/llvm60/files/clang/patch-tools_clang_tools_clang-format_clang-format.py new file mode 100644 index 000000000000..2962d3f4cbcb --- /dev/null +++ b/devel/llvm60/files/clang/patch-tools_clang_tools_clang-format_clang-format.py @@ -0,0 +1,11 @@ +--- tools/clang/tools/clang-format/clang-format.py.orig 2015-09-08 20:44:00 UTC ++++ tools/clang/tools/clang-format/clang-format.py +@@ -34,7 +34,7 @@ import vim + + # set g:clang_format_path to the path to clang-format if it is not on the path + # Change this to the full path if clang-format is not on the path. +-binary = 'clang-format' ++binary = 'clang-format%%LLVM_SUFFIX%%' + if vim.eval('exists("g:clang_format_path")') == "1": + binary = vim.eval('g:clang_format_path') + diff --git a/devel/llvm60/files/clang/patch-tools_clang_tools_clang-format_git-clang-format b/devel/llvm60/files/clang/patch-tools_clang_tools_clang-format_git-clang-format new file mode 100644 index 000000000000..5c5ae3581228 --- /dev/null +++ b/devel/llvm60/files/clang/patch-tools_clang_tools_clang-format_git-clang-format @@ -0,0 +1,32 @@ + +$FreeBSD$ + +--- tools/clang/tools/clang-format/git-clang-format.orig ++++ tools/clang/tools/clang-format/git-clang-format +@@ -90,7 +90,7 @@ + usage=usage, formatter_class=argparse.RawDescriptionHelpFormatter, + description=desc) + p.add_argument('--binary', +- default=config.get('clangformat.binary', 'clang-format'), ++ default=config.get('clangformat.binary', 'clang-format%%LLVM_SUFFIX%%'), + help='path to clang-format'), + p.add_argument('--commit', + default=config.get('clangformat.commit', 'HEAD'), +@@ -344,7 +344,7 @@ + + + def run_clang_format_and_save_to_tree(changed_lines, revision=None, +- binary='clang-format', style=None): ++ binary='clang-format%%LLVM_SUFFIX%%', style=None): + """Run clang-format on each file and save the result to a git tree. + + Returns the object ID (SHA-1) of the created tree.""" +@@ -397,7 +397,7 @@ + + + def clang_format_to_blob(filename, line_ranges, revision=None, +- binary='clang-format', style=None): ++ binary='clang-format%%LLVM_SUFFIX%%', style=None): + """Run clang-format on the given file and save the result to a git blob. + + Runs on the file in `revision` if not None, or on the file in the working diff --git a/devel/llvm60/files/clang/patch-tools_clang_tools_scan-build_libexec_ccc-analyzer b/devel/llvm60/files/clang/patch-tools_clang_tools_scan-build_libexec_ccc-analyzer new file mode 100644 index 000000000000..e1c65480ce2f --- /dev/null +++ b/devel/llvm60/files/clang/patch-tools_clang_tools_scan-build_libexec_ccc-analyzer @@ -0,0 +1,12 @@ +--- tools/clang/tools/scan-build/libexec/ccc-analyzer.orig ++++ tools/clang/tools/scan-build/libexec/ccc-analyzer +@@ -81,6 +81,9 @@ + if (-x "/usr/bin/xcrun") { + $UseXCRUN = 1; + } ++} elsif (`uname -s` eq "FreeBSD\n") { ++ $DefaultCCompiler = 'cc'; ++ $DefaultCXXCompiler = 'c++'; + } else { + $DefaultCCompiler = 'gcc'; + $DefaultCXXCompiler = 'g++'; |