forked from OSchip/llvm-project
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:
parent
1ce7040359
commit
09abecef7b
|
@ -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 {
|
||||
|
|
|
@ -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}}
|
Loading…
Reference in New Issue