]> granicus.if.org Git - clang/commitdiff
A using declaration can redeclare a typedef to the same type. These
authorDouglas Gregor <dgregor@apple.com>
Wed, 7 Jul 2010 23:08:52 +0000 (23:08 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 7 Jul 2010 23:08:52 +0000 (23:08 +0000)
typedefs won't have the same canonical declaration (since they are
distinct), so we need to check for this case specifically. Fixes
<rdar://problem/8018262>.

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

lib/Sema/SemaDeclCXX.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp

index df1143c5c909e8bd73d96ee17709508a8224218e..bd97df2ce9d1232efd793b4bab4339102400b020 100644 (file)
@@ -3496,6 +3496,28 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
   return DeclPtrTy::make(UD);
 }
 
+/// \brief Determine whether a using declaration considers the given
+/// declarations as "equivalent", e.g., if they are redeclarations of
+/// the same entity or are both typedefs of the same type.
+static bool 
+IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
+                         bool &SuppressRedeclaration) {
+  if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) {
+    SuppressRedeclaration = false;
+    return true;
+  }
+
+  if (TypedefDecl *TD1 = dyn_cast<TypedefDecl>(D1))
+    if (TypedefDecl *TD2 = dyn_cast<TypedefDecl>(D2)) {
+      SuppressRedeclaration = true;
+      return Context.hasSameType(TD1->getUnderlyingType(),
+                                 TD2->getUnderlyingType());
+    }
+
+  return false;
+}
+
+
 /// Determines whether to create a using shadow decl for a particular
 /// decl, given the set of decls existing prior to this using lookup.
 bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
@@ -3562,8 +3584,9 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
   for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
          I != E; ++I) {
     NamedDecl *D = (*I)->getUnderlyingDecl();
-    if (D->getCanonicalDecl() == Target->getCanonicalDecl())
-      return false;
+    bool Result;
+    if (IsEquivalentForUsingDecl(Context, D, Target, Result))
+      return Result;
 
     (isa<TagDecl>(D) ? Tag : NonTag) = D;
   }
index ec814b1ab97c64ef48cb02dec99fe6fa6c5287db..dd44bfc914b2d55d6ea900d5b483a81702385b87 100644 (file)
@@ -55,6 +55,19 @@ namespace test0 {
   }
 }
 
+// Typedef redeclaration.
+namespace rdar8018262 {
+  typedef void (*fp)();
+
+  namespace N {
+    typedef void (*fp)();
+  }
+
+  using N::fp;
+
+  fp fp_1;
+}
+
 // Things to test:
 //   member operators
 //   conversion operators