diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/IdentifierResolver.cpp | 165 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 5 |
3 files changed, 157 insertions, 25 deletions
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index a643267085..812f5d64fa 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -15,7 +15,10 @@ #include "clang/Sema/IdentifierResolver.h" #include "clang/Sema/Scope.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" #include "clang/Basic/LangOptions.h" +#include "clang/Lex/ExternalPreprocessorSource.h" +#include "clang/Lex/Preprocessor.h" using namespace clang; @@ -93,9 +96,11 @@ IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { // IdentifierResolver Implementation //===----------------------------------------------------------------------===// -IdentifierResolver::IdentifierResolver(const LangOptions &langOpt) - : LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) { +IdentifierResolver::IdentifierResolver(Preprocessor &PP) + : LangOpt(PP.getLangOptions()), PP(PP), + IdDeclInfos(new IdDeclInfoMap) { } + IdentifierResolver::~IdentifierResolver() { delete IdDeclInfos; } @@ -146,7 +151,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, void IdentifierResolver::AddDecl(NamedDecl *D) { DeclarationName Name = D->getDeclName(); if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + updatingIdentifier(*II); void *Ptr = Name.getFETokenInfo<void>(); @@ -170,6 +175,9 @@ void IdentifierResolver::AddDecl(NamedDecl *D) { void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + updatingIdentifier(*II); + void *Ptr = Name.getFETokenInfo<void>(); if (!Ptr) { @@ -195,7 +203,8 @@ void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { } if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + if (II->isFromAST()) + II->setChangedSinceDeserialization(); // General case: insert the declaration at the appropriate point in the // list, which already has at least two elements. @@ -212,7 +221,7 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) { assert(D && "null param passed"); DeclarationName Name = D->getDeclName(); if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + updatingIdentifier(*II); void *Ptr = Name.getFETokenInfo<void>(); @@ -233,7 +242,7 @@ bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { DeclarationName Name = Old->getDeclName(); if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + updatingIdentifier(*II); void *Ptr = Name.getFETokenInfo<void>(); @@ -254,6 +263,9 @@ bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { /// begin - Returns an iterator for decls with name 'Name'. IdentifierResolver::iterator IdentifierResolver::begin(DeclarationName Name) { + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + readingIdentifier(*II); + void *Ptr = Name.getFETokenInfo<void>(); if (!Ptr) return end(); @@ -269,27 +281,142 @@ IdentifierResolver::begin(DeclarationName Name) { return end(); } -void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II, - NamedDecl *D) { - II->setIsFromAST(false); - void *Ptr = II->getFETokenInfo<void>(); +namespace { + enum DeclMatchKind { + DMK_Different, + DMK_Replace, + DMK_Ignore + }; +} - if (!Ptr) { - II->setFETokenInfo(D); - return; +/// \brief Compare two declarations to see whether they are different or, +/// if they are the same, whether the new declaration should replace the +/// existing declaration. +static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) { + // If the declarations are identical, ignore the new one. + if (Existing == New) + return DMK_Ignore; + + // If the declarations have different kinds, they're obviously different. + if (Existing->getKind() != New->getKind()) + return DMK_Different; + + // If the declarations are redeclarations of each other, keep the newest one. + if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) { + // If the existing declaration is somewhere in the previous declaration + // chain of the new declaration, then prefer the new declaration. + for (Decl::redecl_iterator RD = New->redecls_begin(), + RDEnd = New->redecls_end(); + RD != RDEnd; ++RD) { + if (*RD == Existing) + return DMK_Replace; + + if (RD->isCanonicalDecl()) + break; + } + + return DMK_Ignore; } + + // If the declarations are both Objective-C classes, and one is a forward + // declaration and the other is not, take the full definition. + // FIXME: At some point, we'll actually have to detect collisions better. + // This logic, however, belongs in the AST reader, not here. + if (ObjCInterfaceDecl *ExistingIFace = dyn_cast<ObjCInterfaceDecl>(Existing)) + if (ObjCInterfaceDecl *NewIFace = dyn_cast<ObjCInterfaceDecl>(New)) + if (ExistingIFace->isForwardDecl() != NewIFace->isForwardDecl()) + return ExistingIFace->isForwardDecl()? DMK_Replace : DMK_Ignore; + + return DMK_Different; +} +bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){ + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + updatingIdentifier(*II); + + void *Ptr = Name.getFETokenInfo<void>(); + + if (!Ptr) { + Name.setFETokenInfo(D); + return true; + } + IdDeclInfo *IDI; - + if (isDeclPtr(Ptr)) { - II->setFETokenInfo(NULL); - IDI = &(*IdDeclInfos)[II]; NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); - IDI->AddDecl(PrevD); - } else - IDI = toIdDeclInfo(Ptr); + + switch (compareDeclarations(PrevD, D)) { + case DMK_Different: + break; + + case DMK_Ignore: + return false; + + case DMK_Replace: + Name.setFETokenInfo(D); + return true; + } + + Name.setFETokenInfo(NULL); + IDI = &(*IdDeclInfos)[Name]; + + // If the existing declaration is not visible in translation unit scope, + // then add the new top-level declaration first. + if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + IDI->AddDecl(D); + IDI->AddDecl(PrevD); + } else { + IDI->AddDecl(PrevD); + IDI->AddDecl(D); + } + return true; + } + + IDI = toIdDeclInfo(Ptr); + // See whether this declaration is identical to any existing declarations. + // If not, find the right place to insert it. + for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(), + IEnd = IDI->decls_end(); + I != IEnd; ++I) { + + switch (compareDeclarations(*I, D)) { + case DMK_Different: + break; + + case DMK_Ignore: + return false; + + case DMK_Replace: + *I = D; + return true; + } + + if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + // We've found a declaration that is not visible from the translation + // unit (it's in an inner scope). Insert our declaration here. + IDI->InsertDecl(I, D); + return true; + } + } + + // Add the declaration to the end. IDI->AddDecl(D); + return true; +} + +void IdentifierResolver::readingIdentifier(IdentifierInfo &II) { + if (II.isOutOfDate()) + PP.getExternalSource()->updateOutOfDateIdentifier(II); +} + +void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) { + if (II.isOutOfDate()) + PP.getExternalSource()->updateOutOfDateIdentifier(II); + + if (II.isFromAST()) + II.setChangedSinceDeserialization(); } //===----------------------------------------------------------------------===// diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 8346cc475f..9b788a7058 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -98,7 +98,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, CurContext(0), OriginalLexicalContext(0), PackContext(0), MSStructPragmaOn(false), VisContext(0), ExprNeedsCleanups(0), LateTemplateParser(0), OpaqueParser(0), - IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0), + IdResolver(pp), CXXTypeInfoDecl(0), MSVCGuidDecl(0), GlobalNewDeleteDeclared(false), ObjCShouldCallSuperDealloc(false), ObjCShouldCallSuperFinalize(false), @@ -143,11 +143,11 @@ void Sema::Initialize() { // If either of the 128-bit integer types are unavailable to name lookup, // define them now. DeclarationName Int128 = &Context.Idents.get("__int128_t"); - if (IdentifierResolver::begin(Int128) == IdentifierResolver::end()) + if (IdResolver.begin(Int128) == IdResolver.end()) PushOnScopeChains(Context.getInt128Decl(), TUScope); DeclarationName UInt128 = &Context.Idents.get("__uint128_t"); - if (IdentifierResolver::begin(UInt128) == IdentifierResolver::end()) + if (IdResolver.begin(UInt128) == IdResolver.end()) PushOnScopeChains(Context.getUInt128Decl(), TUScope); } @@ -157,18 +157,18 @@ void Sema::Initialize() { // If 'SEL' does not yet refer to any declarations, make it refer to the // predefined 'SEL'. DeclarationName SEL = &Context.Idents.get("SEL"); - if (IdentifierResolver::begin(SEL) == IdentifierResolver::end()) + if (IdResolver.begin(SEL) == IdResolver.end()) PushOnScopeChains(Context.getObjCSelDecl(), TUScope); // If 'id' does not yet refer to any declarations, make it refer to the // predefined 'id'. DeclarationName Id = &Context.Idents.get("id"); - if (IdentifierResolver::begin(Id) == IdentifierResolver::end()) + if (IdResolver.begin(Id) == IdResolver.end()) PushOnScopeChains(Context.getObjCIdDecl(), TUScope); // Create the built-in typedef for 'Class'. DeclarationName Class = &Context.Idents.get("Class"); - if (IdentifierResolver::begin(Class) == IdentifierResolver::end()) + if (IdResolver.begin(Class) == IdResolver.end()) PushOnScopeChains(Context.getObjCClassDecl(), TUScope); } } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 5f26c3185b..fb00c918ab 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -938,6 +938,11 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { } } +void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { + if (IdResolver.tryAddTopLevelDecl(D, Name) && TUScope) + TUScope->AddDecl(D); +} + bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, bool ExplicitInstantiationOrSpecialization) { return IdResolver.isDeclInScope(D, Ctx, Context, S, |