diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 60 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 41 |
3 files changed, 68 insertions, 34 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 58dadb08019..de0c740fd29 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -13,6 +13,7 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/APValue.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/TargetInfo.h" diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp new file mode 100644 index 00000000000..ea9b106b69d --- /dev/null +++ b/clang/lib/AST/ExprConstant.cpp @@ -0,0 +1,60 @@ +//===--- Expr.cpp - Expression Constant Evaluator -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Expr constant evaluator. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/APValue.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" + +using namespace clang; + + +static bool CalcFakeICEVal(const Expr* Expr, + llvm::APSInt& Result, + ASTContext& Context) { + // Calculate the value of an expression that has a calculatable + // value, but isn't an ICE. Currently, this only supports + // a very narrow set of extensions, but it can be expanded if needed. + if (const ParenExpr *PE = dyn_cast<ParenExpr>(Expr)) + return CalcFakeICEVal(PE->getSubExpr(), Result, Context); + + if (const CastExpr *CE = dyn_cast<CastExpr>(Expr)) { + QualType CETy = CE->getType(); + if ((CETy->isIntegralType() && !CETy->isBooleanType()) || + CETy->isPointerType()) { + if (CalcFakeICEVal(CE->getSubExpr(), Result, Context)) { + Result.extOrTrunc(Context.getTypeSize(CETy)); + // FIXME: This assumes pointers are signed. + Result.setIsSigned(CETy->isSignedIntegerType() || + CETy->isPointerType()); + return true; + } + } + } + + if (Expr->getType()->isIntegralType()) + return Expr->isIntegerConstantExpr(Result, Context); + + return false; +} + +bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const +{ + llvm::APSInt sInt(1); + + if (CalcFakeICEVal(this, sInt, Ctx)) { + Result = APValue(sInt); + return true; + } + + return false; +} diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c0c3f09b8c9..80c37b97641 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" @@ -1799,48 +1800,20 @@ void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart, CollectIvars(Class, Decls); } - -static bool CalcFakeICEVal(const Expr* Expr, - llvm::APSInt& Result, - ASTContext& Context) { - // Calculate the value of an expression that has a calculatable - // value, but isn't an ICE. Currently, this only supports - // a very narrow set of extensions, but it can be expanded if needed. - if (const ParenExpr *PE = dyn_cast<ParenExpr>(Expr)) - return CalcFakeICEVal(PE->getSubExpr(), Result, Context); - - if (const CastExpr *CE = dyn_cast<CastExpr>(Expr)) { - QualType CETy = CE->getType(); - if ((CETy->isIntegralType() && !CETy->isBooleanType()) || - CETy->isPointerType()) { - if (CalcFakeICEVal(CE->getSubExpr(), Result, Context)) { - Result.extOrTrunc(Context.getTypeSize(CETy)); - // FIXME: This assumes pointers are signed. - Result.setIsSigned(CETy->isSignedIntegerType() || - CETy->isPointerType()); - return true; - } - } - } - - if (Expr->getType()->isIntegralType()) - return Expr->isIntegerConstantExpr(Result, Context); - - return false; -} - QualType Sema::TryFixInvalidVariablyModifiedType(QualType T) { // This method tries to turn a variable array into a constant // array even when the size isn't an ICE. This is necessary // for compatibility with code that depends on gcc's buggy // constant expression folding, like struct {char x[(int)(char*)2];} if (const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T)) { - llvm::APSInt Result(32); + APValue Result; if (VLATy->getSizeExpr() && - CalcFakeICEVal(VLATy->getSizeExpr(), Result, Context) && - Result > llvm::APSInt(Result.getBitWidth(), Result.isUnsigned())) { + VLATy->getSizeExpr()->tryEvaluate(Result, Context) && Result.isSInt() && + Result.getSInt() > llvm::APSInt(Result.getSInt().getBitWidth(), + Result.getSInt().isUnsigned())) { return Context.getConstantArrayType(VLATy->getElementType(), - Result, ArrayType::Normal, 0); + Result.getSInt(), + ArrayType::Normal, 0); } } return QualType(); |