diff options
author | Mike Stump <mrs@apple.com> | 2009-10-26 18:35:08 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2009-10-26 18:35:08 +0000 |
commit | 64eda9e50b593f935c95bd1edc98c4bfda03f601 (patch) | |
tree | 06421766987aafc8d11fc2554268d4531b1732a1 /lib/AST/ExprConstant.cpp | |
parent | a98c0348f6bbc0d3c473f8d1e46d15493324f0e5 (diff) |
__builtin_object_size refinements. WIP.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85136 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 94d22998eb..9129558421 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -873,6 +873,36 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { switch (E->isBuiltinCall(Info.Ctx)) { default: return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + + case Builtin::BI__builtin_object_size: { + llvm::APSInt Result(32); + + if (!E->getArg(1)->isIntegerConstantExpr(Result, Info.Ctx)) + assert(0 && "arg2 not ice in __builtin_object_size"); + + const Expr *Arg = E->getArg(0)->IgnoreParens(); + Expr::EvalResult Base; + if (Arg->Evaluate(Base, Info.Ctx) + && Base.Val.getKind() == APValue::LValue + && !Base.HasSideEffects) + if (const Expr *LVBase = Base.Val.getLValueBase()) + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LVBase)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { + uint64_t Size = Info.Ctx.getTypeSize(VD->getType()) / 8; + Size -= Base.Val.getLValueOffset(); + return Success(Size, E); + } + } + + if (Base.HasSideEffects) { + if (Result.getSExtValue() < 2) + return Success(-1, E); + return Success(0, E); + } + + return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + } + case Builtin::BI__builtin_classify_type: return Success(EvaluateBuiltinClassifyType(E), E); |