From: Douglas Gregor Date: Wed, 7 Jul 2010 23:08:52 +0000 (+0000) Subject: A using declaration can redeclare a typedef to the same type. These X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=09acc9863fe422dc83725f77991bf80551664ada;p=clang 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107833 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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(D1)) + if (TypedefDecl *TD2 = dyn_cast(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(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