[cfe-commits] r41674 - in /cfe/trunk: AST/Expr.cpp Sema/Sema.h Sema/SemaDecl.cpp Sema/SemaExpr.cpp include/clang/AST/Expr.h include/clang/Basic/DiagnosticKinds.def test/Sema/array-init.c
Steve Naroff
snaroff at apple.com
Sun Sep 2 13:30:18 PDT 2007
Author: snaroff
Date: Sun Sep 2 15:30:18 2007
New Revision: 41674
URL: http://llvm.org/viewvc/llvm-project?rev=41674&view=rev
Log:
More progress on array initializers.
- Added Expr::isConstantExpr().
- Added type checking for InitListExpr elements.
- Added diagnostic for trying to initialize a variable sized object.
Modified:
cfe/trunk/AST/Expr.cpp
cfe/trunk/Sema/Sema.h
cfe/trunk/Sema/SemaDecl.cpp
cfe/trunk/Sema/SemaExpr.cpp
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/test/Sema/array-init.c
Modified: cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Expr.cpp?rev=41674&r1=41673&r2=41674&view=diff
==============================================================================
--- cfe/trunk/AST/Expr.cpp (original)
+++ cfe/trunk/AST/Expr.cpp Sun Sep 2 15:30:18 2007
@@ -350,6 +350,120 @@
return MLV_Valid;
}
+bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
+
+ switch (getStmtClass()) {
+ default:
+ if (Loc) *Loc = getLocStart();
+ return false;
+ case ParenExprClass:
+ return cast<ParenExpr>(this)->getSubExpr()->isConstantExpr(Ctx, Loc);
+ case StringLiteralClass:
+ case FloatingLiteralClass:
+ case IntegerLiteralClass:
+ case CharacterLiteralClass:
+ case ImaginaryLiteralClass:
+ case TypesCompatibleExprClass:
+ break;
+ case CallExprClass: {
+ const CallExpr *CE = cast<CallExpr>(this);
+ llvm::APSInt Result(32);
+ Result.zextOrTrunc(Ctx.getTypeSize(getType(), CE->getLocStart()));
+ if (CE->isBuiltinClassifyType(Result))
+ break;
+ if (Loc) *Loc = getLocStart();
+ return false;
+ }
+ case DeclRefExprClass:
+ if (isa<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl()))
+ break;
+ if (Loc) *Loc = getLocStart();
+ return false;
+ case UnaryOperatorClass: {
+ const UnaryOperator *Exp = cast<UnaryOperator>(this);
+
+ // Get the operand value. If this is sizeof/alignof, do not evalute the
+ // operand. This affects C99 6.6p3.
+ if (!Exp->isSizeOfAlignOfOp() &&
+ !Exp->getSubExpr()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ switch (Exp->getOpcode()) {
+ // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
+ // See C99 6.6p3.
+ default:
+ if (Loc) *Loc = Exp->getOperatorLoc();
+ return false;
+ case UnaryOperator::Extension:
+ return true; // FIXME: this is wrong.
+ case UnaryOperator::SizeOf:
+ case UnaryOperator::AlignOf:
+ // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
+ if (!Exp->getSubExpr()->getType()->isConstantSizeType(Ctx, Loc))
+ return false;
+ break;
+ case UnaryOperator::LNot:
+ case UnaryOperator::Plus:
+ case UnaryOperator::Minus:
+ case UnaryOperator::Not:
+ break;
+ }
+ break;
+ }
+ case SizeOfAlignOfTypeExprClass: {
+ const SizeOfAlignOfTypeExpr *Exp = cast<SizeOfAlignOfTypeExpr>(this);
+ // alignof always evaluates to a constant.
+ if (Exp->isSizeOf() && !Exp->getArgumentType()->isConstantSizeType(Ctx,Loc))
+ return false;
+ break;
+ }
+ case BinaryOperatorClass: {
+ const BinaryOperator *Exp = cast<BinaryOperator>(this);
+
+ // The LHS of a constant expr is always evaluated and needed.
+ if (!Exp->getLHS()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ if (!Exp->getRHS()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ break;
+ }
+ case ImplicitCastExprClass:
+ case CastExprClass: {
+ const Expr *SubExpr;
+ SourceLocation CastLoc;
+ if (const CastExpr *C = dyn_cast<CastExpr>(this)) {
+ SubExpr = C->getSubExpr();
+ CastLoc = C->getLParenLoc();
+ } else {
+ SubExpr = cast<ImplicitCastExpr>(this)->getSubExpr();
+ CastLoc = getLocStart();
+ }
+ if (!SubExpr->isConstantExpr(Ctx, Loc)) {
+ if (Loc) *Loc = SubExpr->getLocStart();
+ return false;
+ }
+ break;
+ }
+ case ConditionalOperatorClass: {
+ const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
+
+ if (!Exp->getCond()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ if (!Exp->getLHS()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ if (!Exp->getRHS()->isConstantExpr(Ctx, Loc))
+ return false;
+ break;
+ }
+ }
+
+ return true;
+}
+
/// isIntegerConstantExpr - this recursive routine will test if an expression is
/// an integer constant expression. Note: With the introduction of VLA's in
/// C99 the result of the sizeof operator is no longer always a constant
Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=41674&r1=41673&r2=41674&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Sun Sep 2 15:30:18 2007
@@ -445,7 +445,7 @@
QualType CheckInitializer(Expr *simpleInit_or_initList, QualType declType,
bool isStatic);
bool CheckSingleInitializer(Expr *simpleInit, QualType declType);
- bool RequireConstantExprs(InitListExpr *IList);
+ bool CheckInitList(InitListExpr *IList, QualType DType, bool isStatic);
/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
/// the specified width and sign. If an overflow occurs, detect it and emit
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=41674&r1=41673&r2=41674&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Sun Sep 2 15:30:18 2007
@@ -289,19 +289,21 @@
return false;
}
-bool Sema::RequireConstantExprs(InitListExpr *IList) {
+bool Sema::CheckInitList(InitListExpr *IList, QualType DType, bool isStatic) {
bool hadError = false;
for (unsigned i = 0; i < IList->getNumInits(); i++) {
Expr *expr = IList->getInit(i);
if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr))
- RequireConstantExprs(InitList);
+ CheckInitList(InitList, DType, isStatic);
else {
SourceLocation loc;
- // FIXME: should be isConstantExpr()...
- if (!expr->isIntegerConstantExpr(Context, &loc)) {
+
+ if (isStatic && !expr->isConstantExpr(Context, &loc)) { // C99 6.7.8p4.
Diag(loc, diag::err_init_element_not_constant, expr->getSourceRange());
hadError = true;
+ } else if (CheckSingleInitializer(expr, DType)) {
+ hadError = true; // types didn't match.
}
}
}
@@ -316,10 +318,27 @@
// We have an InitListExpr, make sure we set the type.
Init->setType(DeclType);
- if (isStatic) // C99 6.7.8p4.
- RequireConstantExprs(InitList);
-
- // FIXME: Lot of checking still to do...
+ // C99 6.7.8p3: The type of the entity to be initialized shall be an array
+ // of unknown size ("[]") or an object type that is not a variable array type.
+ if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType()) {
+ Expr *expr = VAT->getSizeExpr();
+ if (expr) {
+ Diag(expr->getLocStart(), diag::err_variable_object_no_init,
+ expr->getSourceRange());
+ return QualType();
+ }
+ }
+ if (const ArrayType *Ary = DeclType->getAsArrayType()) {
+ // We have a ConstantArrayType or VariableArrayType with unknown size.
+ QualType ElmtType = Ary->getElementType();
+
+ // If we have a multi-dimensional array, navigate to the base type.
+ while ((Ary = ElmtType->getAsArrayType()))
+ ElmtType = Ary->getElementType();
+
+ CheckInitList(InitList, ElmtType, isStatic);
+ }
+ // FIXME: Handle struct/union types.
return DeclType;
}
Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=41674&r1=41673&r2=41674&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Sun Sep 2 15:30:18 2007
@@ -649,7 +649,9 @@
// doing the semantic analysis will likely be located elsewhere (i.e. in
// consumers of InitListExpr (e.g. ParseDeclarator, ParseCompoundLiteral).
- return new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc);
+ InitListExpr *e = new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc);
+ e->setType(Context.VoidTy); // FIXME: just a place holder for now.
+ return e;
}
Action::ExprResult Sema::
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=41674&r1=41673&r2=41674&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Sun Sep 2 15:30:18 2007
@@ -99,6 +99,8 @@
llvm::APSInt X(32);
return isIntegerConstantExpr(X, Ctx, Loc);
}
+ /// isConstantExpr - Return true if this expression is a valid constant expr.
+ bool isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const;
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExprConstant &&
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=41674&r1=41673&r2=41674&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sun Sep 2 15:30:18 2007
@@ -548,6 +548,8 @@
"'extern' variable cannot have an initializer")
DIAG(warn_extern_init, WARNING,
"'extern' variable has an initializer")
+DIAG(err_variable_object_no_init, ERROR,
+ "variable-sized object may not be initialized")
DIAG(err_redefinition_of_label, ERROR,
"redefinition of label '%0'")
Modified: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=41674&r1=41673&r2=41674&view=diff
==============================================================================
--- cfe/trunk/test/Sema/array-init.c (original)
+++ cfe/trunk/test/Sema/array-init.c Sun Sep 2 15:30:18 2007
@@ -7,12 +7,14 @@
extern int fileScopeExtern[3] = { 1, 3, 5 }; // expected-warning{{'extern' variable has an initializer}}
+static int ary3[] = { 1, "abc", 3 }; // expected-warning{{incompatible types assigning 'char *' to 'int'}}
+
void func() {
int x = 1;
//int x2[] = { 1, 3, 5 };
- int x3[x] = { 1, 2 }; // gcc-error {{variable-sized object may not be initialized}}
+ int x3[x] = { 1, 2 }; // expected-error{{variable-sized object may not be initialized}}
int x4 = { 1, 2 }; // gcc-warning {{excess elements in array initializer}}
@@ -33,4 +35,6 @@
struct threeElements *p = 7; // expected-warning{{incompatible types assigning 'int' to 'struct threeElements *'}}
extern int blockScopeExtern[3] = { 1, 3, 5 }; // expected-error{{'extern' variable cannot have an initializer}}
+
+ static int x2[3] = { 1.0, "abc" , 5.8 }; // expected-warning{{incompatible types assigning 'char *' to 'int'}}
}
More information about the cfe-commits
mailing list