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.

llvm-svn: 147498
This commit is contained in:
Douglas Gregor 2012-01-03 23:26:26 +00:00
parent f83663a9cd
commit b59643baf6
6 changed files with 41 additions and 21 deletions

View File

@ -938,6 +938,12 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
cast<UsingDecl>(OldD)->getQualifier());
}
// A typedef of an Objective-C class type can replace an Objective-C class
// declaration or definition, and vice versa.
if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) ||
(isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(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.

View File

@ -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.

View File

@ -1177,13 +1177,13 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
R.addDecl(D);
if ((*I)->getAttr<OverloadableAttr>()) {
// 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))
while (S->getParent() &&
(!(S->getFlags() & Scope::DeclScope) ||
!S->isDeclScope(*I)))
S = S->getParent();
// Find the last declaration in this scope (with the same
@ -1193,14 +1193,15 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
if (!S->isDeclScope(*LastI))
break;
if (!(*LastI)->isInIdentifierNamespace(IDNS))
continue;
D = getVisibleDecl(*LastI);
if (D)
R.addDecl(D);
}
}
R.resolveKind();
return true;
}
} else {

View File

@ -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<typename T> class Vector;

View File

@ -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<typename T> class Vector {
public:

View File

@ -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.