]> granicus.if.org Git - clang/commitdiff
If name lookup finds different type declarations in different scopes
authorDouglas Gregor <dgregor@apple.com>
Wed, 11 Aug 2010 14:45:53 +0000 (14:45 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 11 Aug 2010 14:45:53 +0000 (14:45 +0000)
that actually refer to the same underlying type, it is not an
ambiguity; add uniquing support based on the canonical type of type
declarations. Fixes <rdar://problem/8296180>.

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

lib/Sema/SemaLookup.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp [new file with mode: 0644]

index 2e651838df954d4a5a5485ea4e50f33457a8b855..837cafda15464e677f8f491a8c0ca7630af928e5 100644 (file)
@@ -311,7 +311,8 @@ void LookupResult::resolveKind() {
   if (ResultKind == Ambiguous) return;
 
   llvm::SmallPtrSet<NamedDecl*, 16> Unique;
-
+  llvm::SmallPtrSet<QualType, 16> UniqueTypes;
+  
   bool Ambiguous = false;
   bool HasTag = false, HasFunction = false, HasNonFunction = false;
   bool HasFunctionTemplate = false, HasUnresolved = false;
@@ -323,32 +324,49 @@ void LookupResult::resolveKind() {
     NamedDecl *D = Decls[I]->getUnderlyingDecl();
     D = cast<NamedDecl>(D->getCanonicalDecl());
 
+    // Redeclarations of types via typedef can occur both within a scope
+    // and, through using declarations and directives, across scopes. There is
+    // no ambiguity if they all refer to the same type, so unique based on the
+    // canonical type.
+    if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
+      if (!TD->getDeclContext()->isRecord()) {
+        QualType T = SemaRef.Context.getTypeDeclType(TD);
+        if (!UniqueTypes.insert(SemaRef.Context.getCanonicalType(T))) {
+          // The type is not unique; pull something off the back and continue
+          // at this index.
+          Decls[I] = Decls[--N];
+          continue;
+        }
+      }
+    }
+    
     if (!Unique.insert(D)) {
       // If it's not unique, pull something off the back (and
       // continue at this index).
       Decls[I] = Decls[--N];
+      continue;
+    } 
+    
+    // Otherwise, do some decl type analysis and then continue.
+
+    if (isa<UnresolvedUsingValueDecl>(D)) {
+      HasUnresolved = true;
+    } else if (isa<TagDecl>(D)) {
+      if (HasTag)
+        Ambiguous = true;
+      UniqueTagIndex = I;
+      HasTag = true;
+    } else if (isa<FunctionTemplateDecl>(D)) {
+      HasFunction = true;
+      HasFunctionTemplate = true;
+    } else if (isa<FunctionDecl>(D)) {
+      HasFunction = true;
     } else {
-      // Otherwise, do some decl type analysis and then continue.
-
-      if (isa<UnresolvedUsingValueDecl>(D)) {
-        HasUnresolved = true;
-      } else if (isa<TagDecl>(D)) {
-        if (HasTag)
-          Ambiguous = true;
-        UniqueTagIndex = I;
-        HasTag = true;
-      } else if (isa<FunctionTemplateDecl>(D)) {
-        HasFunction = true;
-        HasFunctionTemplate = true;
-      } else if (isa<FunctionDecl>(D)) {
-        HasFunction = true;
-      } else {
-        if (HasNonFunction)
-          Ambiguous = true;
-        HasNonFunction = true;
-      }
-      I++;
+      if (HasNonFunction)
+        Ambiguous = true;
+      HasNonFunction = true;
     }
+    I++;
   }
 
   // C++ [basic.scope.hiding]p2:
index 27b41a755ed05a6f7f4b491f1a29bfdcb535b3fd..546c4a477f7b631797be57d9f3d9336aea84e5ad 100644 (file)
@@ -31,3 +31,4 @@ namespace test1 {
     using test1::foo;
   }
 }
+
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp
new file mode 100644 (file)
index 0000000..4cb91cd
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// <rdar://problem/8296180>
+typedef int pid_t;
+namespace ns {
+  typedef int pid_t;
+}
+using namespace ns;
+pid_t x;
+
+struct A { };
+namespace ns {
+  typedef ::A A;
+}
+A a;