aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Sema/SemaDecl.cpp43
-rw-r--r--Sema/SemaType.cpp24
-rw-r--r--include/clang/Basic/DiagnosticKinds.def2
-rw-r--r--test/Sema/array-constraint.c8
4 files changed, 34 insertions, 43 deletions
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index f1a6e78b6a..cc0682a8da 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -25,59 +25,22 @@
#include "llvm/ADT/SmallSet.h"
using namespace clang;
-// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
-// a constant expression of type int with a value greater than zero.
+// C99 6.7.2.1p8: Used by ParseDeclarator/ParseField to make sure we have
+// a constant expression. We return true if we don't have a ConstantArrayType.
bool Sema::VerifyConstantArrayType(const ArrayType *Array,
SourceLocation DeclLoc) {
if (const VariableArrayType *VLA = dyn_cast<VariableArrayType>(Array)) {
Expr *Size = VLA->getSizeExpr();
- if (Size == 0)
- return false; // incomplete type.
-
- if (!Size->getType()->isIntegerType()) {
- Diag(Size->getLocStart(), diag::err_array_size_non_int,
- Size->getType().getAsString(), Size->getSourceRange());
- return false;
- }
- // FIXME: I don't think this is needed. It remains to keep test
- // builtin_classify_type() happy...will revisit soon (today is 8/29/07:-)
- SourceLocation Loc;
- llvm::APSInt SizeVal(32);
- if (!Size->isIntegerConstantExpr(SizeVal, Context, &Loc)) {
+ if (Size) {
// FIXME: This emits the diagnostic to enforce 6.7.2.1p8, but the message
// is wrong. It is also wrong for static variables.
// FIXME: This is also wrong for:
// int sub1(int i, char *pi) { typedef int foo[i];
// struct bar {foo f1; int f2:3; int f3:4} *p; }
Diag(DeclLoc, diag::err_typecheck_illegal_vla, Size->getSourceRange());
- return false;
}
return true;
}
- const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Array);
-
- assert(CAT && "Sema::VerifyConstantArrayType(): Illegal array type");
-
- llvm::APSInt SizeVal(32);
- SizeVal = CAT->getSize();
-
- // We have a constant expression with an integer type, now make sure
- // value greater than zero (C99 6.7.5.2p1).
-
- // FIXME: This check isn't specific to static VLAs, this should be moved
- // elsewhere or replicated. 'int X[-1];' inside a function should emit an
- // error.
- if (SizeVal.isSigned()) {
- llvm::APSInt Zero(SizeVal.getBitWidth());
- Zero.setIsUnsigned(false);
- if (SizeVal < Zero) {
- Diag(DeclLoc, diag::err_typecheck_negative_array_size);
- return true;
- } else if (SizeVal == 0) {
- // GCC accepts zero sized static arrays.
- Diag(DeclLoc, diag::err_typecheck_zero_array_size);
- }
- }
return false;
}
diff --git a/Sema/SemaType.cpp b/Sema/SemaType.cpp
index d1d62a6ea2..17b34628b5 100644
--- a/Sema/SemaType.cpp
+++ b/Sema/SemaType.cpp
@@ -202,13 +202,33 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
D.setInvalidType(true);
}
}
+ // C99 6.7.5.2p1: The size expression shall have integer type.
+ if (ArraySize && !ArraySize->getType()->isIntegerType()) {
+ Diag(ArraySize->getLocStart(), diag::err_array_size_non_int,
+ ArraySize->getType().getAsString(), ArraySize->getSourceRange());
+ D.setInvalidType(true);
+ }
llvm::APSInt ConstVal(32);
// If no expression was provided, we consider it a VLA.
if (!ArraySize || !ArraySize->isIntegerConstantExpr(ConstVal, Context))
T = Context.getVariableArrayType(T, ArraySize, ASM, ATI.TypeQuals);
- else
+ else {
+ // C99 6.7.5.2p1: If the expression is a constant expression, it shall
+ // have a value greater than zero.
+ if (ConstVal.isSigned()) {
+ if (ConstVal.isNegative()) {
+ Diag(ArraySize->getLocStart(),
+ diag::err_typecheck_negative_array_size,
+ ArraySize->getSourceRange());
+ D.setInvalidType(true);
+ } else if (ConstVal == 0) {
+ // GCC accepts zero sized static arrays.
+ Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size,
+ ArraySize->getSourceRange());
+ }
+ }
T = Context.getConstantArrayType(T, ConstVal, ASM, ATI.TypeQuals);
-
+ }
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
if (!getLangOptions().C99 &&
(ASM != ArrayType::Normal ||
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index dbfa1e6f9e..9eaf4d4061 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -534,7 +534,7 @@ DIAG(err_typecheck_illegal_vla, ERROR,
"variable length array declared outside of any function")
DIAG(err_typecheck_negative_array_size, ERROR,
"array size is negative")
-DIAG(err_typecheck_zero_array_size, EXTENSION,
+DIAG(ext_typecheck_zero_array_size, EXTENSION,
"zero size arrays are an extension")
DIAG(err_array_size_non_int, ERROR,
"size of array has non-integer type '%0'")
diff --git a/test/Sema/array-constraint.c b/test/Sema/array-constraint.c
index 4d1c2f1600..1ca3cd7aec 100644
--- a/test/Sema/array-constraint.c
+++ b/test/Sema/array-constraint.c
@@ -31,3 +31,11 @@ typedef int (*pfunc)(void);
pfunc xx(int f[](void)) { // expected-error {{'f' declared as array of functions}}
return f;
}
+
+void check_size() {
+ float f;
+ int size_not_int[f]; // expected-error {{size of array has non-integer type 'float'}}
+ int negative_size[1-2]; // expected-error{{array size is negative}}
+ int zero_size[0]; // expected-warning{{zero size arrays are an extension}}
+}
+