diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5599,7 +5599,8 @@ def err_func_returning_array_function : Error< "function cannot return %select{array|function}0 type %1">; def err_field_declared_as_function : Error<"field %0 declared as a function">; -def err_field_incomplete : Error<"field has incomplete type %0">; +def err_field_incomplete_or_sizeless : Error< + "field has %select{incomplete|sizeless}0 type %1">; def ext_variable_sized_type_in_struct : ExtWarn< "field %0 with variable sized type %1 not at the end of a struct or class is" " a GNU extension">, InGroup; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5247,8 +5247,8 @@ Chain.push_back(Anon); RecordDecl *RecordDef = Record->getDefinition(); - if (RequireCompleteType(Anon->getLocation(), RecTy, - diag::err_field_incomplete) || + if (RequireCompleteSizedType(Anon->getLocation(), RecTy, + diag::err_field_incomplete_or_sizeless) || InjectAnonymousStructOrUnionMembers(*this, S, CurContext, RecordDef, AS_none, Chain)) { Anon->setInvalidDecl(); @@ -16142,8 +16142,9 @@ // C99 6.7.2.1p4 - verify the field type. // C++ 9.6p3: A bit-field shall have integral or enumeration type. if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) { - // Handle incomplete types with specific error. - if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) + // Handle incomplete and sizeless types with a specific error. + if (RequireCompleteSizedType(FieldLoc, FieldTy, + diag::err_field_incomplete_or_sizeless)) return ExprError(); if (FieldName) return Diag(FieldLoc, diag::err_not_integral_type_bitfield) @@ -16360,7 +16361,8 @@ QualType EltTy = Context.getBaseElementType(T); if (!EltTy->isDependentType()) { - if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { + if (RequireCompleteSizedType(Loc, EltTy, + diag::err_field_incomplete_or_sizeless)) { // Fields of incomplete type force their record to be invalid. Record->setInvalidDecl(); InvalidDecl = true; @@ -16904,8 +16906,9 @@ // elsewhere, after synthesized ivars are known. } } else if (!FDTy->isDependentType() && - RequireCompleteType(FD->getLocation(), FD->getType(), - diag::err_field_incomplete)) { + RequireCompleteSizedType( + FD->getLocation(), FD->getType(), + diag::err_field_incomplete_or_sizeless)) { // Incomplete type FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); @@ -16963,8 +16966,8 @@ Context, "", UnavailableAttr::IR_ARCFieldWithOwnership, FD->getLocation())); } else if (getLangOpts().ObjC && - getLangOpts().getGC() != LangOptions::NonGC && - Record && !Record->hasObjectMember()) { + getLangOpts().getGC() != LangOptions::NonGC && Record && + !Record->hasObjectMember()) { if (FD->getType()->isObjCObjectPointerType() || FD->getType().isObjCGCStrong()) Record->setHasObjectMember(true); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1629,7 +1629,8 @@ // If the variable being captured has an invalid type, mark the class as // invalid as well. if (!FieldType->isDependentType()) { - if (RequireCompleteType(Loc, FieldType, diag::err_field_incomplete)) { + if (RequireCompleteSizedType(Loc, FieldType, + diag::err_field_incomplete_or_sizeless)) { RD->setInvalidDecl(); Field->setInvalidDecl(); } else { diff --git a/clang/test/Sema/sizeless-1.c b/clang/test/Sema/sizeless-1.c --- a/clang/test/Sema/sizeless-1.c +++ b/clang/test/Sema/sizeless-1.c @@ -230,6 +230,20 @@ return count; } +struct sized_struct { + int f1; + svint8_t f2; // expected-error {{field has sizeless type 'svint8_t'}} + svint8_t f3 : 2; // expected-error {{field has sizeless type 'svint8_t'}} + svint8_t : 3; // expected-error {{field has sizeless type 'svint8_t'}} +}; + +union sized_union { + int f1; + svint8_t f2; // expected-error {{field has sizeless type 'svint8_t'}} + svint8_t f3 : 2; // expected-error {{field has sizeless type 'svint8_t'}} + svint8_t : 3; // expected-error {{field has sizeless type 'svint8_t'}} +}; + #if __STDC_VERSION__ >= 201112L void test_generic(void) { svint8_t local_int8; diff --git a/clang/test/SemaCXX/sizeless-1.cpp b/clang/test/SemaCXX/sizeless-1.cpp --- a/clang/test/SemaCXX/sizeless-1.cpp +++ b/clang/test/SemaCXX/sizeless-1.cpp @@ -249,6 +249,20 @@ return count; } +struct sized_struct { + int f1; + svint8_t f2; // expected-error {{field has sizeless type 'svint8_t'}} + svint8_t f3 : 2; // expected-error {{field has sizeless type 'svint8_t'}} + svint8_t : 3; // expected-error {{field has sizeless type 'svint8_t'}} +}; + +union sized_union { + int f1; + svint8_t f2; // expected-error {{field has sizeless type 'svint8_t'}} + svint8_t f3 : 2; // expected-error {{field has sizeless type 'svint8_t'}} + svint8_t : 3; // expected-error {{field has sizeless type 'svint8_t'}} +}; + void pass_int8_ref(svint8_t &); // expected-note {{not viable}} svint8_t &return_int8_ref(); @@ -256,6 +270,11 @@ svint8_t &&return_int8_rvalue_ref(); #endif +template +struct s_template { + T y; // expected-error {{field has sizeless type '__SVInt8_t'}} +}; + template struct s_ptr_template { s_ptr_template(); @@ -344,6 +363,9 @@ local_int8 = svint8_t(); local_int8 = svint16_t(); // expected-error {{assigning to 'svint8_t' (aka '__SVInt8_t') from incompatible type 'svint16_t'}} + s_template st_int; + s_template st_svint8; // expected-note {{in instantiation}} + s_ptr_template st_ptr_int; s_ptr_template st_ptr_svint8; @@ -474,6 +496,9 @@ local_int8 = ([]() -> svint8_t { return svint8_t(); })(); auto fn1 = [&local_int8](svint8_t x) { local_int8 = x; }; auto fn2 = [&local_int8](svint8_t *ptr) { *ptr = local_int8; }; +#if __cplusplus >= 201703L + auto fn3 = [a(return_int8())] {}; // expected-error {{field has sizeless type '__SVInt8_t'}} +#endif for (auto x : local_int8) { // expected-error {{no viable 'begin' function available}} }