diff options
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 14 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 40 | ||||
-rw-r--r-- | test/Parser/builtin_classify_type.c | 4 | ||||
-rw-r--r-- | test/Sema/array-constraint.c | 2 | ||||
-rw-r--r-- | test/Sema/typedef-variable-type.c | 2 | ||||
-rw-r--r-- | test/Sema/vla.c | 25 |
6 files changed, 71 insertions, 16 deletions
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index ac204b1793..63bf48c757 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -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") diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0738f55ff2..4d01a2d52c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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; } diff --git a/test/Parser/builtin_classify_type.c b/test/Parser/builtin_classify_type.c index 7cf3d5cd92..0a46f33b71 100644 --- a/test/Parser/builtin_classify_type.c +++ b/test/Parser/builtin_classify_type.c @@ -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; diff --git a/test/Sema/array-constraint.c b/test/Sema/array-constraint.c index 8fa216d46a..7763e7923d 100644 --- a/test/Sema/array-constraint.c +++ b/test/Sema/array-constraint.c @@ -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"; diff --git a/test/Sema/typedef-variable-type.c b/test/Sema/typedef-variable-type.c index 4ced926264..346117ef18 100644 --- a/test/Sema/typedef-variable-type.c +++ b/test/Sema/typedef-variable-type.c @@ -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}} diff --git a/test/Sema/vla.c b/test/Sema/vla.c index 682d2fb266..bccd5e6566 100644 --- a/test/Sema/vla.c +++ b/test/Sema/vla.c @@ -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]; +} + |