forked from OSchip/llvm-project
[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:
parent
8c5c60a493
commit
994c071a1b
|
@ -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<
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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'}}
|
||||
|
|
|
@ -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'}}
|
||||
|
||||
|
|
Loading…
Reference in New Issue