From 2f72c427cfac0277fdc2e1f4fb19432d09d6fb45 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 13 Nov 2007 18:05:45 +0000 Subject: [PATCH] improve handling of address of global when checking for constants and initializers. Patch by Sanghyeon Seo, thanks! llvm-svn: 44049 --- clang/AST/Expr.cpp | 22 ++++++++++++++++++++++ clang/include/clang/AST/Expr.h | 4 ++++ clang/test/Sema/address-constant.c | 7 +++++++ 3 files changed, 33 insertions(+) create mode 100644 clang/test/Sema/address-constant.c diff --git a/clang/AST/Expr.cpp b/clang/AST/Expr.cpp index 4505feca77e8..10f0895695eb 100644 --- a/clang/AST/Expr.cpp +++ b/clang/AST/Expr.cpp @@ -359,6 +359,22 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue() const { return MLV_Valid; } +bool Expr::hasStaticStorage() const { + switch (getStmtClass()) { + default: + return false; + case DeclRefExprClass: { + const Decl *D = cast(this)->getDecl(); + if (const VarDecl *VD = dyn_cast(D)) + return VD->hasStaticStorage(); + return false; + } + case MemberExprClass: + const MemberExpr *M = cast(this); + return !M->isArrow() && M->getBase()->hasStaticStorage(); + } +} + bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { switch (getStmtClass()) { default: @@ -391,11 +407,17 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { if (isa(D) || isa(D)) return true; if (Loc) *Loc = getLocStart(); + if (isa(D)) + return TR->isArrayType(); return false; } case UnaryOperatorClass: { const UnaryOperator *Exp = cast(this); + // C99 6.6p9 + if (Exp->getOpcode() == UnaryOperator::AddrOf) + return Exp->getSubExpr()->hasStaticStorage(); + // Get the operand value. If this is sizeof/alignof, do not evalute the // operand. This affects C99 6.6p3. if (!Exp->isSizeOfAlignOfOp() && diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 7f47a299b3d9..e69344690ddd 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -105,6 +105,10 @@ public: /// isConstantExpr - Return true if this expression is a valid constant expr. bool isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const; + /// hasStaticStorage - Return true if this expression has static storage + /// duration. + bool hasStaticStorage() const; + static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && T->getStmtClass() <= lastExprConstant; diff --git a/clang/test/Sema/address-constant.c b/clang/test/Sema/address-constant.c new file mode 100644 index 000000000000..0b451cc39c0c --- /dev/null +++ b/clang/test/Sema/address-constant.c @@ -0,0 +1,7 @@ +// RUN: clang -fsyntax-only -verify %s + +int i; +int a[] = {0}; +struct { int i; } s; + +int *array[] = {&i, a, &s.i};