diff options
-rw-r--r-- | lib/AST/ExprConstant.cpp | 30 | ||||
-rw-r--r-- | test/CodeGen/object-size.c | 33 |
2 files changed, 63 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); diff --git a/test/CodeGen/object-size.c b/test/CodeGen/object-size.c new file mode 100644 index 0000000000..b686116989 --- /dev/null +++ b/test/CodeGen/object-size.c @@ -0,0 +1,33 @@ +// RUN: clang-cc -triple x86_64-apple-darwin -S -D_FORTIFY_SOURCE=2 %s -o %t.s && +// RUN: FileCheck --input-file=%t.s %s +#include <string.h> + +char gbuf[63]; +char *gp; + +void test1() { + // CHECK: movabsq $59, %rdx + // CHECK-NEXT: movq %rax, %rdi + // CHECK-NEXT: movq %rcx, %rsi + // CHECK-NEXT: call ___strcpy_chk + strcpy(&gbuf[4], "Hi there"); +} + +void test2() { + // CHECK: movabsq $63, %rdx + // CHECK-NEXT: movq %rax, %rdi + // CHECK-NEXT: movq %rcx, %rsi + // CHECK-NEXT: call ___strcpy_chk + strcpy(gbuf, "Hi there"); +} + +void test4() { + // CHECK: call ___inline_strcpy_chk + strcpy(gp, "Hi"); +} + +void test3() { + int i; + // CHECK: call ___inline_strcpy_chk + strcpy((++i, gbuf), "Hi"); +} |