diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -265,7 +265,8 @@ BackRefVec NameBackReferences; typedef llvm::DenseMap ArgBackRefMap; - ArgBackRefMap TypeBackReferences; + ArgBackRefMap FunArgBackReferences; + ArgBackRefMap TemplateArgBackReferences; typedef std::set> PassObjectSizeArgsSet; PassObjectSizeArgsSet PassObjectSizeArgs; @@ -343,7 +344,7 @@ const TemplateArgumentList &TemplateArgs); void mangleObjCMethodName(const ObjCMethodDecl *MD); - void mangleArgumentType(QualType T, SourceRange Range); + void mangleFunctionArgumentType(QualType T, SourceRange Range); void manglePassObjectSizeArg(const PassObjectSizeAttr *POSA); bool isArtificialTagType(QualType T) const; @@ -793,7 +794,7 @@ // the X part is aliased. However, if you need to mangle // void foo(A::X, A::X), // the A::X<> part is not aliased. - // That said, from the mangler's perspective we have a structure like this: + // That is, from the mangler's perspective we have a structure like this: // namespace[s] -> type[ -> template-parameters] // but from the Clang perspective we have // type [ -> template-parameters] @@ -803,12 +804,30 @@ // the mangled type name as a key to check the mangling of different types // for aliasing. - llvm::SmallString<64> TemplateMangling; - llvm::raw_svector_ostream Stream(TemplateMangling); - MicrosoftCXXNameMangler Extra(Context, Stream); - Extra.mangleTemplateInstantiationName(TD, *TemplateArgs); - - mangleSourceName(TemplateMangling); + // It's important to key cache reads off ND, not TD -- the same TD can + // be used with different TemplateArgs, but ND uniquely identifies + // TD / TemplateArg pairs. + ArgBackRefMap::iterator Found = TemplateArgBackReferences.find(ND); + if (Found == TemplateArgBackReferences.end()) { + // Mangle full template name into temporary buffer. + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + Extra.mangleTemplateInstantiationName(TD, *TemplateArgs); + + // Use the string backref vector to possibly get a back reference. + mangleSourceName(TemplateMangling); + + // Memoize back reference for this type. + BackRefVec::iterator StringFound = + llvm::find(NameBackReferences, TemplateMangling); + if (StringFound != NameBackReferences.end()) { + TemplateArgBackReferences[ND] = + StringFound - NameBackReferences.begin(); + } + } else { + Out << Found->second; + } return; } @@ -1282,11 +1301,13 @@ // Always start with the unqualified name. // Templates have their own context for back references. - ArgBackRefMap OuterArgsContext; + ArgBackRefMap OuterFunArgsContext; + ArgBackRefMap OuterTemplateArgsContext; BackRefVec OuterTemplateContext; PassObjectSizeArgsSet OuterPassObjectSizeArgs; NameBackReferences.swap(OuterTemplateContext); - TypeBackReferences.swap(OuterArgsContext); + FunArgBackReferences.swap(OuterFunArgsContext); + TemplateArgBackReferences.swap(OuterTemplateArgsContext); PassObjectSizeArgs.swap(OuterPassObjectSizeArgs); mangleUnscopedTemplateName(TD); @@ -1294,7 +1315,8 @@ // Restore the previous back reference contexts. NameBackReferences.swap(OuterTemplateContext); - TypeBackReferences.swap(OuterArgsContext); + FunArgBackReferences.swap(OuterFunArgsContext); + TemplateArgBackReferences.swap(OuterTemplateArgsContext); PassObjectSizeArgs.swap(OuterPassObjectSizeArgs); } @@ -1699,8 +1721,8 @@ } } -void MicrosoftCXXNameMangler::mangleArgumentType(QualType T, - SourceRange Range) { +void MicrosoftCXXNameMangler::mangleFunctionArgumentType(QualType T, + SourceRange Range) { // MSVC will backreference two canonically equivalent types that have slightly // different manglings when mangled alone. @@ -1730,9 +1752,9 @@ TypePtr = T.getCanonicalType().getAsOpaquePtr(); } - ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); + ArgBackRefMap::iterator Found = FunArgBackReferences.find(TypePtr); - if (Found == TypeBackReferences.end()) { + if (Found == FunArgBackReferences.end()) { size_t OutSizeBefore = Out.tell(); mangleType(T, Range, QMM_Drop); @@ -1741,9 +1763,9 @@ // Only types longer than 1 character are considered // and only 10 back references slots are available: bool LongerThanOneChar = (Out.tell() - OutSizeBefore > 1); - if (LongerThanOneChar && TypeBackReferences.size() < 10) { - size_t Size = TypeBackReferences.size(); - TypeBackReferences[TypePtr] = Size; + if (LongerThanOneChar && FunArgBackReferences.size() < 10) { + size_t Size = FunArgBackReferences.size(); + FunArgBackReferences[TypePtr] = Size; } } else { Out << Found->second; @@ -1757,16 +1779,16 @@ auto Iter = PassObjectSizeArgs.insert({Type, Dynamic}).first; auto *TypePtr = (const void *)&*Iter; - ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); + ArgBackRefMap::iterator Found = FunArgBackReferences.find(TypePtr); - if (Found == TypeBackReferences.end()) { + if (Found == FunArgBackReferences.end()) { std::string Name = Dynamic ? "__pass_dynamic_object_size" : "__pass_object_size"; mangleArtificialTagType(TTK_Enum, Name + llvm::utostr(Type), {"__clang"}); - if (TypeBackReferences.size() < 10) { - size_t Size = TypeBackReferences.size(); - TypeBackReferences[TypePtr] = Size; + if (FunArgBackReferences.size() < 10) { + size_t Size = FunArgBackReferences.size(); + FunArgBackReferences[TypePtr] = Size; } } else { Out << Found->second; @@ -2192,12 +2214,12 @@ Out << 'X'; } else if (StructorType == Ctor_CopyingClosure) { // Copy constructor closure always takes an unqualified reference. - mangleArgumentType(getASTContext().getLValueReferenceType( - Proto->getParamType(0) - ->getAs() - ->getPointeeType(), - /*SpelledAsLValue=*/true), - Range); + mangleFunctionArgumentType(getASTContext().getLValueReferenceType( + Proto->getParamType(0) + ->getAs() + ->getPointeeType(), + /*SpelledAsLValue=*/true), + Range); Out << '@'; } else { llvm_unreachable("unexpected constructor closure!"); @@ -2239,7 +2261,7 @@ } else { // Happens for function pointer type arguments for example. for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) { - mangleArgumentType(Proto->getParamType(I), Range); + mangleFunctionArgumentType(Proto->getParamType(I), Range); // Mangle each pass_object_size parameter as if it's a parameter of enum // type passed directly after the parameter with the pass_object_size // attribute. The aforementioned enum's name is __pass_object_size, and we @@ -2731,10 +2753,12 @@ if (T->qual_empty() && !T->isSpecialized()) return mangleType(T->getBaseType(), Range, QMM_Drop); - ArgBackRefMap OuterArgsContext; + ArgBackRefMap OuterFunArgsContext; + ArgBackRefMap OuterTemplateArgsContext; BackRefVec OuterTemplateContext; - TypeBackReferences.swap(OuterArgsContext); + FunArgBackReferences.swap(OuterFunArgsContext); + TemplateArgBackReferences.swap(OuterTemplateArgsContext); NameBackReferences.swap(OuterTemplateContext); mangleTagTypeKind(TTK_Struct); @@ -2758,7 +2782,8 @@ Out << '@'; - TypeBackReferences.swap(OuterArgsContext); + FunArgBackReferences.swap(OuterFunArgsContext); + TemplateArgBackReferences.swap(OuterTemplateArgsContext); NameBackReferences.swap(OuterTemplateContext); } diff --git a/clang/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp b/clang/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp --- a/clang/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp @@ -191,3 +191,44 @@ // CHECK: "??$fun_tmpl_recurse@H$1??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@1@H@Z@fn_space@@YA?AURetVal@0@H@Z" // CHECK: "??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@0@H@Z" } + + +template +struct Fooob {}; + +using A0 = Fooob; +using A1 = Fooob; +using A2 = Fooob; +using A3 = Fooob; +using A4 = Fooob; +using A5 = Fooob; +using A6 = Fooob; +using A7 = Fooob; +using A8 = Fooob; +using A9 = Fooob; +using A10 = Fooob; + +// This should take milliseconds, not minutes. +void f(A9 a) {} +// CHECK: "?f@@YAXU?$Fooob@U?$Fooob@U?$Fooob@U?$Fooob@U?$Fooob@U?$Fooob@U?$Fooob@U?$Fooob@U?$Fooob@U?$Fooob@HHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@@Z" + + +template +struct Food {}; + +using B0 = Food; +using B1 = Food; +using B2 = Food; +using B3 = Food; +using B4 = Food; +using B5 = Food; +using B6 = Food; + +// This too should take milliseconds, not minutes. +void f(B6 a) {} + +// CHECK: "?f@@YAXU?$Food@U?$Food@U?$Food@U?$Food@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U3@U3@U3@U3@U3@U3@U3@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U4@U4@U4@U4@U4@U4@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U3@U3@U3@U3@U3@U3@U3@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U5@U5@U5@U5@U5@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U3@U3@U3@U3@U3@U3@U3@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U4@U4@U4@U4@U4@U4@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U3@U3@U3@U3@U3@U3@U3@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U6@U6@U6@U6@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@@Z"