From: Jon Chesterfield Date: Wed, 19 Aug 2020 17:11:34 +0000 (+0100) Subject: [Clang] Fix BZ47169, loader_uninitialized on incomplete types X-Git-Tag: llvmorg-13-init~14271 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bcaa806a4747595116b538e8b75b12966e6607f6;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ab14963..566a2f9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12476,6 +12476,17 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { } if (!Var->isInvalidDecl() && RealDecl->hasAttr()) { + 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(); diff --git a/clang/test/CodeGenCXX/attr-loader-uninitialized.cpp b/clang/test/CodeGenCXX/attr-loader-uninitialized.cpp index e82ae47..6501a25 100644 --- a/clang/test/CodeGenCXX/attr-loader-uninitialized.cpp +++ b/clang/test/CodeGenCXX/attr-loader-uninitialized.cpp @@ -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 struct templ{T * t;}; + +// CHECK: @templ_int = global %struct.templ undef, align 8 +templ templ_int [[clang::loader_uninitialized]]; + +// CHECK: @templ_trivial = global %struct.templ.0 undef, align 8 +templ templ_trivial [[clang::loader_uninitialized]]; + +// CHECK: @templ_incomplete = global %struct.templ.1 undef, align 8 +struct incomplete; +templ templ_incomplete [[clang::loader_uninitialized]]; diff --git a/clang/test/Sema/attr-loader-uninitialized.c b/clang/test/Sema/attr-loader-uninitialized.c index f2e78d9..a1edd85 100644 --- a/clang/test/Sema/attr-loader-uninitialized.c +++ b/clang/test/Sema/attr-loader-uninitialized.c @@ -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'}} diff --git a/clang/test/Sema/attr-loader-uninitialized.cpp b/clang/test/Sema/attr-loader-uninitialized.cpp index 3a330b3..54b018f 100644 --- a/clang/test/Sema/attr-loader-uninitialized.cpp +++ b/clang/test/Sema/attr-loader-uninitialized.cpp @@ -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'}}