[cfe-commits] r39587 - in /cfe/cfe/trunk: AST/Expr.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/Basic/DiagnosticKinds.def
clattner at cs.uiuc.edu
clattner at cs.uiuc.edu
Wed Jul 11 09:45:58 PDT 2007
Author: clattner
Date: Wed Jul 11 11:45:58 2007
New Revision: 39587
URL: http://llvm.org/viewvc/llvm-project?rev=39587&view=rev
Log:
Rename Sema::isConstantArrayType -> VerifyConstantArrayType. Make sure to
check canonical types in a few places. Tighten up VerifyConstantArrayType
to diagnose more errors, now that we can evaluate i-c-e's. Add some fixmes
about poor diagnostics.
We now correctly typecheck this example:
void s(void) {
typedef int a[(int) +1.0];
static a b; // invalid, static VLA
static int c[(int) +1.0]; // invalid, static VLA
}
void t(void) {
typedef int a[(int)1.0];
static a b; // valid, constant size
}
void u() {
static int X[-1];
static int Y[0];
}
producing:
static-vla.c:3:12: error: variable length array declared outside of any function
static a b; // invalid, static VLA
^
static-vla.c:5:14: error: variable length array declared outside of any function
static int c[(int) +1.0]; // invalid, static VLA
^ ~~~~~~~~~~
static-vla.c:15:14: error: array size is negative
static int X[-1];
^ ~~
static-vla.c:16:14: warning: zero size arrays are an extension
static int Y[0];
^ ~
Modified:
cfe/cfe/trunk/AST/Expr.cpp
cfe/cfe/trunk/Sema/Sema.h
cfe/cfe/trunk/Sema/SemaDecl.cpp
cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
Modified: cfe/cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Expr.cpp?rev=39587&r1=39586&r2=39587&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/Expr.cpp (original)
+++ cfe/cfe/trunk/AST/Expr.cpp Wed Jul 11 11:45:58 2007
@@ -410,7 +410,7 @@
Result = (int)FL->getValue();
break;
}
- if (Loc) *Loc = getLocStart();
+ if (Loc) *Loc = Operand->getLocStart();
return false;
}
case ConditionalOperatorClass: {
Modified: cfe/cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.h?rev=39587&r1=39586&r2=39587&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:45:58 2007
@@ -331,9 +331,11 @@
QualType CheckSizeOfAlignOfOperand(QualType type, SourceLocation loc,
bool isSizeof);
- // 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.
- bool isConstantArrayType(ArrayType *ary, SourceLocation loc);
+ /// 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. If the
+ /// array has an incomplete type or a valid constant size, return false,
+ /// otherwise emit a diagnostic and return true.
+ bool VerifyConstantArrayType(const ArrayType *ary, SourceLocation loc);
};
Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39587&r1=39586&r2=39587&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:45:58 2007
@@ -30,23 +30,47 @@
// 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.
-bool Sema::isConstantArrayType(ArrayType *ary, SourceLocation loc) {
- if (Expr *size = ary->getSize()) {
- SourceLocation expLoc;
- if (!size->isIntegerConstantExpr(&expLoc)) {
- Diag(expLoc, diag::err_typecheck_illegal_vla);
- return false;
- }
- if (!size->getType()->isIntegerType()) {
- Diag(size->getLocStart(), diag::err_array_size_non_int,
- size->getType().getAsString());
- return false;
- }
- // We have a constant expression with an integer type, now make sure
- // value greater than zero (C99 6.7.5.2p1).
- // FIXME: evaluate constant expression.
+bool Sema::VerifyConstantArrayType(const ArrayType *Array,
+ SourceLocation DeclLoc) {
+ const Expr *Size = Array->getSize();
+ 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 true;
+ }
+
+ // Verify that the size of the array is an integer constant expr.
+ SourceLocation Loc;
+ APSInt SizeVal(32);
+ if (!Size->isIntegerConstantExpr(SizeVal, &Loc)) {
+ // FIXME: This emits the diagnostic to enforce 6.7.2.1p8, but the message
+ // is wrong. It is also wrong for static variables.
+ Diag(DeclLoc, diag::err_typecheck_illegal_vla, Size->getSourceRange());
+ return true;
+ }
+
+ // 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()) {
+ APSInt Zero(SizeVal.getBitWidth());
+ Zero.setIsUnsigned(false);
+ if (SizeVal < Zero) {
+ Diag(DeclLoc, diag::err_typecheck_negative_array_size,
+ Size->getSourceRange());
+ return true;
+ } else if (SizeVal == 0) {
+ // GCC accepts zero sized static arrays.
+ Diag(DeclLoc, diag::err_typecheck_zero_array_size,
+ Size->getSourceRange());
+ }
}
- return true;
+ return false;
}
Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
@@ -272,7 +296,7 @@
// C99 6.7.7p2: If a typedef name specifies a variably modified type
// then it shall have block scope.
if (ArrayType *ary = dyn_cast<ArrayType>(NewTD->getUnderlyingType())) {
- if (!isConstantArrayType(ary, D.getIdentifierLoc()))
+ if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
return 0;
}
}
@@ -340,8 +364,8 @@
}
// 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 (ArrayType *ary = dyn_cast<ArrayType>(R)) {
- if (!isConstantArrayType(ary, D.getIdentifierLoc()))
+ if (ArrayType *ary = dyn_cast<ArrayType>(R.getCanonicalType())) {
+ if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
return 0;
}
NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC);
@@ -358,8 +382,8 @@
if (SC == VarDecl::Static) {
// 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 (ArrayType *ary = dyn_cast<ArrayType>(R)) {
- if (!isConstantArrayType(ary, D.getIdentifierLoc()))
+ if (ArrayType *ary = dyn_cast<ArrayType>(R.getCanonicalType())) {
+ if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
return 0;
}
}
@@ -669,8 +693,8 @@
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
- if (ArrayType *ary = dyn_cast<ArrayType>(T)) {
- if (!isConstantArrayType(ary, Loc))
+ if (ArrayType *ary = dyn_cast<ArrayType>(T.getCanonicalType())) {
+ if (VerifyConstantArrayType(ary, Loc))
return 0;
}
return new FieldDecl(Loc, II, T);
@@ -807,6 +831,7 @@
}
SourceLocation expLoc;
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
+ // FIXME: Capture this value in the enumconstantdecl.
if (Val && !((Expr *)Val)->isIntegerConstantExpr(&expLoc)) {
Diag(expLoc, diag::err_enum_value_not_integer_constant_expr, Id->getName());
return 0;
Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39587&r1=39586&r2=39587&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:45:58 2007
@@ -469,6 +469,10 @@
"case label does not reduce to an integer constant")
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,
+ "zero size arrays are an extension")
DIAG(err_array_size_non_int, ERROR,
"size of array has non-integer type '%0'")
More information about the cfe-commits
mailing list