forked from OSchip/llvm-project
[Clang] Fix BZ47169, loader_uninitialized on incomplete types
[Clang] Fix BZ47169, loader_uninitialized on incomplete types Reported by @erichkeane. Fix proposed by @erichkeane works, tests included. Bug introduced in D74361. Crash was on querying a CXXRecordDecl for hasTrivialDefaultConstructor on an incomplete type. Fixed by calling RequireCompleteType in the right place. Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D85990
This commit is contained in:
parent
33c554d844
commit
bcaa806a47
|
@ -12476,6 +12476,17 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
|
|||
}
|
||||
|
||||
if (!Var->isInvalidDecl() && RealDecl->hasAttr<LoaderUninitializedAttr>()) {
|
||||
if (Var->getStorageClass() == SC_Extern) {
|
||||
Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl)
|
||||
<< Var;
|
||||
Var->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
if (RequireCompleteType(Var->getLocation(), Var->getType(),
|
||||
diag::err_typecheck_decl_incomplete_type)) {
|
||||
Var->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
if (CXXRecordDecl *RD = Var->getType()->getAsCXXRecordDecl()) {
|
||||
if (!RD->hasTrivialDefaultConstructor()) {
|
||||
Diag(Var->getLocation(), diag::err_loader_uninitialized_trivial_ctor);
|
||||
|
@ -12483,12 +12494,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (Var->getStorageClass() == SC_Extern) {
|
||||
Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl)
|
||||
<< Var;
|
||||
Var->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition();
|
||||
|
|
|
@ -28,3 +28,15 @@ double arr[32] __attribute__((loader_uninitialized));
|
|||
// Defining as arr2[] [[clang..]] raises the error: attribute cannot be applied to types
|
||||
// CHECK: @arr2 = global [4 x double] undef
|
||||
double arr2 [[clang::loader_uninitialized]] [4];
|
||||
|
||||
template<typename T> struct templ{T * t;};
|
||||
|
||||
// CHECK: @templ_int = global %struct.templ undef, align 8
|
||||
templ<int> templ_int [[clang::loader_uninitialized]];
|
||||
|
||||
// CHECK: @templ_trivial = global %struct.templ.0 undef, align 8
|
||||
templ<trivial> templ_trivial [[clang::loader_uninitialized]];
|
||||
|
||||
// CHECK: @templ_incomplete = global %struct.templ.1 undef, align 8
|
||||
struct incomplete;
|
||||
templ<incomplete> templ_incomplete [[clang::loader_uninitialized]];
|
||||
|
|
|
@ -10,6 +10,10 @@ const int can_still_be_const __attribute__((loader_uninitialized));
|
|||
extern int external_rejected __attribute__((loader_uninitialized));
|
||||
// expected-error@-1 {{variable 'external_rejected' cannot be declared both 'extern' and with the 'loader_uninitialized' attribute}}
|
||||
|
||||
struct S;
|
||||
extern struct S incomplete_external_rejected __attribute__((loader_uninitialized));
|
||||
// expected-error@-1 {{variable 'incomplete_external_rejected' cannot be declared both 'extern' and with the 'loader_uninitialized' attribute}}
|
||||
|
||||
int noargs __attribute__((loader_uninitialized(0)));
|
||||
// expected-error@-1 {{'loader_uninitialized' attribute takes no arguments}}
|
||||
|
||||
|
@ -35,3 +39,8 @@ __private_extern__ int initialized_private_extern_rejected __attribute__((loader
|
|||
|
||||
extern __attribute__((visibility("hidden"))) int extern_hidden __attribute__((loader_uninitialized));
|
||||
// expected-error@-1 {{variable 'extern_hidden' cannot be declared both 'extern' and with the 'loader_uninitialized' attribute}}
|
||||
|
||||
struct Incomplete;
|
||||
struct Incomplete incomplete __attribute__((loader_uninitialized));
|
||||
// expected-error@-1 {{variable has incomplete type 'struct Incomplete'}}
|
||||
// expected-note@-3 {{forward declaration of 'struct Incomplete'}}
|
||||
|
|
|
@ -9,6 +9,10 @@ const int still_cant_be_const __attribute__((loader_uninitialized));
|
|||
extern int external_rejected __attribute__((loader_uninitialized));
|
||||
// expected-error@-1 {{variable 'external_rejected' cannot be declared both 'extern' and with the 'loader_uninitialized' attribute}}
|
||||
|
||||
struct S;
|
||||
extern S incomplete_external_rejected __attribute__((loader_uninitialized));
|
||||
// expected-error@-1 {{variable 'incomplete_external_rejected' cannot be declared both 'extern' and with the 'loader_uninitialized' attribute}}
|
||||
|
||||
int noargs __attribute__((loader_uninitialized(0)));
|
||||
// expected-error@-1 {{'loader_uninitialized' attribute takes no arguments}}
|
||||
|
||||
|
@ -58,3 +62,12 @@ struct nontrivial
|
|||
|
||||
nontrivial needs_trivial_ctor __attribute__((loader_uninitialized));
|
||||
// expected-error@-1 {{variable with 'loader_uninitialized' attribute must have a trivial default constructor}}
|
||||
|
||||
struct Incomplete;
|
||||
Incomplete incomplete __attribute__((loader_uninitialized));
|
||||
// expected-error@-1 {{variable has incomplete type 'Incomplete'}}
|
||||
// expected-note@-3 {{forward declaration of 'Incomplete'}}
|
||||
|
||||
struct Incomplete s_incomplete __attribute__((loader_uninitialized));
|
||||
// expected-error@-1 {{variable has incomplete type 'struct Incomplete'}}
|
||||
// expected-note@-7 {{forward declaration of 'Incomplete'}}
|
||||
|
|
Loading…
Reference in New Issue