diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 13 |
3 files changed, 44 insertions, 20 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7f4b3952807..bc31d4612e5 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16,7 +16,6 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" -#include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/CommentDiagnostic.h" @@ -1974,9 +1973,7 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { New->setTypeSourceInfo(OldTD->getTypeSourceInfo()); // Make the old tag definition visible. - if (auto *Listener = getASTMutationListener()) - Listener->RedefinedHiddenDefinition(Hidden, NewTag->getLocation()); - Hidden->setHidden(false); + makeMergedDefinitionVisible(Hidden, NewTag->getLocation()); } } @@ -11311,8 +11308,8 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S, /// \param IsTypeSpecifier \c true if this is a type-specifier (or /// trailing-type-specifier) other than one in an alias-declaration. /// -/// \param SkipBody If non-null, will be set to true if the caller should skip -/// the definition of this tag, and treat it as if it were a declaration. +/// \param SkipBody If non-null, will be set to indicate if the caller should +/// skip the definition of this tag and treat it as if it were a declaration. Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, @@ -11323,7 +11320,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation ScopedEnumKWLoc, bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, - bool IsTypeSpecifier, bool *SkipBody) { + bool IsTypeSpecifier, SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. IdentifierInfo *OrigName = Name; assert((Name != nullptr || TUK == TUK_Definition) && @@ -11633,6 +11630,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } } + // If we have a known previous declaration to use, then use it. + if (Previous.empty() && SkipBody && SkipBody->Previous) + Previous.addDecl(SkipBody->Previous); + if (!Previous.empty()) { NamedDecl *PrevDecl = Previous.getFoundDecl(); NamedDecl *DirectPrevDecl = @@ -11774,10 +11775,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // assume that this definition is identical to the hidden one // we already have. Make the existing definition visible and // use it in place of this one. - *SkipBody = true; - if (auto *Listener = getASTMutationListener()) - Listener->RedefinedHiddenDefinition(Hidden, KWLoc); - Hidden->setHidden(false); + SkipBody->ShouldSkip = true; + makeMergedDefinitionVisible(Hidden, KWLoc); return Def; } else if (!IsExplicitSpecializationAfterInstantiation) { // A redeclaration in function prototype scope in C isn't @@ -13465,6 +13464,29 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, Val, EnumVal); } +Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II, + SourceLocation IILoc) { + if (!getLangOpts().Modules || !getLangOpts().CPlusPlus) + return SkipBodyInfo(); + + // We have an anonymous enum definition. Look up the first enumerator to + // determine if we should merge the definition with an existing one and + // skip the body. + NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName, + ForRedeclaration); + auto *PrevECD = dyn_cast_or_null<EnumConstantDecl>(PrevDecl); + NamedDecl *Hidden; + if (PrevECD && + !hasVisibleDefinition(cast<NamedDecl>(PrevECD->getDeclContext()), + &Hidden)) { + SkipBodyInfo Skip; + Skip.ShouldSkip = true; + Skip.Previous = Hidden; + return Skip; + } + + return SkipBodyInfo(); +} Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 09424a48d63..012c1cf3927 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/Lookup.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -1169,6 +1170,12 @@ static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) { return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom(); } +void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) { + if (auto *Listener = getASTMutationListener()) + Listener->RedefinedHiddenDefinition(ND, Loc); + ND->setHidden(false); +} + /// \brief Find the module in which the given declaration was defined. static Module *getDefiningModule(Decl *Entity) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Entity)) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c642c0599b5..687e6111f2d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -12,7 +12,6 @@ #include "TreeTransform.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" @@ -838,7 +837,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, TemplateParameterList** OuterTemplateParamLists, - bool *SkipBody) { + SkipBodyInfo *SkipBody) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); assert(TUK != TUK_Reference && "Can only declare or define class templates"); @@ -999,16 +998,12 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // simply making that previous definition visible. NamedDecl *Hidden = nullptr; if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) { - *SkipBody = true; + SkipBody->ShouldSkip = true; auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate(); assert(Tmpl && "original definition of a class template is not a " "class template?"); - if (auto *Listener = getASTMutationListener()) { - Listener->RedefinedHiddenDefinition(Hidden, KWLoc); - Listener->RedefinedHiddenDefinition(Tmpl, KWLoc); - } - Hidden->setHidden(false); - Tmpl->setHidden(false); + makeMergedDefinitionVisible(Hidden, KWLoc); + makeMergedDefinitionVisible(Tmpl, KWLoc); return Def; } |