diff options
-rw-r--r-- | clang/include/clang/AST/ASTContext.h | 8 | ||||
-rw-r--r-- | clang/include/clang/AST/Decl.h | 25 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 19 | ||||
-rw-r--r-- | clang/lib/AST/CXXABI.h | 12 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 8 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumCXXABI.cpp | 14 | ||||
-rw-r--r-- | clang/lib/AST/MicrosoftCXXABI.cpp | 33 | ||||
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 31 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 5 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle-ms-cxx11.cpp | 18 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle-ms.cpp | 29 |
14 files changed, 184 insertions, 57 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 92be4b41835..6391244ca03 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2311,6 +2311,14 @@ public: Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, unsigned ParmIdx); + void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *TND); + + TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD); + + void addDeclaratorForUnnamedTagDecl(TagDecl *TD, DeclaratorDecl *DD); + + DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD); + void setManglingNumber(const NamedDecl *ND, unsigned Number); unsigned getManglingNumber(const NamedDecl *ND) const; diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 50d8aaed174..cc778a550a7 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2778,12 +2778,12 @@ private: /// declaration specifier for variables, it points to the first VarDecl (used /// for mangling); /// otherwise, it is a null (TypedefNameDecl) pointer. - llvm::PointerUnion<NamedDecl *, ExtInfo *> NamedDeclOrQualifier; + llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier; - bool hasExtInfo() const { return NamedDeclOrQualifier.is<ExtInfo *>(); } - ExtInfo *getExtInfo() { return NamedDeclOrQualifier.get<ExtInfo *>(); } + bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); } + ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); } const ExtInfo *getExtInfo() const { - return NamedDeclOrQualifier.get<ExtInfo *>(); + return TypedefNameDeclOrQualifier.get<ExtInfo *>(); } protected: @@ -2794,7 +2794,7 @@ protected: TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false), IsEmbeddedInDeclarator(false), IsFreeStanding(false), IsCompleteDefinitionRequired(false), - NamedDeclOrQualifier((NamedDecl *)nullptr) { + TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) { assert((DK != Enum || TK == TTK_Enum) && "EnumDecl not matched with TTK_Enum"); setPreviousDecl(PrevDecl); @@ -2941,22 +2941,11 @@ public: return (getDeclName() || getTypedefNameForAnonDecl()); } - bool hasDeclaratorForAnonDecl() const { - return dyn_cast_or_null<DeclaratorDecl>( - NamedDeclOrQualifier.get<NamedDecl *>()); - } - DeclaratorDecl *getDeclaratorForAnonDecl() const { - return hasExtInfo() ? nullptr : dyn_cast_or_null<DeclaratorDecl>( - NamedDeclOrQualifier.get<NamedDecl *>()); - } - TypedefNameDecl *getTypedefNameForAnonDecl() const { - return hasExtInfo() ? nullptr : dyn_cast_or_null<TypedefNameDecl>( - NamedDeclOrQualifier.get<NamedDecl *>()); + return hasExtInfo() ? nullptr + : TypedefNameDeclOrQualifier.get<TypedefNameDecl *>(); } - void setDeclaratorForAnonDecl(DeclaratorDecl *DD) { NamedDeclOrQualifier = DD; } - void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); /// \brief Retrieve the nested-name-specifier that qualifies the name of this diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 0a99575f406..285b194803b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -8549,6 +8549,25 @@ Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx); } +void ASTContext::addTypedefNameForUnnamedTagDecl(TagDecl *TD, + TypedefNameDecl *DD) { + return ABI->addTypedefNameForUnnamedTagDecl(TD, DD); +} + +TypedefNameDecl * +ASTContext::getTypedefNameForUnnamedTagDecl(const TagDecl *TD) { + return ABI->getTypedefNameForUnnamedTagDecl(TD); +} + +void ASTContext::addDeclaratorForUnnamedTagDecl(TagDecl *TD, + DeclaratorDecl *DD) { + return ABI->addDeclaratorForUnnamedTagDecl(TD, DD); +} + +DeclaratorDecl *ASTContext::getDeclaratorForUnnamedTagDecl(const TagDecl *TD) { + return ABI->getDeclaratorForUnnamedTagDecl(TD); +} + void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) { ParamIndices[D] = index; } diff --git a/clang/lib/AST/CXXABI.h b/clang/lib/AST/CXXABI.h index dad226474fa..c23b9191c7a 100644 --- a/clang/lib/AST/CXXABI.h +++ b/clang/lib/AST/CXXABI.h @@ -21,6 +21,7 @@ namespace clang { class ASTContext; class CXXConstructorDecl; +class DeclaratorDecl; class Expr; class MemberPointerType; class MangleNumberingContext; @@ -57,6 +58,17 @@ public: virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, unsigned ParmIdx) = 0; + + virtual void addTypedefNameForUnnamedTagDecl(TagDecl *TD, + TypedefNameDecl *DD) = 0; + + virtual TypedefNameDecl * + getTypedefNameForUnnamedTagDecl(const TagDecl *TD) = 0; + + virtual void addDeclaratorForUnnamedTagDecl(TagDecl *TD, + DeclaratorDecl *DD) = 0; + + virtual DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) = 0; }; /// Creates an instance of a C++ ABI class. diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index c3c2ac49f0b..8cd2e17af8b 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3403,7 +3403,7 @@ SourceRange TagDecl::getSourceRange() const { TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); } void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { - NamedDeclOrQualifier = TDD; + TypedefNameDeclOrQualifier = TDD; if (const Type *T = getTypeForDecl()) { (void)T; assert(T->isLinkageValid()); @@ -3461,7 +3461,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (QualifierLoc) { // Make sure the extended qualifier info is allocated. if (!hasExtInfo()) - NamedDeclOrQualifier = new (getASTContext()) ExtInfo; + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; } else { @@ -3469,7 +3469,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { getASTContext().Deallocate(getExtInfo()); - NamedDeclOrQualifier = (TypedefNameDecl*)nullptr; + TypedefNameDeclOrQualifier = (TypedefNameDecl *)nullptr; } else getExtInfo()->QualifierLoc = QualifierLoc; @@ -3483,7 +3483,7 @@ void TagDecl::setTemplateParameterListsInfo( // Make sure the extended decl info is allocated. if (!hasExtInfo()) // Allocate external info struct. - NamedDeclOrQualifier = new (getASTContext()) ExtInfo; + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; // Set the template parameter lists info. getExtInfo()->setTemplateParameterListsInfo(Context, TPLists); } diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index 7503cbfc980..8a2cc0fbee4 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -149,6 +149,20 @@ public: return nullptr; } + void addTypedefNameForUnnamedTagDecl(TagDecl *TD, + TypedefNameDecl *DD) override {} + + TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { + return nullptr; + } + + void addDeclaratorForUnnamedTagDecl(TagDecl *TD, + DeclaratorDecl *DD) override {} + + DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { + return nullptr; + } + MangleNumberingContext *createMangleNumberingContext() const override { return new ItaniumNumberingContext(); } diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index aba6796256a..6847ee16f7a 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -70,6 +70,11 @@ class MicrosoftCXXABI : public CXXABI { llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *> CtorToDefaultArgExpr; + llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *> + UnnamedTagDeclToDeclaratorDecl; + llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *> + UnnamedTagDeclToTypedefNameDecl; + public: MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } @@ -120,6 +125,34 @@ public: RecordToCopyCtor[RD] = CD; } + void addTypedefNameForUnnamedTagDecl(TagDecl *TD, + TypedefNameDecl *DD) override { + TD = TD->getCanonicalDecl(); + DD = cast<TypedefNameDecl>(DD->getCanonicalDecl()); + TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD]; + if (!I) + I = DD; + } + + TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { + return UnnamedTagDeclToTypedefNameDecl[const_cast<TagDecl *>( + TD->getCanonicalDecl())]; + } + + void addDeclaratorForUnnamedTagDecl(TagDecl *TD, + DeclaratorDecl *DD) override { + TD = TD->getCanonicalDecl(); + DD = cast<DeclaratorDecl>(DD->getCanonicalDecl()); + DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD]; + if (!I) + I = DD; + } + + DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { + return UnnamedTagDeclToDeclaratorDecl[const_cast<TagDecl *>( + TD->getCanonicalDecl())]; + } + MangleNumberingContext *createMangleNumberingContext() const override { return new MicrosoftNumberingContext(); } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 1be02f5e23c..596f1386570 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -786,10 +786,17 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } llvm::SmallString<64> Name("<unnamed-type-"); - if (TD->hasDeclaratorForAnonDecl()) { - // Anonymous types with no tag or typedef get the name of their + if (DeclaratorDecl *DD = + Context.getASTContext().getDeclaratorForUnnamedTagDecl(TD)) { + // Anonymous types without a name for linkage purposes have their // declarator mangled in if they have one. - Name += TD->getDeclaratorForAnonDecl()->getName(); + Name += DD->getName(); + } else if (TypedefNameDecl *TND = + Context.getASTContext().getTypedefNameForUnnamedTagDecl( + TD)) { + // Anonymous types without a name for linkage purposes have their + // associate typedef mangled in if they have one. + Name += TND->getName(); } else { // Otherwise, number the types using a $S prefix. Name += "$S"; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c74bb8351e8..72946e8fb82 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3560,11 +3560,8 @@ void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) { void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, TypedefNameDecl *NewTD) { - // Do nothing if the tag is not anonymous or already has an - // associated typedef (from an earlier typedef in this decl group). - if (TagFromDeclSpec->getIdentifier()) - return; - if (TagFromDeclSpec->getTypedefNameForAnonDecl()) + // Do nothing if the tag already has a name for linkage purposes. + if (TagFromDeclSpec->hasNameForLinkage()) return; // A well-formed anonymous tag must always be a TUK_Definition. @@ -3572,8 +3569,11 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, // The type must match the tag exactly; no qualifiers allowed. if (!Context.hasSameType(NewTD->getUnderlyingType(), - Context.getTagDeclType(TagFromDeclSpec))) + Context.getTagDeclType(TagFromDeclSpec))) { + if (getLangOpts().CPlusPlus) + Context.addTypedefNameForUnnamedTagDecl(TagFromDeclSpec, NewTD); return; + } // If we've already computed linkage for the anonymous tag, then // adding a typedef name for the anonymous decl can change that @@ -10050,8 +10050,9 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (DeclSpec::isDeclRep(DS.getTypeSpecType())) { if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) { handleTagNumbering(Tag, S); - if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl()) - Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup); + if (FirstDeclaratorInGroup && !Tag->hasNameForLinkage() && + getLangOpts().CPlusPlus) + Context.addDeclaratorForUnnamedTagDecl(Tag, FirstDeclaratorInGroup); } } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9899f1e8b1a..029af186fdc 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -813,6 +813,14 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { Enum->setAccess(D->getAccess()); // Forward the mangling number from the template to the instantiated decl. SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D)); + // See if the old tag was defined along with a declarator. + // If it did, mark the new tag as being associated with that declarator. + if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D)) + SemaRef.Context.addDeclaratorForUnnamedTagDecl(Enum, DD); + // See if the old tag was defined along with a typedef. + // If it did, mark the new tag as being associated with that typedef. + if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D)) + SemaRef.Context.addTypedefNameForUnnamedTagDecl(Enum, TND); if (SubstQualifier(D, Enum)) return nullptr; Owner->addDecl(Enum); @@ -1298,6 +1306,16 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { SemaRef.Context.setManglingNumber(Record, SemaRef.Context.getManglingNumber(D)); + // See if the old tag was defined along with a declarator. + // If it did, mark the new tag as being associated with that declarator. + if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D)) + SemaRef.Context.addDeclaratorForUnnamedTagDecl(Record, DD); + + // See if the old tag was defined along with a typedef. + // If it did, mark the new tag as being associated with that typedef. + if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D)) + SemaRef.Context.addTypedefNameForUnnamedTagDecl(Record, TND); + Owner->addDecl(Record); // DR1484 clarifies that the members of a local class are instantiated as part @@ -3615,19 +3633,6 @@ void Sema::BuildVariableInstantiation( NewVar->setReferenced(OldVar->isReferenced()); } - // See if the old variable had a type-specifier that defined an anonymous tag. - // If it did, mark the new variable as being the declarator for the new - // anonymous tag. - if (const TagType *OldTagType = OldVar->getType()->getAs<TagType>()) { - TagDecl *OldTag = OldTagType->getDecl(); - if (OldTag->getDeclaratorForAnonDecl() == OldVar) { - TagDecl *NewTag = NewVar->getType()->castAs<TagType>()->getDecl(); - assert(!NewTag->hasNameForLinkage() && - !NewTag->hasDeclaratorForAnonDecl()); - NewTag->setDeclaratorForAnonDecl(NewVar); - } - } - InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope); LookupResult Previous( diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 00785aa1d05..25a684a531e 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -441,8 +441,8 @@ void ASTDeclReader::Visit(Decl *D) { // If this is a tag declaration with a typedef name for linkage, it's safe // to load that typedef now. if (NamedDeclForTagDecl) - cast<TagDecl>(D)->NamedDeclOrQualifier = - cast<NamedDecl>(Reader.GetDecl(NamedDeclForTagDecl)); + cast<TagDecl>(D)->TypedefNameDeclOrQualifier = + cast<TypedefNameDecl>(Reader.GetDecl(NamedDeclForTagDecl)); } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { // if we have a fully initialized TypeDecl, we can safely read its type now. ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull(); @@ -595,16 +595,13 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { case 1: { // ExtInfo TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); - TD->NamedDeclOrQualifier = Info; + TD->TypedefNameDeclOrQualifier = Info; break; } case 2: // TypedefNameForAnonDecl NamedDeclForTagDecl = ReadDeclID(Record, Idx); TypedefNameForLinkage = Reader.GetIdentifierInfo(F, Record, Idx); break; - case 3: // DeclaratorForAnonDecl - NamedDeclForTagDecl = ReadDeclID(Record, Idx); - break; default: llvm_unreachable("unexpected tag info kind"); } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index d38e58766a2..24e07c42a41 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -378,9 +378,6 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) { Record.push_back(2); Writer.AddDeclRef(TD, Record); Writer.AddIdentifierRef(TD->getDeclName().getAsIdentifierInfo(), Record); - } else if (auto *DD = D->getDeclaratorForAnonDecl()) { - Record.push_back(3); - Writer.AddDeclRef(DD, Record); } else { Record.push_back(0); } @@ -410,7 +407,6 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { !D->isUsed(false) && !D->hasExtInfo() && !D->getTypedefNameForAnonDecl() && - !D->getDeclaratorForAnonDecl() && D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && @@ -439,7 +435,6 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { !D->isUsed(false) && !D->hasExtInfo() && !D->getTypedefNameForAnonDecl() && - !D->getDeclaratorForAnonDecl() && D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && diff --git a/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp index 3f4075f7f37..7cb09704de0 100644 --- a/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -243,3 +243,21 @@ void f() {} template void f<AliasA>(); // CHECK-DAG: @"\01??$f@$$YAliasA@PR20047@@@PR20047@@YAXXZ" } + +namespace UnnamedType { +struct A { + struct {} *TD; +}; + +void f(decltype(*A::TD)) {} +// CHECK-DAG: @"\01?f@UnnamedType@@YAXAAU<unnamed-type-TD>@A@1@@Z" + +template <typename T> +struct B { + enum { + } *e; +}; + +void f(decltype(B<int>::e)) {} +// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAW4<unnamed-type-e>@?$B@H@1@@Z +} diff --git a/clang/test/CodeGenCXX/mangle-ms.cpp b/clang/test/CodeGenCXX/mangle-ms.cpp index 0da5c6f1f8d..54855ec5a4d 100644 --- a/clang/test/CodeGenCXX/mangle-ms.cpp +++ b/clang/test/CodeGenCXX/mangle-ms.cpp @@ -389,3 +389,32 @@ template void fn_tmpl<extern_c_func>(); extern "C" void __attribute__((overloadable)) overloaded_fn() {} // CHECK-DAG: @"\01?overloaded_fn@@$$J0YAXXZ" + +namespace UnnamedType { +struct S { + typedef struct {} *T1[1]; + typedef struct {} T2; + typedef struct {} *T3, T4; + using T5 = struct {}; + using T6 = struct {} *; +}; +void f(S::T1) {} +void f(S::T2) {} +void f(S::T3) {} +void f(S::T4) {} +void f(S::T5) {} +void f(S::T6) {} +// CHECK-DAG: @"\01?f@UnnamedType@@YAXQAPAU<unnamed-type-T1>@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT2@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAUT4@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT4@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT5@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAU<unnamed-type-T6>@S@1@@Z" + +// X64-DAG: @"\01?f@UnnamedType@@YAXQEAPEAU<unnamed-type-T1>@S@1@@Z" +// X64-DAG: @"\01?f@UnnamedType@@YAXUT2@S@1@@Z" +// X64-DAG: @"\01?f@UnnamedType@@YAXPEAUT4@S@1@@Z"(%"struct.UnnamedType::S::T4" +// X64-DAG: @"\01?f@UnnamedType@@YAXUT4@S@1@@Z" +// X64-DAG: @"\01?f@UnnamedType@@YAXUT5@S@1@@Z" +// X64-DAG: @"\01?f@UnnamedType@@YAXPEAU<unnamed-type-T6>@S@1@@Z" +} |