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 @@ -5895,8 +5895,8 @@ "flexible array requires brace-enclosed initializer">; def err_illegal_decl_array_of_functions : Error< "'%0' declared as array of functions of type %1">; -def err_illegal_decl_array_incomplete_type : Error< - "array has incomplete element type %0">; +def err_array_incomplete_or_sizeless_type : Error< + "array has %select{incomplete|sizeless}0 element type %1">; def err_illegal_message_expr_incomplete_type : Error< "Objective-C message has incomplete result type %0">; def err_illegal_decl_array_of_references : Error< 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 @@ -12385,9 +12385,9 @@ if (!Var->isInvalidDecl()) { if (const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(Type)) { - if (RequireCompleteType(Var->getLocation(), - ArrayT->getElementType(), - diag::err_illegal_decl_array_incomplete_type)) + if (RequireCompleteSizedType( + Var->getLocation(), ArrayT->getElementType(), + diag::err_array_incomplete_or_sizeless_type)) Var->setInvalidDecl(); } else if (Var->getStorageClass() == SC_Static) { // C99 6.9.2p3: If the declaration of an identifier for an object is diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6175,10 +6175,10 @@ QualType literalType = TInfo->getType(); if (literalType->isArrayType()) { - if (RequireCompleteType(LParenLoc, Context.getBaseElementType(literalType), - diag::err_illegal_decl_array_incomplete_type, - SourceRange(LParenLoc, - LiteralExpr->getSourceRange().getEnd()))) + if (RequireCompleteSizedType( + LParenLoc, Context.getBaseElementType(literalType), + diag::err_array_incomplete_or_sizeless_type, + SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd()))) return ExprError(); if (literalType->isVariableArrayType()) return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2214,7 +2214,7 @@ } if (T->isVoidType() || T->isIncompleteArrayType()) { - Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T; + Diag(Loc, diag::err_array_incomplete_or_sizeless_type) << 0 << T; return QualType(); } @@ -2232,11 +2232,16 @@ } else { // C99 6.7.5.2p1: If the element type is an incomplete or function type, // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]()) - if (RequireCompleteType(Loc, T, - diag::err_illegal_decl_array_incomplete_type)) + if (RequireCompleteSizedType(Loc, T, + diag::err_array_incomplete_or_sizeless_type)) return QualType(); } + if (T->isSizelessType()) { + Diag(Loc, diag::err_array_incomplete_or_sizeless_type) << 1 << T; + return QualType(); + } + if (T->isFunctionType()) { Diag(Loc, diag::err_illegal_decl_array_of_functions) << getPrintableNameForEntity(Entity) << T; 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 @@ -51,6 +51,8 @@ struct incomplete_struct *incomplete_ptr; +typedef svint8_t sizeless_array[1]; // expected-error {{array has sizeless element type}} + void func(int sel) { static svint8_t static_int8; // expected-error {{non-local variable with sizeless type 'svint8_t'}} @@ -93,6 +95,9 @@ _Atomic svint8_t atomic_int8; // expected-error {{_Atomic cannot be applied to sizeless type 'svint8_t'}} __restrict svint8_t restrict_int8; // expected-error {{requires a pointer or reference}} + svint8_t array_int8[1]; // expected-error {{array has sizeless element type}} + svint8_t array_int8_init[] = {}; // expected-error {{array has sizeless element type}} + _Bool test_int8 = init_int8; // expected-error {{initializing '_Bool' with an expression of incompatible type 'svint8_t'}} int int_int8 = init_int8; // expected-error {{initializing 'int' with an expression of incompatible type 'svint8_t'}} 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 @@ -61,6 +61,8 @@ struct incomplete_struct *incomplete_ptr; +typedef svint8_t sizeless_array[1]; // expected-error {{array has sizeless element type}} + void func(int sel) { static svint8_t static_int8; // expected-error {{non-local variable with sizeless type 'svint8_t'}} @@ -107,6 +109,9 @@ _Atomic svint8_t atomic_int8; // expected-error {{_Atomic cannot be applied to sizeless type 'svint8_t'}} __restrict svint8_t restrict_int8; // expected-error {{requires a pointer or reference}} + svint8_t array_int8[1]; // expected-error {{array has sizeless element type}} + svint8_t array_int8_init[] = {}; // expected-error {{array has sizeless element type}} + bool test_int8 = init_int8; // expected-error {{cannot initialize a variable of type 'bool' with an lvalue of type 'svint8_t'}} int int_int8 = init_int8; // expected-error {{cannot initialize a variable of type 'int' with an lvalue of type 'svint8_t'}} @@ -283,6 +288,11 @@ T *y; }; +template +struct s_array_template { + T y[1]; // expected-error {{array has sizeless element type}} +}; + struct widget { widget(s_ptr_template); svint8_t operator[](int); @@ -330,6 +340,13 @@ void template_fn_rvalue_ref(T &&) {} #endif +#if __cplusplus >= 201103L +template +using array_alias = T[1]; // expected-error {{array has sizeless element type '__SVInt8_t'}} +extern array_alias *array_alias_int_ptr; +extern array_alias *array_alias_int8_ptr; // expected-note {{in instantiation of template type alias 'array_alias' requested here}} +#endif + void cxx_only(int sel) { svint8_t local_int8; svint16_t local_int16; @@ -372,6 +389,9 @@ widget w(1); local_int8 = w[1]; + s_array_template st_array_int; + s_array_template st_array_svint8; // expected-note {{in instantiation}} + local_int8 = static_cast(wrapper()); local_int16 = static_cast(wrapper()); // expected-error {{assigning to 'svint16_t' (aka '__SVInt16_t') from incompatible type 'svint8_t'}}