From: Douglas Gregor Date: Tue, 3 Jan 2012 23:26:26 +0000 (+0000) Subject: Test "merging" of typedef types across distinct modules. At present, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7a537404f039d4b7d063bbdc3c8c924be977dff2;p=clang Test "merging" of typedef types across distinct modules. At present, the AST reader doesn't actually perform a merge, because name lookup knows how to merge identical typedefs together. As part of this, teach C/Objective-C name lookup to return multiple results in all cases, rather than first digging through the attributes to see if the value is overloadable. This way, we'll catch ambiguous lookups in C/Objective-C. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147498 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 31a9b3b292..479f80f1dd 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -938,6 +938,12 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { cast(OldD)->getQualifier()); } + // A typedef of an Objective-C class type can replace an Objective-C class + // declaration or definition, and vice versa. + if ((isa(this) && isa(OldD)) || + (isa(this) && isa(OldD))) + return true; + // For non-function declarations, if the declarations are of the // same kind then this must be a redeclaration, or semantic analysis // would not have given us the new declaration. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9583ab6327..43c9af58bc 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8010,8 +8010,6 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // lookup. This is only actually possible in C++, where a few // things like templates still live in the tag namespace. } else { - assert(getLangOptions().CPlusPlus); - // Use a better diagnostic if an elaborated-type-specifier // found the wrong kind of type on the first // (non-redeclaration) lookup. diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 4f53487dcd..f836a077b6 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1177,30 +1177,31 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { R.addDecl(D); - if ((*I)->getAttr()) { - // If this declaration has the "overloadable" attribute, we - // might have a set of overloaded functions. - - // Figure out what scope the identifier is in. - while (!(S->getFlags() & Scope::DeclScope) || - !S->isDeclScope(*I)) - S = S->getParent(); - - // Find the last declaration in this scope (with the same - // name, naturally). - IdentifierResolver::iterator LastI = I; - for (++LastI; LastI != IEnd; ++LastI) { - if (!S->isDeclScope(*LastI)) - break; - - D = getVisibleDecl(*LastI); - if (D) - R.addDecl(D); - } + // Check whether there are any other declarations with the same name + // and in the same scope. + + // Figure out what scope the identifier is in. + while (S->getParent() && + (!(S->getFlags() & Scope::DeclScope) || + !S->isDeclScope(*I))) + S = S->getParent(); + + // Find the last declaration in this scope (with the same + // name, naturally). + IdentifierResolver::iterator LastI = I; + for (++LastI; LastI != IEnd; ++LastI) { + if (!S->isDeclScope(*LastI)) + break; + + if (!(*LastI)->isInIdentifierNamespace(IDNS)) + continue; + + D = getVisibleDecl(*LastI); + if (D) + R.addDecl(D); } R.resolveKind(); - return true; } } else { diff --git a/test/Modules/Inputs/redecl-merge-left.h b/test/Modules/Inputs/redecl-merge-left.h index b21271b146..47f3492f30 100644 --- a/test/Modules/Inputs/redecl-merge-left.h +++ b/test/Modules/Inputs/redecl-merge-left.h @@ -56,6 +56,9 @@ struct S4 { struct S3 *produce_S3(void); void consume_S4(struct S4*); +typedef int T1; +typedef float T2; + #ifdef __cplusplus template class Vector; diff --git a/test/Modules/Inputs/redecl-merge-right.h b/test/Modules/Inputs/redecl-merge-right.h index 686a96228a..315a9c37ff 100644 --- a/test/Modules/Inputs/redecl-merge-right.h +++ b/test/Modules/Inputs/redecl-merge-right.h @@ -59,6 +59,9 @@ struct S4; void consume_S3(struct S3*); struct S4 *produce_S4(void); +typedef int T1; +typedef double T2; + #ifdef __cplusplus template class Vector { public: diff --git a/test/Modules/redecl-merge.m b/test/Modules/redecl-merge.m index c0e83e8a86..44d427c4c7 100644 --- a/test/Modules/redecl-merge.m +++ b/test/Modules/redecl-merge.m @@ -55,6 +55,15 @@ void testTagMerge() { s3.s3_field = 0; } +void testTypedefMerge(int i, double d) { + T1 *ip = &i; + // in other file: expected-note{{candidate found by name lookup is 'T2'}} + // FIXME: Typedefs aren't actually merged in the sense of other merges, because + // we should only merge them when the types are identical. + // in other file: expected-note{{candidate found by name lookup is 'T2'}} + T2 *dp = &d; // expected-error{{reference to 'T2' is ambiguous}} +} + // Test redeclarations of entities in explicit submodules, to make // sure we're maintaining the declaration chains even when normal name // lookup can't see what we're looking for.