diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-07-07 23:08:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-07-07 23:08:52 +0000 |
commit | 09acc9863fe422dc83725f77991bf80551664ada (patch) | |
tree | 303d9e0042c23a72e82d10382f20f28cd386343c | |
parent | 016a4a90c8e75d59de731fa3aa98f0a55656e66c (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.cpp | 27 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp | 13 |
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 |