diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 31a9b3b2929f..479f80f1dd4d 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9583ab6327f0..43c9af58bc98 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 4f53487dcdbb..f836a077b6bb 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/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. + // 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->getFlags() & Scope::DeclScope) || - !S->isDeclScope(*I)) - S = S->getParent(); + // 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; - - D = getVisibleDecl(*LastI); - if (D) - R.addDecl(D); - } + // 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/clang/test/Modules/Inputs/redecl-merge-left.h b/clang/test/Modules/Inputs/redecl-merge-left.h index b21271b14621..47f3492f309b 100644 --- a/clang/test/Modules/Inputs/redecl-merge-left.h +++ b/clang/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/clang/test/Modules/Inputs/redecl-merge-right.h b/clang/test/Modules/Inputs/redecl-merge-right.h index 686a96228a19..315a9c37fff5 100644 --- a/clang/test/Modules/Inputs/redecl-merge-right.h +++ b/clang/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/clang/test/Modules/redecl-merge.m b/clang/test/Modules/redecl-merge.m index c0e83e8a8649..44d427c4c755 100644 --- a/clang/test/Modules/redecl-merge.m +++ b/clang/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.