diff options
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 6 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 98 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 7 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle.cpp | 30 |
5 files changed, 101 insertions, 53 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0b36d58806a..77a47b8861d 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1588,6 +1588,9 @@ public: void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); void CheckShadow(Scope *S, VarDecl *D); void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); + void handleTagNumbering(const TagDecl *Tag, Scope *TagScope); + void setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, + TypedefNameDecl *NewTD); void CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *D); NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, TypeSourceInfo *TInfo, @@ -3989,7 +3992,8 @@ public: SourceLocation UsingLoc, UnqualifiedId &Name, AttributeList *AttrList, - TypeResult Type); + TypeResult Type, + Decl *DeclFromDeclSpec); /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 04bb4405cbf..4e58ca345fb 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -558,6 +558,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, // Maybe this is an alias-declaration. TypeResult TypeAlias; bool IsAliasDecl = Tok.is(tok::equal); + Decl *DeclFromDeclSpec = nullptr; if (IsAliasDecl) { // If we had any misplaced attributes from earlier, this is where they // should have been written. @@ -612,10 +613,12 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) << FixItHint::CreateRemoval(SS.getRange()); - TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind ? - Declarator::AliasTemplateContext : - Declarator::AliasDeclContext, AS, OwnedType, - &Attrs); + TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind + ? Declarator::AliasTemplateContext + : Declarator::AliasDeclContext, + AS, &DeclFromDeclSpec, &Attrs); + if (OwnedType) + *OwnedType = DeclFromDeclSpec; } else { // C++11 attributes are not allowed on a using-declaration, but GNU ones // are. @@ -664,7 +667,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, TemplateParams ? TemplateParams->size() : 0); return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, UsingLoc, Name, Attrs.getList(), - TypeAlias); + TypeAlias, DeclFromDeclSpec); } return Actions.ActOnUsingDeclaration(getCurScope(), AS, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e9b0f5a3fbd..dc428569bea 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3416,8 +3416,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg()); } -static void HandleTagNumbering(Sema &S, const TagDecl *Tag, Scope *TagScope) { - if (!S.Context.getLangOpts().CPlusPlus) +void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) { + if (!Context.getLangOpts().CPlusPlus) return; if (isa<CXXRecordDecl>(Tag->getParent())) { @@ -3426,23 +3426,63 @@ static void HandleTagNumbering(Sema &S, const TagDecl *Tag, Scope *TagScope) { if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl()) return; MangleNumberingContext &MCtx = - S.Context.getManglingNumberContext(Tag->getParent()); - S.Context.setManglingNumber( + Context.getManglingNumberContext(Tag->getParent()); + Context.setManglingNumber( Tag, MCtx.getManglingNumber(Tag, TagScope->getMSLocalManglingNumber())); return; } // If this tag isn't a direct child of a class, number it if it is local. Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = - S.getCurrentMangleNumberContext(Tag->getDeclContext(), - ManglingContextDecl)) { - S.Context.setManglingNumber( + if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( + Tag->getDeclContext(), ManglingContextDecl)) { + Context.setManglingNumber( Tag, MCtx->getManglingNumber(Tag, TagScope->getMSLocalManglingNumber())); } } +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()) + return; + + // A well-formed anonymous tag must always be a TUK_Definition. + assert(TagFromDeclSpec->isThisDeclarationADefinition()); + + // The type must match the tag exactly; no qualifiers allowed. + if (!Context.hasSameType(NewTD->getUnderlyingType(), + Context.getTagDeclType(TagFromDeclSpec))) + return; + + // If we've already computed linkage for the anonymous tag, then + // adding a typedef name for the anonymous decl can change that + // linkage, which might be a serious problem. Diagnose this as + // unsupported and ignore the typedef name. TODO: we should + // pursue this as a language defect and establish a formal rule + // for how to handle it. + if (TagFromDeclSpec->hasLinkageBeenComputed()) { + Diag(NewTD->getLocation(), diag::err_typedef_changes_linkage); + + SourceLocation tagLoc = TagFromDeclSpec->getInnerLocStart(); + tagLoc = getLocForEndOfToken(tagLoc); + + llvm::SmallString<40> textToInsert; + textToInsert += ' '; + textToInsert += NewTD->getIdentifier()->getName(); + Diag(tagLoc, diag::note_typedef_changes_linkage) + << FixItHint::CreateInsertion(tagLoc, textToInsert); + return; + } + + // Otherwise, set this is the anon-decl typedef for the tag. + TagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); +} + /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. It also accepts template /// parameters to cope with template friend declarations. @@ -3472,7 +3512,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } if (Tag) { - HandleTagNumbering(*this, Tag, S); + handleTagNumbering(Tag, S); Tag->setFreeStanding(); if (Tag->isInvalidDecl()) return Tag; @@ -9720,7 +9760,7 @@ 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(*this, Tag, S); + handleTagNumbering(Tag, S); if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl()) Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup); } @@ -10935,44 +10975,10 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, case TST_union: case TST_class: { TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); - - // 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()) break; - if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break; - - // A well-formed anonymous tag must always be a TUK_Definition. - assert(tagFromDeclSpec->isThisDeclarationADefinition()); - - // The type must match the tag exactly; no qualifiers allowed. - if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec))) - break; - - // If we've already computed linkage for the anonymous tag, then - // adding a typedef name for the anonymous decl can change that - // linkage, which might be a serious problem. Diagnose this as - // unsupported and ignore the typedef name. TODO: we should - // pursue this as a language defect and establish a formal rule - // for how to handle it. - if (tagFromDeclSpec->hasLinkageBeenComputed()) { - Diag(D.getIdentifierLoc(), diag::err_typedef_changes_linkage); - - SourceLocation tagLoc = D.getDeclSpec().getTypeSpecTypeLoc(); - tagLoc = getLocForEndOfToken(tagLoc); - - llvm::SmallString<40> textToInsert; - textToInsert += ' '; - textToInsert += D.getIdentifier()->getName(); - Diag(tagLoc, diag::note_typedef_changes_linkage) - << FixItHint::CreateInsertion(tagLoc, textToInsert); - break; - } - - // Otherwise, set this is the anon-decl typedef for the tag. - tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); + setTagNameForLinkagePurposes(tagFromDeclSpec, NewTD); break; } - + default: break; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 57d9ad264e7..45ba685d118 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8474,7 +8474,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, SourceLocation UsingLoc, UnqualifiedId &Name, AttributeList *AttrList, - TypeResult Type) { + TypeResult Type, + Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. while (S->getFlags() & Scope::TemplateParamScope) S = S->getParent(); @@ -8602,6 +8603,10 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, NewND = NewDecl; } else { + if (auto *TD = dyn_cast_or_null<TagDecl>(DeclFromDeclSpec)) { + setTagNameForLinkagePurposes(TD, NewTD); + handleTagNumbering(TD, S); + } ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); NewND = NewTD; } diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index 34f091d0369..5012c3b3798 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/test/CodeGenCXX/mangle.cpp @@ -1071,3 +1071,33 @@ auto f4(T... x) -> decltype(operator+(x...)); // CHECK-LABEL: @_ZN6test522f4IJNS_1XEEEEDTclonplspfp_EEDpT_ void use() { f4(X{}); } } + +namespace test53 { +struct c { + using t1 = struct { int z; }; + using t2 = struct { double z; }; + using t3 = struct { float z; }; + using t4 = struct { float z; }; + + __attribute__((used)) c(t1) {} + __attribute__((used)) c(t2) {} + __attribute__((used)) c(t3) {} + __attribute__((used)) c(t4) {} + // CHECK-LABEL: @_ZN6test531cC2ENS0_2t1E + // CHECK-LABEL: @_ZN6test531cC2ENS0_2t2E + // CHECK-LABEL: @_ZN6test531cC2ENS0_2t3E + // CHECK-LABEL: @_ZN6test531cC2ENS0_2t4E +}; +} + +namespace test54 { +struct c { + using t1 = struct { int z; } *; + using t2 = struct { double z; } *; + + __attribute__((used)) c(t1) {} + __attribute__((used)) c(t2) {} + // CHECK-LABEL: @_ZN6test541cC2EPNS0_Ut_E + // CHECK-LABEL: @_ZN6test541cC2EPNS0_Ut0_E +}; +} |