diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -514,6 +514,8 @@ /// need to be consistently numbered for the mangler). llvm::DenseMap> MangleNumberingContexts; + llvm::DenseMap> + ExtraMangleNumberingContexts; /// Side-table of mangling numbers for declarations which rarely /// need them (like static local vars). @@ -2812,6 +2814,9 @@ /// Retrieve the context for computing mangling numbers in the given /// DeclContext. MangleNumberingContext &getManglingNumberContext(const DeclContext *DC); + enum NeedExtraManglingDecl_t { NeedExtraManglingDecl }; + MangleNumberingContext &getManglingNumberContext(NeedExtraManglingDecl_t, + const Decl *D); std::unique_ptr createMangleNumberingContext() const; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -57,6 +57,7 @@ #include #include #include +#include #include namespace llvm { @@ -1045,13 +1046,6 @@ /// suffice, e.g., in a default function argument. Decl *ManglingContextDecl; - /// The context information used to mangle lambda expressions - /// and block literals within this context. - /// - /// This mangling information is allocated lazily, since most contexts - /// do not have lambda expressions or block literals. - std::unique_ptr MangleNumbering; - /// If we are processing a decltype type, a set of call expressions /// for which we have deferred checking the completeness of the return type. SmallVector DelayedDecltypeCalls; @@ -1080,12 +1074,7 @@ ExpressionKind ExprContext) : Context(Context), ParentCleanup(ParentCleanup), NumCleanupObjects(NumCleanupObjects), NumTypos(0), - ManglingContextDecl(ManglingContextDecl), MangleNumbering(), - ExprContext(ExprContext) {} - - /// Retrieve the mangling numbering context, used to consistently - /// number constructs like lambdas for mangling. - MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx); + ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext) {} bool isUnevaluated() const { return Context == ExpressionEvaluationContext::Unevaluated || @@ -1104,15 +1093,12 @@ void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec); /// Compute the mangling number context for a lambda expression or - /// block literal. + /// block literal. Also return the extra mangling decl if any. /// /// \param DC - The DeclContext containing the lambda expression or /// block literal. - /// \param[out] ManglingContextDecl - Returns the ManglingContextDecl - /// associated with the context, if relevant. - MangleNumberingContext *getCurrentMangleNumberContext( - const DeclContext *DC, - Decl *&ManglingContextDecl); + std::tuple + getCurrentMangleNumberContext(const DeclContext *DC); /// SpecialMemberOverloadResult - The overloading result for a special member diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -10261,6 +10261,16 @@ return *MCtx; } +MangleNumberingContext & +ASTContext::getManglingNumberContext(NeedExtraManglingDecl_t, const Decl *D) { + assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C. + std::unique_ptr &MCtx = + ExtraMangleNumberingContexts[D]; + if (!MCtx) + MCtx = createMangleNumberingContext(); + return *MCtx; +} + std::unique_ptr ASTContext::createMangleNumberingContext() const { return ABI->createMangleNumberingContext(); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4284,9 +4284,11 @@ } // If this tag isn't a direct child of a class, number it if it is local. + MangleNumberingContext *MCtx; Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( - Tag->getDeclContext(), ManglingContextDecl)) { + std::tie(MCtx, ManglingContextDecl) = + getCurrentMangleNumberContext(Tag->getDeclContext()); + if (MCtx) { Context.setManglingNumber( Tag, MCtx->getManglingNumber( Tag, getMSManglingNumber(getLangOpts(), TagScope))); @@ -5022,9 +5024,11 @@ if (VarDecl *NewVD = dyn_cast(Anon)) { if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { + MangleNumberingContext *MCtx; Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( - NewVD->getDeclContext(), ManglingContextDecl)) { + std::tie(MCtx, ManglingContextDecl) = + getCurrentMangleNumberContext(NewVD->getDeclContext()); + if (MCtx) { Context.setManglingNumber( NewVD, MCtx->getManglingNumber( NewVD, getMSManglingNumber(getLangOpts(), S))); @@ -7090,9 +7094,11 @@ RegisterLocallyScopedExternCDecl(NewVD, S); if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { + MangleNumberingContext *MCtx; Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( - NewVD->getDeclContext(), ManglingContextDecl)) { + std::tie(MCtx, ManglingContextDecl) = + getCurrentMangleNumberContext(NewVD->getDeclContext()); + if (MCtx) { Context.setManglingNumber( NewVD, MCtx->getManglingNumber( NewVD, getMSManglingNumber(getLangOpts(), S))); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14043,10 +14043,11 @@ BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc); if (LangOpts.CPlusPlus) { + MangleNumberingContext *MCtx; Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = - getCurrentMangleNumberContext(Block->getDeclContext(), - ManglingContextDecl)) { + std::tie(MCtx, ManglingContextDecl) = + getCurrentMangleNumberContext(Block->getDeclContext()); + if (MCtx) { unsigned ManglingNumber = MCtx->getManglingNumber(Block); Block->setBlockMangling(ManglingNumber, ManglingContextDecl); } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -272,12 +272,11 @@ return false; } -MangleNumberingContext * -Sema::getCurrentMangleNumberContext(const DeclContext *DC, - Decl *&ManglingContextDecl) { +std::tuple +Sema::getCurrentMangleNumberContext(const DeclContext *DC) { // Compute the context for allocating mangling numbers in the current // expression, if the ABI requires them. - ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl; + Decl *ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl; enum ContextKind { Normal, @@ -325,22 +324,18 @@ if ((IsInNonspecializedTemplate && !(ManglingContextDecl && isa(ManglingContextDecl))) || isInInlineFunction(CurContext)) { - ManglingContextDecl = nullptr; while (auto *CD = dyn_cast(DC)) DC = CD->getParent(); - return &Context.getManglingNumberContext(DC); + return std::make_tuple(&Context.getManglingNumberContext(DC), nullptr); } - ManglingContextDecl = nullptr; - return nullptr; + return std::make_tuple(nullptr, nullptr); } case StaticDataMember: // -- the initializers of nonspecialized static members of template classes - if (!IsInNonspecializedTemplate) { - ManglingContextDecl = nullptr; - return nullptr; - } + if (!IsInNonspecializedTemplate) + return std::make_tuple(nullptr, nullptr); // Fall through to get the current context. LLVM_FALLTHROUGH; @@ -352,21 +347,15 @@ // -- the initializers of inline variables case VariableTemplate: // -- the initializers of templated variables - return &ExprEvalContexts.back().getMangleNumberingContext(Context); + return std::make_tuple( + &Context.getManglingNumberContext(ASTContext::NeedExtraManglingDecl, + ManglingContextDecl), + ManglingContextDecl); } llvm_unreachable("unexpected context"); } -MangleNumberingContext & -Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext( - ASTContext &Ctx) { - assert(ManglingContextDecl && "Need to have a context declaration"); - if (!MangleNumbering) - MangleNumbering = Ctx.createMangleNumberingContext(); - return *MangleNumbering; -} - CXXMethodDecl *Sema::startLambdaDefinition( CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc, @@ -439,10 +428,11 @@ if (Mangling) { Class->setLambdaMangling(Mangling->first, Mangling->second); } else { + MangleNumberingContext *MCtx; Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = - getCurrentMangleNumberContext(Class->getDeclContext(), - ManglingContextDecl)) { + std::tie(MCtx, ManglingContextDecl) = + getCurrentMangleNumberContext(Class->getDeclContext()); + if (MCtx) { unsigned ManglingNumber = MCtx->getManglingNumber(Method); Class->setLambdaMangling(ManglingNumber, ManglingContextDecl); } diff --git a/clang/test/CodeGenCXX/mangle-lambdas.cpp b/clang/test/CodeGenCXX/mangle-lambdas.cpp --- a/clang/test/CodeGenCXX/mangle-lambdas.cpp +++ b/clang/test/CodeGenCXX/mangle-lambdas.cpp @@ -178,18 +178,24 @@ } namespace std { - struct type_info; + struct type_info { + bool before(const type_info &) const noexcept; + }; } namespace PR12123 { struct A { virtual ~A(); } g; + struct C { virtual ~C(); } k; struct B { void f(const std::type_info& x = typeid([]()->A& { return g; }())); void h(); + void j(bool cond = typeid([]() -> A & { return g; }()).before(typeid([]() -> C & { return k; }()))); }; - void B::h() { f(); } + void B::h() { f(); j(); } } // CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %"struct.PR12123::A"* @_ZZN7PR121231B1jEbEd_NKUlvE_clEv +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %"struct.PR12123::C"* @_ZZN7PR121231B1jEbEd_NKUlvE0_clEv // CHECK-LABEL: define {{.*}} @_Z{{[0-9]*}}testVarargsLambdaNumberingv( inline int testVarargsLambdaNumbering() {