From 2fc9bb9ce23aec06620745773d24e59944b87ffc Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Wed, 18 Mar 2020 18:20:05 +0000 Subject: [PATCH] Vendor import of llvm-project branch release/10.x llvmorg-10.0.0-rc4-5-g52c365aa9ca. --- clang/include/clang/AST/Expr.h | 22 ++++--- clang/include/clang/AST/Stmt.h | 15 +++++ clang/include/clang/Sema/Sema.h | 41 ++++++++++++- clang/include/clang/Sema/Template.h | 10 ++++ clang/lib/AST/ASTImporter.cpp | 2 +- clang/lib/Lex/Pragma.cpp | 3 + clang/lib/Sema/SemaExpr.cpp | 17 +++--- clang/lib/Sema/SemaExprCXX.cpp | 2 +- clang/lib/Sema/SemaTemplate.cpp | 54 ++++++++++++++++- clang/lib/Sema/SemaTemplateInstantiate.cpp | 6 +- clang/lib/Sema/TreeTransform.h | 23 ++++++-- clang/lib/Serialization/ASTReaderDecl.cpp | 67 ++++++++++++++++++++-- clang/lib/Serialization/ASTReaderStmt.cpp | 2 + clang/lib/Serialization/ASTWriterStmt.cpp | 2 + clang/tools/driver/driver.cpp | 22 ++++--- llvm/include/llvm/Support/ManagedStatic.h | 6 ++ llvm/include/llvm/Support/Timer.h | 5 ++ llvm/lib/Support/Timer.cpp | 4 ++ 18 files changed, 258 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index bcb960540001..7ff53ef7c653 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -3955,14 +3955,18 @@ class StmtExpr : public Expr { Stmt *SubStmt; SourceLocation LParenLoc, RParenLoc; public: - StmtExpr(CompoundStmt *substmt, QualType T, - SourceLocation lp, SourceLocation rp, bool InDependentContext) : - // Note: we treat a statement-expression in a dependent context as always - // being value- and instantiation-dependent. This matches the behavior of - // lambda-expressions and GCC. - Expr(StmtExprClass, T, VK_RValue, OK_Ordinary, - T->isDependentType(), InDependentContext, InDependentContext, false), - SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) {} + StmtExpr(CompoundStmt *SubStmt, QualType T, SourceLocation LParenLoc, + SourceLocation RParenLoc, unsigned TemplateDepth) + : // We treat a statement-expression in a dependent context as + // always being value- and instantiation-dependent. This matches the + // behavior of lambda-expressions and GCC. + Expr(StmtExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(), + TemplateDepth != 0, TemplateDepth != 0, false), + SubStmt(SubStmt), LParenLoc(LParenLoc), RParenLoc(RParenLoc) { + // FIXME: A templated statement expression should have an associated + // DeclContext so that nested declarations always have a dependent context. + StmtExprBits.TemplateDepth = TemplateDepth; + } /// Build an empty statement expression. explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { } @@ -3979,6 +3983,8 @@ class StmtExpr : public Expr { SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } + unsigned getTemplateDepth() const { return StmtExprBits.TemplateDepth; } + static bool classof(const Stmt *T) { return T->getStmtClass() == StmtExprClass; } diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 253b76941991..3aa2745937b1 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -588,6 +588,18 @@ class alignas(void *) Stmt { unsigned Kind : 2; }; + class StmtExprBitfields { + friend class ASTStmtReader; + friend class StmtExpr; + + unsigned : NumExprBits; + + /// The number of levels of template parameters enclosing this statement + /// expression. Used to determine if a statement expression remains + /// dependent after instantiation. + unsigned TemplateDepth; + }; + //===--- C++ Expression bitfields classes ---===// class CXXOperatorCallExprBitfields { @@ -996,6 +1008,9 @@ class alignas(void *) Stmt { PseudoObjectExprBitfields PseudoObjectExprBits; SourceLocExprBitfields SourceLocExprBits; + // GNU Extensions. + StmtExprBitfields StmtExprBits; + // C++ Expressions CXXOperatorCallExprBitfields CXXOperatorCallExprBits; CXXRewrittenBinaryOperatorBitfields CXXRewrittenBinaryOperatorBits; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 2b5f7c1a7203..033f7af6f2f3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -620,6 +620,15 @@ class Sema final { /// function, block, and method scopes that are currently active. SmallVector FunctionScopes; + /// The index of the first FunctionScope that corresponds to the current + /// context. + unsigned FunctionScopesStart = 0; + + ArrayRef getFunctionScopes() const { + return llvm::makeArrayRef(FunctionScopes.begin() + FunctionScopesStart, + FunctionScopes.end()); + } + /// Stack containing information needed when in C++2a an 'auto' is encountered /// in a function declaration parameter type specifier in order to invent a /// corresponding template parameter in the enclosing abbreviated function @@ -627,6 +636,16 @@ class Sema final { /// the FunctionScopes stack. SmallVector InventedParameterInfos; + /// The index of the first InventedParameterInfo that refers to the current + /// context. + unsigned InventedParameterInfosStart = 0; + + ArrayRef getInventedParameterInfos() const { + return llvm::makeArrayRef(InventedParameterInfos.begin() + + InventedParameterInfosStart, + InventedParameterInfos.end()); + } + typedef LazyVector ExtVectorDeclsType; @@ -800,17 +819,24 @@ class Sema final { DeclContext *SavedContext; ProcessingContextState SavedContextState; QualType SavedCXXThisTypeOverride; + unsigned SavedFunctionScopesStart; + unsigned SavedInventedParameterInfosStart; public: ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true) : S(S), SavedContext(S.CurContext), SavedContextState(S.DelayedDiagnostics.pushUndelayed()), - SavedCXXThisTypeOverride(S.CXXThisTypeOverride) + SavedCXXThisTypeOverride(S.CXXThisTypeOverride), + SavedFunctionScopesStart(S.FunctionScopesStart), + SavedInventedParameterInfosStart(S.InventedParameterInfosStart) { assert(ContextToPush && "pushing null context"); S.CurContext = ContextToPush; if (NewThisContext) S.CXXThisTypeOverride = QualType(); + // Any saved FunctionScopes do not refer to this context. + S.FunctionScopesStart = S.FunctionScopes.size(); + S.InventedParameterInfosStart = S.InventedParameterInfos.size(); } void pop() { @@ -818,6 +844,8 @@ class Sema final { S.CurContext = SavedContext; S.DelayedDiagnostics.popUndelayed(SavedContextState); S.CXXThisTypeOverride = SavedCXXThisTypeOverride; + S.FunctionScopesStart = SavedFunctionScopesStart; + S.InventedParameterInfosStart = SavedInventedParameterInfosStart; SavedContext = nullptr; } @@ -4924,7 +4952,9 @@ class Sema final { void ActOnStartStmtExpr(); ExprResult ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt, - SourceLocation RPLoc); // "({..})" + SourceLocation RPLoc); + ExprResult BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, + SourceLocation RPLoc, unsigned TemplateDepth); // Handle the final expression in a statement expression. ExprResult ActOnStmtExprResult(ExprResult E); void ActOnStmtExprError(); @@ -11924,6 +11954,13 @@ class Sema final { return DC; } + /// Determine the number of levels of enclosing template parameters. This is + /// only usable while parsing. Note that this does not include dependent + /// contexts in which no template parameters have yet been declared, such as + /// in a terse function template or generic lambda before the first 'auto' is + /// encountered. + unsigned getTemplateDepth(Scope *S) const; + /// To be used for checking whether the arguments being passed to /// function exceeds the number of parameters expected for it. static bool TooManyArguments(size_t NumParams, size_t NumArgs, diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 4c1cfecd4de6..47d6143bdc9a 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -95,6 +95,16 @@ class VarDecl; return TemplateArgumentLists.size(); } + /// Determine how many of the \p OldDepth outermost template parameter + /// lists would be removed by substituting these arguments. + unsigned getNewDepth(unsigned OldDepth) const { + if (OldDepth < NumRetainedOuterLevels) + return OldDepth; + if (OldDepth < getNumLevels()) + return NumRetainedOuterLevels; + return OldDepth - TemplateArgumentLists.size(); + } + /// Retrieve the template argument at a given depth and index. const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index f42361500a91..ab4e961dcd4c 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6726,7 +6726,7 @@ ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { return new (Importer.getToContext()) StmtExpr(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc, - E->isInstantiationDependent()); + E->getTemplateDepth()); } ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index a8cd18b123b0..57a95815488e 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -42,6 +42,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Timer.h" #include #include #include @@ -1038,6 +1039,8 @@ struct PragmaDebugHandler : public PragmaHandler { if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) llvm_unreachable("This is an assertion!"); } else if (II->isStr("crash")) { + llvm::Timer T("crash", "pragma crash"); + llvm::TimeRegion R(&T); if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) LLVM_BUILTIN_TRAP; } else if (II->isStr("parser_crash")) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 63d8d7506d03..04a7038d6754 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13909,7 +13909,12 @@ void Sema::ActOnStmtExprError() { } ExprResult Sema::ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt, - SourceLocation RPLoc) { // "({..})" + SourceLocation RPLoc) { + return BuildStmtExpr(LPLoc, SubStmt, RPLoc, getTemplateDepth(S)); +} + +ExprResult Sema::BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, + SourceLocation RPLoc, unsigned TemplateDepth) { assert(SubStmt && isa(SubStmt) && "Invalid action invocation!"); CompoundStmt *Compound = cast(SubStmt); @@ -13938,18 +13943,10 @@ ExprResult Sema::ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt, } } - bool IsDependentContext = false; - if (S) - IsDependentContext = S->getTemplateParamParent() != nullptr; - else - // FIXME: This is not correct when substituting inside a templated - // context that isn't a DeclContext (such as a variable template). - IsDependentContext = CurContext->isDependentContext(); - // FIXME: Check that expression type is complete/non-abstract; statement // expressions are not lvalues. Expr *ResStmtExpr = - new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc, IsDependentContext); + new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc, TemplateDepth); if (StmtExprMayBindToTemp) return MaybeBindToTemporary(ResStmtExpr); return ResStmtExpr; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 705abdb4ce72..e97171b6334e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6802,7 +6802,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { Context, SubStmt, SourceLocation(), SourceLocation()); Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(), SourceLocation(), - CurContext->isDependentContext()); + /*FIXME TemplateDepth=*/0); return MaybeCreateExprWithCleanups(E); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ad4ea2d2593d..4f577a3cf748 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -46,6 +46,48 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps, return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc()); } +unsigned Sema::getTemplateDepth(Scope *S) const { + unsigned Depth = 0; + + // Each template parameter scope represents one level of template parameter + // depth. + for (Scope *TempParamScope = S->getTemplateParamParent(); + TempParamScope && !Depth; + TempParamScope = TempParamScope->getParent()->getTemplateParamParent()) { + ++Depth; + } + + // Note that there are template parameters with the given depth. + auto ParamsAtDepth = [&](unsigned D) { Depth = std::max(Depth, D + 1); }; + + // Look for parameters of an enclosing generic lambda. We don't create a + // template parameter scope for these. + for (FunctionScopeInfo *FSI : getFunctionScopes()) { + if (auto *LSI = dyn_cast(FSI)) { + if (!LSI->TemplateParams.empty()) { + ParamsAtDepth(LSI->AutoTemplateParameterDepth); + break; + } + if (LSI->GLTemplateParameterList) { + ParamsAtDepth(LSI->GLTemplateParameterList->getDepth()); + break; + } + } + } + + // Look for parameters of an enclosing terse function template. We don't + // create a template parameter scope for these either. + for (const InventedTemplateParameterInfo &Info : + getInventedParameterInfos()) { + if (!Info.TemplateParams.empty()) { + ParamsAtDepth(Info.AutoTemplateParameterDepth); + break; + } + } + + return Depth; +} + /// \brief Determine whether the declaration found is acceptable as the name /// of a template and, if so, return that template declaration. Otherwise, /// returns null. @@ -2173,9 +2215,15 @@ struct ConvertConstructorToDeductionGuideTransform { // constructor. ExprResult NewDefArg; if (OldParam->hasDefaultArg()) { - NewDefArg = SemaRef.SubstExpr(OldParam->getDefaultArg(), Args); - if (NewDefArg.isInvalid()) - return nullptr; + // We don't care what the value is (we won't use it); just create a + // placeholder to indicate there is a default argument. + QualType ParamTy = NewDI->getType(); + NewDefArg = new (SemaRef.Context) + OpaqueValueExpr(OldParam->getDefaultArg()->getBeginLoc(), + ParamTy.getNonLValueExprType(SemaRef.Context), + ParamTy->isLValueReferenceType() ? VK_LValue : + ParamTy->isRValueReferenceType() ? VK_XValue : + VK_RValue); } ParmVarDecl *NewParam = ParmVarDecl::Create(SemaRef.Context, DC, diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 568f5404dc0b..b5d2ab1f31f2 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -922,6 +922,10 @@ namespace { this->Entity = Entity; } + unsigned TransformTemplateDepth(unsigned Depth) { + return TemplateArgs.getNewDepth(Depth); + } + bool TryExpandParameterPacks(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef Unexpanded, @@ -2162,7 +2166,7 @@ namespace { // The deduced type itself. TemplateTypeParmDecl *VisitTemplateTypeParmType( const TemplateTypeParmType *T) { - if (!T->getDecl()->isImplicit()) + if (!T->getDecl() || !T->getDecl()->isImplicit()) return nullptr; return T->getDecl(); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0892f966ac2e..805fe6684205 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -212,6 +212,14 @@ class TreeTransform { return T.isNull(); } + /// Transform a template parameter depth level. + /// + /// During a transformation that transforms template parameters, this maps + /// an old template parameter depth to a new depth. + unsigned TransformTemplateDepth(unsigned Depth) { + return Depth; + } + /// Determine whether the given call argument should be dropped, e.g., /// because it is a default argument. /// @@ -2527,8 +2535,9 @@ class TreeTransform { /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildStmtExpr(SourceLocation LParenLoc, Stmt *SubStmt, - SourceLocation RParenLoc) { - return getSema().ActOnStmtExpr(nullptr, LParenLoc, SubStmt, RParenLoc); + SourceLocation RParenLoc, unsigned TemplateDepth) { + return getSema().BuildStmtExpr(LParenLoc, SubStmt, RParenLoc, + TemplateDepth); } /// Build a new __builtin_choose_expr expression. @@ -10345,16 +10354,18 @@ TreeTransform::TransformStmtExpr(StmtExpr *E) { return ExprError(); } - if (!getDerived().AlwaysRebuild() && + unsigned OldDepth = E->getTemplateDepth(); + unsigned NewDepth = getDerived().TransformTemplateDepth(OldDepth); + + if (!getDerived().AlwaysRebuild() && OldDepth == NewDepth && SubStmt.get() == E->getSubStmt()) { // Calling this an 'error' is unintuitive, but it does the right thing. SemaRef.ActOnStmtExprError(); return SemaRef.MaybeBindToTemporary(E); } - return getDerived().RebuildStmtExpr(E->getLParenLoc(), - SubStmt.get(), - E->getRParenLoc()); + return getDerived().RebuildStmtExpr(E->getLParenLoc(), SubStmt.get(), + E->getRParenLoc(), NewDepth); } template diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index b7000a6956d9..e3eea3c6f860 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2867,7 +2867,8 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) { return LocalOffset + M.GlobalBitOffset; } -static bool isSameTemplateParameterList(const TemplateParameterList *X, +static bool isSameTemplateParameterList(const ASTContext &C, + const TemplateParameterList *X, const TemplateParameterList *Y); /// Determine whether two template parameters are similar enough @@ -2879,7 +2880,32 @@ static bool isSameTemplateParameter(const NamedDecl *X, if (const auto *TX = dyn_cast(X)) { const auto *TY = cast(Y); - return TX->isParameterPack() == TY->isParameterPack(); + if (TX->isParameterPack() != TY->isParameterPack()) + return false; + if (TX->hasTypeConstraint() != TY->hasTypeConstraint()) + return false; + if (TX->hasTypeConstraint()) { + const TypeConstraint *TXTC = TX->getTypeConstraint(); + const TypeConstraint *TYTC = TY->getTypeConstraint(); + if (TXTC->getNamedConcept() != TYTC->getNamedConcept()) + return false; + if (TXTC->hasExplicitTemplateArgs() != TYTC->hasExplicitTemplateArgs()) + return false; + if (TXTC->hasExplicitTemplateArgs()) { + const auto *TXTCArgs = TXTC->getTemplateArgsAsWritten(); + const auto *TYTCArgs = TYTC->getTemplateArgsAsWritten(); + if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs) + return false; + llvm::FoldingSetNodeID XID, YID; + for (const auto &ArgLoc : TXTCArgs->arguments()) + ArgLoc.getArgument().Profile(XID, X->getASTContext()); + for (const auto &ArgLoc : TYTCArgs->arguments()) + ArgLoc.getArgument().Profile(YID, Y->getASTContext()); + if (XID != YID) + return false; + } + } + return true; } if (const auto *TX = dyn_cast(X)) { @@ -2891,7 +2917,8 @@ static bool isSameTemplateParameter(const NamedDecl *X, const auto *TX = cast(X); const auto *TY = cast(Y); return TX->isParameterPack() == TY->isParameterPack() && - isSameTemplateParameterList(TX->getTemplateParameters(), + isSameTemplateParameterList(TX->getASTContext(), + TX->getTemplateParameters(), TY->getTemplateParameters()); } @@ -2944,7 +2971,8 @@ static bool isSameQualifier(const NestedNameSpecifier *X, /// Determine whether two template parameter lists are similar enough /// that they may be used in declarations of the same template. -static bool isSameTemplateParameterList(const TemplateParameterList *X, +static bool isSameTemplateParameterList(const ASTContext &C, + const TemplateParameterList *X, const TemplateParameterList *Y) { if (X->size() != Y->size()) return false; @@ -2953,6 +2981,18 @@ static bool isSameTemplateParameterList(const TemplateParameterList *X, if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I))) return false; + const Expr *XRC = X->getRequiresClause(); + const Expr *YRC = Y->getRequiresClause(); + if (!XRC != !YRC) + return false; + if (XRC) { + llvm::FoldingSetNodeID XRCID, YRCID; + XRC->Profile(XRCID, C, /*Canonical=*/true); + YRC->Profile(YRCID, C, /*Canonical=*/true); + if (XRCID != YRCID) + return false; + } + return true; } @@ -2989,7 +3029,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A, return true; } -/// Determine whether the two declarations refer to the same entity. +/// Determine whether the two declarations refer to the same entity.pr static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); @@ -3064,6 +3104,19 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { } ASTContext &C = FuncX->getASTContext(); + + const Expr *XRC = FuncX->getTrailingRequiresClause(); + const Expr *YRC = FuncY->getTrailingRequiresClause(); + if (!XRC != !YRC) + return false; + if (XRC) { + llvm::FoldingSetNodeID XRCID, YRCID; + XRC->Profile(XRCID, C, /*Canonical=*/true); + YRC->Profile(YRCID, C, /*Canonical=*/true); + if (XRCID != YRCID) + return false; + } + auto GetTypeAsWritten = [](const FunctionDecl *FD) { // Map to the first declaration that we've already merged into this one. // The TSI of redeclarations might not match (due to calling conventions @@ -3087,6 +3140,7 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { return true; return false; } + return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() && hasSameOverloadableAttrs(FuncX, FuncY); } @@ -3126,7 +3180,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { const auto *TemplateY = cast(Y); return isSameEntity(TemplateX->getTemplatedDecl(), TemplateY->getTemplatedDecl()) && - isSameTemplateParameterList(TemplateX->getTemplateParameters(), + isSameTemplateParameterList(TemplateX->getASTContext(), + TemplateX->getTemplateParameters(), TemplateY->getTemplateParameters()); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 5dd0ef9d43c3..c38b3ad18467 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -754,6 +754,7 @@ void ASTStmtReader::VisitConceptSpecializationExpr( E->TemplateKWLoc = Record.readSourceLocation(); E->ConceptName = Record.readDeclarationNameInfo(); E->NamedConcept = readDeclAs(); + E->FoundDecl = Record.readDeclAs(); E->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); llvm::SmallVector Args; for (unsigned I = 0; I < NumTemplateArgs; ++I) @@ -1190,6 +1191,7 @@ void ASTStmtReader::VisitStmtExpr(StmtExpr *E) { E->setLParenLoc(readSourceLocation()); E->setRParenLoc(readSourceLocation()); E->setSubStmt(cast_or_null(Record.readSubStmt())); + E->StmtExprBits.TemplateDepth = Record.readInt(); } void ASTStmtReader::VisitChooseExpr(ChooseExpr *E) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 1b118c257a4c..8519a4df019d 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -429,6 +429,7 @@ void ASTStmtWriter::VisitConceptSpecializationExpr( Record.AddSourceLocation(E->getTemplateKWLoc()); Record.AddDeclarationNameInfo(E->getConceptNameInfo()); Record.AddDeclRef(E->getNamedConcept()); + Record.AddDeclRef(E->getFoundDecl()); Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten()); for (const TemplateArgument &Arg : TemplateArgs) Record.AddTemplateArgument(Arg); @@ -1068,6 +1069,7 @@ void ASTStmtWriter::VisitStmtExpr(StmtExpr *E) { Record.AddStmt(E->getSubStmt()); Record.AddSourceLocation(E->getLParenLoc()); Record.AddSourceLocation(E->getRParenLoc()); + Record.push_back(E->getTemplateDepth()); Code = serialization::EXPR_STMT; } diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 4457e40ff04b..7b3968341cc7 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -30,6 +30,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" +#include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/ErrorHandling.h" @@ -491,6 +492,7 @@ int main(int argc_, const char **argv_) { std::unique_ptr C(TheDriver.BuildCompilation(argv)); int Res = 1; + bool IsCrash = false; if (C && !C->containsError()) { SmallVector, 4> FailingCommands; Res = TheDriver.ExecuteCompilation(*C, FailingCommands); @@ -517,11 +519,11 @@ int main(int argc_, const char **argv_) { // If result status is 70, then the driver command reported a fatal error. // On Windows, abort will return an exit code of 3. In these cases, // generate additional diagnostic information if possible. - bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70; + IsCrash = CommandRes < 0 || CommandRes == 70; #ifdef _WIN32 - DiagnoseCrash |= CommandRes == 3; + IsCrash |= CommandRes == 3; #endif - if (DiagnoseCrash) { + if (IsCrash) { TheDriver.generateCompilationDiagnostics(*C, *FailingCommand); break; } @@ -530,10 +532,16 @@ int main(int argc_, const char **argv_) { Diags.getClient()->finish(); - // If any timers were active but haven't been destroyed yet, print their - // results now. This happens in -disable-free mode. - llvm::TimerGroup::printAll(llvm::errs()); - llvm::TimerGroup::clearAll(); + if (!UseNewCC1Process && IsCrash) { + // When crashing in -fintegrated-cc1 mode, bury the timer pointers, because + // the internal linked list might point to already released stack frames. + llvm::BuryPointer(llvm::TimerGroup::aquireDefaultGroup()); + } else { + // If any timers were active but haven't been destroyed yet, print their + // results now. This happens in -disable-free mode. + llvm::TimerGroup::printAll(llvm::errs()); + llvm::TimerGroup::clearAll(); + } #ifdef _WIN32 // Exit status should not be negative on Win32, unless abnormal termination. diff --git a/llvm/include/llvm/Support/ManagedStatic.h b/llvm/include/llvm/Support/ManagedStatic.h index e65bb051f181..bbd0d04ed040 100644 --- a/llvm/include/llvm/Support/ManagedStatic.h +++ b/llvm/include/llvm/Support/ManagedStatic.h @@ -102,6 +102,12 @@ class ManagedStatic : public ManagedStaticBase { } const C *operator->() const { return &**this; } + + // Extract the instance, leaving the ManagedStatic uninitialized. The + // user is then responsible for the lifetime of the returned instance. + C *claim() { + return static_cast(Ptr.exchange(nullptr)); + } }; /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. diff --git a/llvm/include/llvm/Support/Timer.h b/llvm/include/llvm/Support/Timer.h index a298ecd90404..045ac448bdb4 100644 --- a/llvm/include/llvm/Support/Timer.h +++ b/llvm/include/llvm/Support/Timer.h @@ -230,6 +230,11 @@ class TimerGroup { /// used by the Statistic code to influence the construction and destruction /// order of the global timer lists. static void ConstructTimerLists(); + + /// This makes the default group unmanaged, and lets the user manage the + /// group's lifetime. + static std::unique_ptr aquireDefaultGroup(); + private: friend class Timer; friend void PrintStatisticsJSON(raw_ostream &OS); diff --git a/llvm/lib/Support/Timer.cpp b/llvm/lib/Support/Timer.cpp index 613d2eaae6d3..2d3d00812826 100644 --- a/llvm/lib/Support/Timer.cpp +++ b/llvm/lib/Support/Timer.cpp @@ -441,3 +441,7 @@ const char *TimerGroup::printAllJSONValues(raw_ostream &OS, const char *delim) { void TimerGroup::ConstructTimerLists() { (void)*NamedGroupedTimers; } + +std::unique_ptr TimerGroup::aquireDefaultGroup() { + return std::unique_ptr(DefaultTimerGroup.claim()); +}