forked from OSchip/llvm-project
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:
parent
f83663a9cd
commit
b59643baf6
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1177,30 +1177,31 @@ 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))
|
||||
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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue