]> granicus.if.org Git - clang/commitdiff
Implement declaration merging for typedefs loaded from disjoint
authorDouglas Gregor <dgregor@apple.com>
Wed, 4 Jan 2012 16:44:10 +0000 (16:44 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 4 Jan 2012 16:44:10 +0000 (16:44 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147533 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaLookup.cpp
lib/Serialization/ASTReaderDecl.cpp

index 48ae1b970ddabc44c4aa0439f73e63c634232dd7..ae950ff27aa7bd692bb5276be0a3ef0496174cbc 100644 (file)
@@ -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 {
index 4871a3049ab9c53c8eb1f2f5e3fb5f1f9b81ffc2..c00b69cf75b0a503f1e16964072ae3ac95af2738 100644 (file)
@@ -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<TypedefNameDecl>(X))
+    if (TypedefNameDecl *TypedefY = dyn_cast<TypedefNameDecl>(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<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
     return true;