aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-07-07 23:08:52 +0000
committerDouglas Gregor <dgregor@apple.com>2010-07-07 23:08:52 +0000
commit09acc9863fe422dc83725f77991bf80551664ada (patch)
tree303d9e0042c23a72e82d10382f20f28cd386343c
parent016a4a90c8e75d59de731fa3aa98f0a55656e66c (diff)
A using declaration can redeclare a typedef to the same type. These
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
-rw-r--r--lib/Sema/SemaDeclCXX.cpp27
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp13
2 files changed, 38 insertions, 2 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index df1143c5c9..bd97df2ce9 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp
index ec814b1ab9..dd44bfc914 100644
--- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp
@@ -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