PR48002: Fix injection of elaborated-type-specifiers within local

classes into the enclosing block scope.

We weren't properly detecting whether the name would be injected into a
block scope in the case where it was lexically declared in a local
class.
This commit is contained in:
Richard Smith 2020-10-28 14:27:38 -07:00
parent 1ce7040359
commit 09abecef7b
2 changed files with 59 additions and 4 deletions

View File

@ -1478,10 +1478,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
// Out-of-line definitions shouldn't be pushed into scope in C++, unless they
// are function-local declarations.
if (getLangOpts().CPlusPlus && D->isOutOfLine() &&
!D->getDeclContext()->getRedeclContext()->Equals(
D->getLexicalDeclContext()->getRedeclContext()) &&
!D->getLexicalDeclContext()->isFunctionOrMethod())
if (getLangOpts().CPlusPlus && D->isOutOfLine() && !S->getFnParent())
return;
// Template instantiations should also not be pushed into scope.
@ -15728,6 +15725,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// type declared by an elaborated-type-specifier. In C that is not correct
// and we should instead merge compatible types found by lookup.
if (getLangOpts().CPlusPlus) {
// FIXME: This can perform qualified lookups into function contexts,
// which are meaningless.
Previous.setRedeclarationKind(forRedeclarationInCurContext());
LookupQualifiedName(Previous, SearchDC);
} else {

View File

@ -0,0 +1,56 @@
// RUN: %clang_cc1 -verify %s
// Some of the diagnostics produce 'did you mean?' suggestions. We don't care
// which ones for the purpose of this test.
// expected-note@* 0+{{here}}
struct A *f();
using Test_A = A;
void f(struct B*);
using Test_B = B;
struct C;
using Test_C = C;
struct X {
struct D *f();
void f(struct E*);
struct F;
friend struct G;
};
using Test_D = D;
using Test_XD = X::D; // expected-error {{no type named 'D' in 'X'}}
using Test_E = E;
using Test_XE = X::E; // expected-error {{no type named 'E' in 'X'}}
using Test_F = F; // expected-error {{unknown type name 'F'}}
using Test_XF = X::F;
using Test_G = G; // expected-error {{unknown type name 'G'}}
using Test_XG = X::G; // expected-error {{no type named 'G' in 'X'}}
void g() {
{
struct X {
struct H *f();
void f(struct I*);
struct J;
friend struct K;
};
using Test_H = H;
using Test_XH = X::H; // expected-error {{no type named}}
using Test_I = I;
using Test_XI = X::I; // expected-error {{no type named}}
using Test_J = J; // expected-error {{unknown type name}}
using Test_XJ = X::J;
using Test_K = K; // expected-error {{unknown type name}}
using Test_XK = X::K; // expected-error {{no type named}}
}
using Test_H = H; // expected-error {{unknown type name}}
using Test_I = I; // expected-error {{unknown type name}}
using Test_J = J; // expected-error {{unknown type name}}
using Test_K = K; // expected-error {{unknown type name}}
}
using Test_H = H; // expected-error {{unknown type name}}
using Test_I = I; // expected-error {{unknown type name}}
using Test_J = J; // expected-error {{unknown type name}}
using Test_K = K; // expected-error {{unknown type name}}