forked from OSchip/llvm-project
Check for improper use of 'static' and type qualifiers in array
declarators. They are only allowed for function parameters, and then only on the outermost array type derivation. llvm-svn: 161934
This commit is contained in:
parent
5717f4c1eb
commit
420052640f
|
@ -3677,6 +3677,10 @@ def err_illegal_decl_array_of_references : Error<
|
|||
"'%0' declared as array of references of type %1">;
|
||||
def err_decl_negative_array_size : Error<
|
||||
"'%0' declared as an array with a negative size">;
|
||||
def err_array_static_outside_prototype : Error<
|
||||
"%0 used in array declarator outside of function prototype">;
|
||||
def err_array_static_not_outermost : Error<
|
||||
"%0 used in non-outermost array type derivation">;
|
||||
def err_array_star_outside_prototype : Error<
|
||||
"star modifier used outside of function prototype">;
|
||||
def err_illegal_decl_pointer_to_reference : Error<
|
||||
|
|
|
@ -2258,6 +2258,50 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
ASM = ArrayType::Normal;
|
||||
D.setInvalidType(true);
|
||||
}
|
||||
|
||||
// C99 6.7.5.2p1: The optional type qualifiers and the keyword static
|
||||
// shall appear only in a declaration of a function parameter with an
|
||||
// array type, ...
|
||||
if (ASM == ArrayType::Static || ATI.TypeQuals) {
|
||||
if (!D.isPrototypeContext()) {
|
||||
S.Diag(DeclType.Loc, diag::err_array_static_outside_prototype) <<
|
||||
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
|
||||
// Remove the 'static' and the type qualifiers.
|
||||
if (ASM == ArrayType::Static)
|
||||
ASM = ArrayType::Normal;
|
||||
ATI.TypeQuals = 0;
|
||||
D.setInvalidType(true);
|
||||
}
|
||||
|
||||
// C99 6.7.5.2p1: ... and then only in the outermost array type
|
||||
// derivation.
|
||||
unsigned x = chunkIndex;
|
||||
while (x != 0) {
|
||||
// Walk outwards along the declarator chunks.
|
||||
x--;
|
||||
const DeclaratorChunk &DC = D.getTypeObject(x);
|
||||
switch (DC.Kind) {
|
||||
case DeclaratorChunk::Paren:
|
||||
continue;
|
||||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::Pointer:
|
||||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
S.Diag(DeclType.Loc, diag::err_array_static_not_outermost) <<
|
||||
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
|
||||
if (ASM == ArrayType::Static)
|
||||
ASM = ArrayType::Normal;
|
||||
ATI.TypeQuals = 0;
|
||||
D.setInvalidType(true);
|
||||
break;
|
||||
case DeclaratorChunk::Function:
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
// These are invalid anyway, so just ignore.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
|
||||
SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
|
||||
break;
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
|
||||
|
||||
void cat0(int a[static 0]) {} // expected-warning {{'static' has no effect on zero-length arrays}}
|
||||
|
||||
void cat(int a[static 3]) {} // expected-note 2 {{callee declares array parameter as static here}}
|
||||
|
||||
typedef int i3[static 3];
|
||||
void tcat(i3 a) {}
|
||||
|
||||
void vat(int i, int a[static i]) {} // expected-note {{callee declares array parameter as static here}}
|
||||
|
||||
void f(int *p) {
|
||||
|
@ -20,12 +17,37 @@ void f(int *p) {
|
|||
cat(c);
|
||||
cat(p);
|
||||
|
||||
tcat(0); // expected-warning {{null passed to a callee which requires a non-null argument}}
|
||||
tcat(a); // expected-warning {{array argument is too small; contains 2 elements, callee requires at least 3}}
|
||||
tcat(b);
|
||||
tcat(c);
|
||||
tcat(p);
|
||||
|
||||
vat(1, 0); // expected-warning {{null passed to a callee which requires a non-null argument}}
|
||||
vat(3, b);
|
||||
}
|
||||
|
||||
|
||||
typedef int td[static 3]; // expected-error {{'static' used in array declarator outside of function prototype}}
|
||||
typedef void(*fp)(int[static 42]); // no-warning
|
||||
|
||||
void g(void) {
|
||||
int a[static 42]; // expected-error {{'static' used in array declarator outside of function prototype}}
|
||||
|
||||
int b[const 10]; // expected-error {{type qualifier used in array declarator outside of function prototype}}
|
||||
int c[volatile 10]; // expected-error {{type qualifier used in array declarator outside of function prototype}}
|
||||
int d[restrict 10]; // expected-error {{type qualifier used in array declarator outside of function prototype}}
|
||||
|
||||
int e[static restrict 1]; // expected-error {{'static' used in array declarator outside of function prototype}}
|
||||
}
|
||||
|
||||
void h(int [static const 10][42]); // no-warning
|
||||
|
||||
void i(int [10]
|
||||
[static 42]); // expected-error {{'static' used in non-outermost array type derivation}}
|
||||
|
||||
void j(int [10]
|
||||
[const 42]); // expected-error {{type qualifier used in non-outermost array type derivation}}
|
||||
|
||||
void k(int (*x)[static 10]); // expected-error {{'static' used in non-outermost array type derivation}}
|
||||
void l(int (x)[static 10]); // no-warning
|
||||
void m(int *x[static 10]); // no-warning
|
||||
void n(int *(x)[static 10]); // no-warning
|
||||
|
||||
void o(int (x[static 10])(void)); // expected-error{{'x' declared as array of functions of type 'int (void)'}}
|
||||
void p(int (^x)[static 10]); // expected-error{{block pointer to non-function type is invalid}}
|
||||
void q(int (^x[static 10])()); // no-warning
|
||||
|
|
Loading…
Reference in New Issue