From 9b7b39116ea07aea979ea49c4ec32ded85a5019f Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 4 Jan 2012 16:44:10 +0000 Subject: [PATCH] Implement declaration merging for typedefs loaded from disjoint modules, so long as the typedefs refer to the same underlying type. This ensures that the typedefs end up in the same redeclaration chain. To test this, fix name lookup for C/Objective-C to properly deal with multiple declarations with the same name in the same scope. llvm-svn: 147533 --- clang/lib/Sema/SemaLookup.cpp | 41 +++++++++++------------ clang/lib/Serialization/ASTReaderDecl.cpp | 24 +++++++++---- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 48ae1b970dda..ae950ff27aa7 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1179,29 +1179,28 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // Check whether there are any other declarations with the same name // and in the same scope. + if (I != IEnd) { + DeclContext *DC = (*I)->getDeclContext()->getRedeclContext(); + IdentifierResolver::iterator LastI = I; + for (++LastI; LastI != IEnd; ++LastI) { + DeclContext *LastDC + = (*LastI)->getDeclContext()->getRedeclContext(); + if (!(*LastI)->isInIdentifierNamespace(IDNS)) + continue; + + if (!LastDC->Equals(DC)) + break; + + if (!LastDC->isFileContext() && !S->isDeclScope(*LastI)) + break; + + D = R.isForRedeclaration()? *LastI : getVisibleDecl(*LastI); + if (D) + R.addDecl(D); + } - // Figure out what scope the identifier is in. - while (S->getParent() && - (!(S->getFlags() & Scope::DeclScope) || - !S->isDeclScope(*I))) - S = S->getParent(); - - // Find the last declaration in this scope (with the same - // name, naturally). - IdentifierResolver::iterator LastI = I; - for (++LastI; LastI != IEnd; ++LastI) { - if (!S->isDeclScope(*LastI)) - break; - - if (!(*LastI)->isInIdentifierNamespace(IDNS)) - continue; - - D = R.isForRedeclaration()? *LastI : getVisibleDecl(*LastI); - if (D) - R.addDecl(D); + R.resolveKind(); } - - R.resolveKind(); return true; } } else { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 4871a3049ab9..c00b69cf75b0 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -402,9 +402,14 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { } void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { - VisitRedeclarable(TD); + // Record the declaration -> global ID mapping. + Reader.DeclToID[TD] = ThisDeclID; + + RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); - TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); + + TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); + mergeRedeclarable(TD, Redecl); } void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { @@ -1668,15 +1673,22 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { if (X == Y) return true; - // Must have the same kind. - if (X->getKind() != Y->getKind()) - return false; - // Must be in the same context. if (!X->getDeclContext()->getRedeclContext()->Equals( Y->getDeclContext()->getRedeclContext())) return false; + + // Two typedefs refer to the same entity if they have the same underlying + // type. + if (TypedefNameDecl *TypedefX = dyn_cast(X)) + if (TypedefNameDecl *TypedefY = dyn_cast(Y)) + return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(), + TypedefY->getUnderlyingType()); + // Must have the same kind. + if (X->getKind() != Y->getKind()) + return false; + // Objective-C classes and protocols with the same name always match. if (isa(X) || isa(X)) return true;