diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-05-07 03:54:19 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-05-07 03:54:19 +0000 |
commit | d9ba224f66af76e66352dcabd52a030e382ee235 (patch) | |
tree | 2672a07b55bb73c955fe0ae06ba1a4292e7487a1 /clang/lib/Sema/SemaDecl.cpp | |
parent | 69a4779965a47ca7ce767a2c28fd8ffc041df77c (diff) | |
download | bcm5719-llvm-d9ba224f66af76e66352dcabd52a030e382ee235.tar.gz bcm5719-llvm-d9ba224f66af76e66352dcabd52a030e382ee235.zip |
[modules] Suport for merging a parsed enum definition into an existing imported but not visible definition.
llvm-svn: 236690
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 44 |
1 files changed, 33 insertions, 11 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, |