PR17731: When determining whether a tag and a non-tag were declared in the same

scope, be careful about function-scope declarations (which are not declared in
their semantic context).

llvm-svn: 193671
This commit is contained in:
Richard Smith 2013-10-30 01:02:04 +00:00
parent 60db142d86
commit 3876cc88ac
2 changed files with 62 additions and 2 deletions

View File

@ -337,6 +337,21 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) {
delete Paths;
}
/// Get a representative context for a declaration such that two declarations
/// will have the same context if they were found within the same scope.
DeclContext *getContextForScopeMatching(Decl *D) {
// For function-local declarations, use that function as the context. This
// doesn't account for scopes within the function; the caller must deal with
// those.
DeclContext *DC = D->getLexicalDeclContext();
if (DC->isFunctionOrMethod())
return DC;
// Otherwise, look at the semantic context of the declaration. The
// declaration must have been found there.
return D->getDeclContext()->getRedeclContext();
}
/// Resolves the result kind of this lookup.
void LookupResult::resolveKind() {
unsigned N = Decls.size();
@ -437,8 +452,8 @@ void LookupResult::resolveKind() {
// even if they're not visible. (ref?)
if (HideTags && HasTag && !Ambiguous &&
(HasFunction || HasNonFunction || HasUnresolved)) {
if (Decls[UniqueTagIndex]->getDeclContext()->getRedeclContext()->Equals(
Decls[UniqueTagIndex? 0 : N-1]->getDeclContext()->getRedeclContext()))
if (getContextForScopeMatching(Decls[UniqueTagIndex])->Equals(
getContextForScopeMatching(Decls[UniqueTagIndex ? 0 : N - 1])))
Decls[UniqueTagIndex] = Decls[--N];
else
Ambiguous = true;

View File

@ -22,3 +22,48 @@ void f() {
Y(1); // okay
}
namespace PR17731 {
void f() {
struct S { S() {} };
int S(void);
int a = S();
struct S b;
{
int S(void);
int a = S();
struct S c = b;
}
{
struct S { S() {} }; // expected-note {{candidate}}
int a = S(); // expected-error {{no viable conversion from 'S'}}
struct S c = b; // expected-error {{no viable conversion from 'struct S'}}
}
}
void g() {
int S(void);
struct S { S() {} };
int a = S();
struct S b;
{
int S(void);
int a = S();
struct S c = b;
}
{
struct S { S() {} }; // expected-note {{candidate}}
int a = S(); // expected-error {{no viable conversion from 'S'}}
struct S c = b; // expected-error {{no viable conversion from 'struct S'}}
}
}
struct A {
struct B;
void f();
int B;
};
struct A::B {};
void A::f() {
B = 123;
struct B b;
}
}