diff options
-rw-r--r-- | clang/include/clang/AST/Expr.h | 4 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 29 | ||||
-rw-r--r-- | clang/test/CodeGen/object-size.c | 10 |
3 files changed, 42 insertions, 1 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index d63e01dcd0d..bcac18ffa22 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -241,6 +241,10 @@ public: /// in Result. bool Evaluate(EvalResult &Result, ASTContext &Ctx) const; + /// EvaluateAsAny - The same as Evaluate, except that it also succeeds on + /// stack based objects. + bool EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const; + /// isEvaluatable - Call Evaluate to see if this expression can be constant /// folded, but discard the result. bool isEvaluatable(ASTContext &Ctx) const; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 9992b6944ec..8435e034173 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -877,7 +877,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_object_size: { const Expr *Arg = E->getArg(0)->IgnoreParens(); Expr::EvalResult Base; - if (Arg->Evaluate(Base, Info.Ctx) + if (Arg->EvaluateAsAny(Base, Info.Ctx) && Base.Val.getKind() == APValue::LValue && !Base.HasSideEffects) if (const Expr *LVBase = Base.Val.getLValueBase()) @@ -1830,6 +1830,33 @@ bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const { return true; } +bool Expr::EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const { + EvalInfo Info(Ctx, Result, true); + + if (getType()->isVectorType()) { + if (!EvaluateVector(this, Result.Val, Info)) + return false; + } else if (getType()->isIntegerType()) { + if (!IntExprEvaluator(Info, Result.Val).Visit(const_cast<Expr*>(this))) + return false; + } else if (getType()->hasPointerRepresentation()) { + if (!EvaluatePointer(this, Result.Val, Info)) + return false; + } else if (getType()->isRealFloatingType()) { + llvm::APFloat f(0.0); + if (!EvaluateFloat(this, f, Info)) + return false; + + Result.Val = APValue(f); + } else if (getType()->isAnyComplexType()) { + if (!EvaluateComplex(this, Result.Val, Info)) + return false; + } else + return false; + + return true; +} + bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const { EvalInfo Info(Ctx, Result); diff --git a/clang/test/CodeGen/object-size.c b/clang/test/CodeGen/object-size.c index 36dc341e932..970d11f6e16 100644 --- a/clang/test/CodeGen/object-size.c +++ b/clang/test/CodeGen/object-size.c @@ -47,3 +47,13 @@ void test6() { // CHECK: call ___inline_strcpy_chk strcpy((++i, gbuf), "Hi there"); } + +void test7() { + char buf[57]; + + // CHECK: movabsq $53, %rdx + // CHECK-NEXT: movq %rax, %rdi + // CHECK-NEXT: movq %rcx, %rsi + // CHECK-NEXT: call ___strcpy_chk + strcpy(&buf[4], "Hi there"); +} |