]> granicus.if.org Git - clang/commitdiff
Improve VLA diagnostics/sema checking. Fixes PR2361 and PR2352.
authorAnders Carlsson <andersca@mac.com>
Sun, 7 Dec 2008 00:20:55 +0000 (00:20 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 7 Dec 2008 00:20:55 +0000 (00:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60638 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticKinds.def
lib/Sema/SemaDecl.cpp
test/Parser/builtin_classify_type.c
test/Sema/array-constraint.c
test/Sema/typedef-variable-type.c
test/Sema/vla.c

index ac204b17935e9d2d16927b196bb12bfc676f4f58..63bf48c75777b0f530ee6efc29b2ae8d43a14f82 100644 (file)
@@ -998,8 +998,16 @@ DIAG(warn_enum_too_large, WARNING,
      "enumeration values exceed range of largest integer")
 DIAG(warn_illegal_constant_array_size, EXTENSION,
      "size of static array must be an integer constant expression")
-DIAG(err_typecheck_illegal_vla, ERROR,
-     "arrays with static storage duration must have constant integer length")
+DIAG(err_vla_decl_in_file_scope, ERROR,
+     "variable length array declaration not allowed in file scope")
+DIAG(err_vla_decl_has_static_storage, ERROR,
+     "variable length array declaration can not have 'static' storage duration")
+DIAG(err_vla_decl_has_extern_linkage, ERROR,
+     "variable length array declaration can not have 'extern' linkage")
+DIAG(err_vm_decl_in_file_scope, ERROR,
+     "variably modified type declaration not allowed in file scope")
+DIAG(err_vm_decl_has_extern_linkage, ERROR,
+     "variably modified type declaration can not have 'extern' linkage")
 DIAG(err_typecheck_field_variable_size, ERROR,
      "fields must have a constant size")
 DIAG(err_typecheck_negative_array_size, ERROR,
@@ -1157,6 +1165,8 @@ DIAG(err_typecheck_incomplete_tag, ERROR,
      "incomplete definition of type %0")
 DIAG(err_typecheck_no_member, ERROR,
      "no member named %0")
+DIAG(err_typecheck_ivar_variable_size, ERROR,
+     "instance variables must have a constant size")
 // FIXME: Improve with %select
 DIAG(err_typecheck_illegal_increment_decrement, ERROR,
      "cannot modify value of type %0")
index 0738f55ff2bd5224876f1d96845ba2888cdd71f4..4d01a2d52c6628cc158f2b921132c592d16127c9 100644 (file)
@@ -906,8 +906,11 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
       // C99 6.7.7p2: If a typedef name specifies a variably modified type
       // then it shall have block scope.
       if (NewTD->getUnderlyingType()->isVariablyModifiedType()) {
-        // FIXME: Diagnostic needs to be fixed.
-        Diag(D.getIdentifierLoc(), diag::err_typecheck_illegal_vla);
+        if (NewTD->getUnderlyingType()->isVariableArrayType())
+          Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope);
+        else
+          Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope);
+
         InvalidDecl = true;
       }
     }
@@ -1924,15 +1927,33 @@ Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
       continue;
     QualType T = IDecl->getType();
     
-    // C99 6.7.5.2p2: If an identifier is declared to be an object with 
-    // static storage duration, it shall not have a variable length array.
-    if ((IDecl->isFileVarDecl() || IDecl->isBlockVarDecl()) && 
-        IDecl->getStorageClass() == VarDecl::Static) {
-      if (T->isVariableArrayType()) {
-        Diag(IDecl->getLocation(), diag::err_typecheck_illegal_vla);
+    if (T->isVariableArrayType()) {
+      if (IDecl->isFileVarDecl()) {
+        Diag(IDecl->getLocation(), diag::err_vla_decl_in_file_scope);
         IDecl->setInvalidDecl();
+      } else {
+        // C99 6.7.5.2p2: If an identifier is declared to be an object with 
+        // static storage duration, it shall not have a variable length array.
+        if (IDecl->getStorageClass() == VarDecl::Static) {
+          Diag(IDecl->getLocation(), diag::err_vla_decl_has_static_storage);
+          IDecl->setInvalidDecl();
+        } else if (IDecl->getStorageClass() == VarDecl::Extern) {
+          Diag(IDecl->getLocation(), diag::err_vla_decl_has_extern_linkage);
+          IDecl->setInvalidDecl();
+        }
+      }
+    } else if (T->isVariablyModifiedType()) {
+      if (IDecl->isFileVarDecl()) {
+        Diag(IDecl->getLocation(), diag::err_vm_decl_in_file_scope);
+        IDecl->setInvalidDecl();
+      } else {
+        if (IDecl->getStorageClass() == VarDecl::Extern) {
+          Diag(IDecl->getLocation(), diag::err_vm_decl_has_extern_linkage);
+          IDecl->setInvalidDecl();
+        }
       }
     }
+     
     // Block scope. C99 6.7p7: If an identifier for an object is declared with
     // no linkage (C99 6.2.2p6), the type for the object shall be complete...
     if (IDecl->isBlockVarDecl() && 
@@ -2735,8 +2756,7 @@ Sema::DeclTy *Sema::ActOnIvar(Scope *S,
   // C99 6.7.2.1p8: A member of a structure or union may have any type other
   // than a variably modified type.
   if (T->isVariablyModifiedType()) {
-    // FIXME: This diagnostic needs work
-    Diag(Loc, diag::err_typecheck_illegal_vla) << SourceRange(Loc);
+    Diag(Loc, diag::err_typecheck_ivar_variable_size);
     InvalidDecl = true;
   }
   
index 7cf3d5cd922d3e93d3be8130be2dc50d276ebbd3..0a46f33b71d956904af5b9c5b264daef782b659a 100644 (file)
@@ -9,8 +9,8 @@ int main() {
   struct foo s;
 
   static int ary[__builtin_classify_type(a)];
-  static int ary2[(__builtin_classify_type)(a)]; // expected-error{{arrays with static storage duration must have constant integer length}}
-  static int ary3[(*__builtin_classify_type)(a)]; // expected-error{{arrays with static storage duration must have constant integer length}}
+  static int ary2[(__builtin_classify_type)(a)]; // expected-error{{variable length array declaration can not have 'static' storage duration}}
+  static int ary3[(*__builtin_classify_type)(a)]; // expected-error{{variable length array declaration can not have 'static' storage duration}}
 
   int result;
 
index 8fa216d46a1bbd13f530ac2ba582c1711601bf26..7763e7923d18a2eb5c31a7d43bb5c704ff3c33f6 100644 (file)
@@ -41,7 +41,7 @@ void check_size() {
 }
 
 static int I;
-typedef int TA[I]; // expected-error {{arrays with static storage duration must have constant integer length}}
+typedef int TA[I]; // expected-error {{variable length array declaration not allowed in file scope}}
 
 void strFunc(char *);
 const char staticAry[] = "test";
index 4ced92626433be71f952f3057dcd59bb992c1e90..346117ef18a2628589a968b682ea3e72afc387ce 100644 (file)
@@ -1,3 +1,3 @@
 // RUN: clang %s -verify -fsyntax-only -pedantic
 
-typedef int (*a)[!.0]; // expected-error{{arrays with static storage duration must have constant integer length}}
+typedef int (*a)[!.0]; // expected-error{{variably modified type declaration not allowed in file scope}}
index 682d2fb2667fdff96b08d21a577bf916a53d7bf8..bccd5e65669e9901b6877c57ccc7894e121d5e60 100644 (file)
@@ -16,3 +16,28 @@ void f (unsigned int m)
 // PR3048
 int x = sizeof(struct{char qq[x];}); // expected-error {{fields must have a constant size}}
 
+// PR2352
+void f2(unsigned int m)
+{
+  extern int e[2][m]; // expected-error {{variable length array declaration can not have 'extern' linkage}}
+
+  e[0][0] = 0;
+  
+}
+
+// PR2361
+int i; 
+int c[][i]; // expected-error {{variably modified type declaration not allowed in file scope}}
+int d[i]; // expected-error {{variable length array declaration not allowed in file scope}}
+
+int (*e)[i]; // expected-error {{variably modified type declaration not allowed in file scope}}
+
+void f3()
+{
+  static int a[i]; // expected-error {{variable length array declaration can not have 'static' storage duration}}
+  extern int b[i]; // expected-error {{variable length array declaration can not have 'extern' linkage}}
+
+  extern int (*c)[i]; // expected-error {{variably modified type declaration can not have 'extern' linkage}}
+  static int (*d)[i];
+}
+