From 7a241baf2fad7719bc57acd2cf2fe400256b26f6 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Thu, 3 Jul 2008 04:20:39 +0000 Subject: [PATCH] Shuffle things around in preparation for integrating Eli's constant evaluator. llvm-svn: 53074 --- clang/clang.xcodeproj/project.pbxproj | 6 ++- clang/include/clang/AST/APValue.h | 11 ++++- clang/include/clang/AST/Expr.h | 5 ++- clang/lib/AST/Expr.cpp | 1 + clang/lib/AST/ExprConstant.cpp | 60 +++++++++++++++++++++++++++ clang/lib/Sema/SemaDecl.cpp | 41 ++++-------------- 6 files changed, 86 insertions(+), 38 deletions(-) create mode 100644 clang/lib/AST/ExprConstant.cpp diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index 1b3f147096c4..4ae76efcb118 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 035611E20DB40C8100D2EF2A /* RewriteObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 035611E10DB40C8100D2EF2A /* RewriteObjC.cpp */; }; 03F50AC60D416EAA00B9CF60 /* Targets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F50AC50D416EAA00B9CF60 /* Targets.cpp */; }; 1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A30A9E80B93A4C800201A91 /* ExprCXX.h */; }; + 1A32C17F0E1C87AD00A6B483 /* ExprConstant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */; }; 1A376A2D0D4AED9B002A1C52 /* CGExprConstant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */; }; 1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A7342470C7B57D500122F56 /* CGObjC.cpp */; }; 1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; }; @@ -260,6 +261,7 @@ 035611E10DB40C8100D2EF2A /* RewriteObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteObjC.cpp; path = Driver/RewriteObjC.cpp; sourceTree = ""; }; 03F50AC50D416EAA00B9CF60 /* Targets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Targets.cpp; sourceTree = ""; }; 1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = ""; }; + 1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ExprConstant.cpp; path = lib/AST/ExprConstant.cpp; sourceTree = ""; tabWidth = 2; }; 1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprConstant.cpp; path = lib/CodeGen/CGExprConstant.cpp; sourceTree = ""; }; 1A68BC110D0CADDD001A28C8 /* PPCBuiltins.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = PPCBuiltins.def; path = clang/AST/PPCBuiltins.def; sourceTree = ""; }; 1A68BC120D0CADDD001A28C8 /* TargetBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TargetBuiltins.h; path = clang/AST/TargetBuiltins.h; sourceTree = ""; }; @@ -406,7 +408,7 @@ DE5932CE0AD60FF400BC794C /* clang.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = clang.h; path = Driver/clang.h; sourceTree = ""; }; DE5932CF0AD60FF400BC794C /* PrintParserCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PrintParserCallbacks.cpp; path = Driver/PrintParserCallbacks.cpp; sourceTree = ""; }; DE5932D00AD60FF400BC794C /* PrintPreprocessedOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PrintPreprocessedOutput.cpp; path = Driver/PrintPreprocessedOutput.cpp; sourceTree = ""; }; - DE613EF30E0E148D00B05B79 /* APValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = APValue.h; path = clang/AST/APValue.h; sourceTree = ""; }; + DE613EF30E0E148D00B05B79 /* APValue.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = APValue.h; path = clang/AST/APValue.h; sourceTree = ""; tabWidth = 2; }; DE67E70A0C020EC500F66BC5 /* SemaType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaType.cpp; path = lib/Sema/SemaType.cpp; sourceTree = ""; }; DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaStmt.cpp; path = lib/Sema/SemaStmt.cpp; sourceTree = ""; }; DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExprCXX.cpp; path = lib/Sema/SemaExprCXX.cpp; sourceTree = ""; }; @@ -826,6 +828,7 @@ DE38CF260D8C9E6C00A273B6 /* DeclObjC.cpp */, 3513185F0CD14468006B66F7 /* DeclSerialization.cpp */, DE0FCB330A9C21F100248FD5 /* Expr.cpp */, + 1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */, 35260CA40C7F75C000D66CE9 /* ExprCXX.cpp */, DE3452400AEF1A2D00DBC861 /* Stmt.cpp */, DEF2EDA60C6A4252000C4259 /* StmtDumper.cpp */, @@ -1121,6 +1124,7 @@ 3534A01D0E129849002709B2 /* ParseCXXInlineMethods.cpp in Sources */, DE22BCF20E14197E0094DC60 /* SemaDeclAttr.cpp in Sources */, 359DBBD40E1AC9CC00F43FA0 /* AnalysisConsumer.cpp in Sources */, + 1A32C17F0E1C87AD00A6B483 /* ExprConstant.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 626019c31b1f..ba3d86bf498b 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -18,9 +18,10 @@ #include "llvm/ADT/APFloat.h" namespace clang { + class Expr; /// APValue - This class implements a discriminated union of [uninitialized] -/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat]. +/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset]. class APValue { typedef llvm::APSInt APSInt; typedef llvm::APFloat APFloat; @@ -30,7 +31,8 @@ public: SInt, Float, ComplexSInt, - ComplexFloat + ComplexFloat, + LValue }; private: ValueKind Kind; @@ -44,6 +46,11 @@ private: ComplexAPFloat() : Real(0.0), Imag(0.0) {} }; + struct LValue { + Expr* Base; + uint64_t Offset; + }; + enum { MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat)) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index b2071869adc0..e821cc391034 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -29,7 +29,8 @@ namespace clang { class Selector; class Decl; class ASTContext; - + class APValue; + /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt /// is required. @@ -108,6 +109,8 @@ public: /// isConstantExpr - Return true if this expression is a valid constant expr. bool isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const; + bool tryEvaluate(APValue& Result, ASTContext &Ctx) const; + /// hasGlobalStorage - Return true if this expression has static storage /// duration. This means that the address of this expression is a link-time /// constant. diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 58dadb080196..de0c740fd293 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 000000000000..ea9b106b69d9 --- /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(Expr)) + return CalcFakeICEVal(PE->getSubExpr(), Result, Context); + + if (const CastExpr *CE = dyn_cast(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 c0c3f09b8c90..80c37b97641c 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(Expr)) - return CalcFakeICEVal(PE->getSubExpr(), Result, Context); - - if (const CastExpr *CE = dyn_cast(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(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();