aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2012-08-15 07:42:30 +0000
committerHans Wennborg <hans@hanshq.net>2012-08-15 07:42:30 +0000
commit7f397c5d97fc0c11333d939f2c07bc3b230956e2 (patch)
tree4e4bca2af66c7826049fe11f342a58b49de448a4
parentdece8b325821acaa5b91e97cf03baf610f264e01 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161934 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--lib/Sema/SemaType.cpp44
-rw-r--r--test/Sema/static-array.c42
3 files changed, 80 insertions, 10 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 6d7b52e55f..0fbe40f4f8 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index c45705813e..7b7cc99dff 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -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;
diff --git a/test/Sema/static-array.c b/test/Sema/static-array.c
index 2d4b968dec..be8957c254 100644
--- a/test/Sema/static-array.c
+++ b/test/Sema/static-array.c
@@ -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