[Sema][SVE] Reject arrays of sizeless types

The SVE ACLE doesn't allow arrays of sizeless types.  At the moment
clang accepts the TU:

  __SVInt8_t x[2];

but trying to code-generate it triggers the LLVM assertion:

  llvm/lib/IR/Type.cpp:588: static llvm::ArrayType* llvm::ArrayType::get(llvm::Type*, uint64_t): Assertion `isValidElementType(ElementType) && "Invalid type for array element!"' failed.

This patch reports an appropriate error instead.

The rules are slightly more restrictive than for general incomplete types.
For example:

  struct s;
  typedef struct s arr[2];

is valid as far as it goes, whereas arrays of sizeless types are
invalid in all contexts.  BuildArrayType therefore needs a specific
check for isSizelessType in addition to the usual handling of
incomplete types.

Differential Revision: https://reviews.llvm.org/D76082
This commit is contained in:
Richard Sandiford 2020-02-27 10:25:31 +00:00
parent 8c5c60a493
commit 994c071a1b
6 changed files with 42 additions and 12 deletions

View File

@ -5895,8 +5895,8 @@ def err_flexible_array_init_needs_braces : Error<
"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<

View File

@ -12385,9 +12385,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
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

View File

@ -6175,10 +6175,10 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
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)

View File

@ -2214,7 +2214,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
}
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 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
} 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;

View File

@ -51,6 +51,8 @@ void unused() {
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 @@ void func(int sel) {
_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'}}

View File

@ -61,6 +61,8 @@ void unused() {
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 @@ void func(int sel) {
_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 @@ struct s_ptr_template {
T *y;
};
template <typename T>
struct s_array_template {
T y[1]; // expected-error {{array has sizeless element type}}
};
struct widget {
widget(s_ptr_template<int>);
svint8_t operator[](int);
@ -330,6 +340,13 @@ template <typename T>
void template_fn_rvalue_ref(T &&) {}
#endif
#if __cplusplus >= 201103L
template <typename T>
using array_alias = T[1]; // expected-error {{array has sizeless element type '__SVInt8_t'}}
extern array_alias<int> *array_alias_int_ptr;
extern array_alias<svint8_t> *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 @@ void cxx_only(int sel) {
widget w(1);
local_int8 = w[1];
s_array_template<int> st_array_int;
s_array_template<svint8_t> st_array_svint8; // expected-note {{in instantiation}}
local_int8 = static_cast<svint8_t>(wrapper<svint8_t>());
local_int16 = static_cast<svint8_t>(wrapper<svint8_t>()); // expected-error {{assigning to 'svint16_t' (aka '__SVInt16_t') from incompatible type 'svint8_t'}}