diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 2f9123cc0019..95d8af96485b 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -405,12 +405,14 @@ public: CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_) : Context(Outer.Context), Out(Out_), NullOut(false), Structor(Outer.Structor), StructorType(Outer.StructorType), - SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {} + SeqID(Outer.SeqID), AbiTagsRoot(AbiTags), + Substitutions(Outer.Substitutions) {} CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_) : Context(Outer.Context), Out(Out_), NullOut(true), Structor(Outer.Structor), StructorType(Outer.StructorType), - SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {} + SeqID(Outer.SeqID), AbiTagsRoot(AbiTags), + Substitutions(Outer.Substitutions) {} #if MANGLE_CHECKER ~CXXNameMangler() { @@ -458,6 +460,8 @@ private: void addSubstitution(QualType T); void addSubstitution(TemplateName Template); void addSubstitution(uintptr_t Ptr); + // Destructive copy substitutions from other mangler. + void extendSubstitutions(CXXNameMangler* Other); void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, bool recursive = false); @@ -685,6 +689,10 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // Output name with implicit tags and function encoding from temporary buffer. mangleNameWithAbiTags(FD, &AdditionalAbiTags); Out << FunctionEncodingStream.str().substr(EncodingPositionStart); + + // Function encoding could create new substitutions so we have to add + // temp mangled substitutions to main mangler. + extendSubstitutions(&FunctionEncodingMangler); } void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { @@ -4426,6 +4434,14 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) { Substitutions[Ptr] = SeqID++; } +void CXXNameMangler::extendSubstitutions(CXXNameMangler* Other) { + assert(Other->SeqID >= SeqID && "Must be superset of substitutions!"); + if (Other->SeqID > SeqID) { + Substitutions.swap(Other->Substitutions); + SeqID = Other->SeqID; + } +} + CXXNameMangler::AbiTagList CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) { // When derived abi tags are disabled there is no need to make any list. diff --git a/clang/test/CodeGenCXX/mangle-abi-tag.cpp b/clang/test/CodeGenCXX/mangle-abi-tag.cpp index 385a16f26a51..990d2f94b5a5 100644 --- a/clang/test/CodeGenCXX/mangle-abi-tag.cpp +++ b/clang/test/CodeGenCXX/mangle-abi-tag.cpp @@ -203,3 +203,19 @@ void f18_test() { } // A18::operator A[abi:A][abi:B]() but GCC adds the same tags twice! // CHECK-DAG: define linkonce_odr {{.+}} @_ZN3A18cv1AB1AB1BEv( + +namespace N19 { + class A {}; + class __attribute__((abi_tag("B"))) B {}; + class D {}; + class F {}; + + template + class C {}; + + B foo(A, D); +} +void f19_test(N19::C, N19::F, N19::D) { +} +// f19_test(N19::C, N19::F, N19::D) +// CHECK-DAG: define void @_Z8f19_testN3N191CINS_1AEXadL_ZNS_3fooB1BES1_NS_1DEEEEENS_1FES2_(