From 9c3b588db9ddf5582e4d1e3ff931d7b1cac7d8c8 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Wed, 30 Jan 2019 20:34:53 +0000 Subject: [PATCH] Add a new builtin: __builtin_dynamic_object_size This builtin has the same UI as __builtin_object_size, but has the potential to be evaluated dynamically. It is meant to be used as a drop-in replacement for libraries that use __builtin_object_size when a dynamic checking mode is enabled. For instance, __builtin_object_size fails to provide any extra checking in the following function: void f(size_t alloc) { char* p = malloc(alloc); strcpy(p, "foobar"); // expands to __builtin___strcpy_chk(p, "foobar", __builtin_object_size(p, 0)) } This is an overflow if alloc < 7, but because LLVM can't fold the object size intrinsic statically, it folds __builtin_object_size to -1. With __builtin_dynamic_object_size, alloc is passed through to __builtin___strcpy_chk. rdar://32212419 Differential revision: https://reviews.llvm.org/D56760 llvm-svn: 352665 --- clang/docs/LanguageExtensions.rst | 26 ++ clang/include/clang/Basic/Builtins.def | 1 + clang/lib/AST/ExprConstant.cpp | 1 + clang/lib/Analysis/CFG.cpp | 3 +- clang/lib/CodeGen/CGBuiltin.cpp | 13 +- clang/lib/CodeGen/CGCall.cpp | 3 +- clang/lib/CodeGen/CodeGenFunction.h | 6 +- clang/lib/Sema/SemaChecking.cpp | 1 + .../Checkers/BuiltinFunctionChecker.cpp | 1 + clang/test/CodeGen/alloc-size.c | 219 ++++++++-------- clang/test/CodeGen/object-size.c | 285 +++++++++++---------- clang/test/Sema/builtin-object-size.c | 47 ++-- 12 files changed, 332 insertions(+), 274 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 03b20c2..d4c40b2 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2922,3 +2922,29 @@ Specifying Linker Options on ELF Targets The ``#pragma comment(lib, ...)`` directive is supported on all ELF targets. The second parameter is the library name (without the traditional Unix prefix of ``lib``). This allows you to provide an implicit link of dependent libraries. + +Evaluating Object Size Dynamically +================================== + +Clang supports the builtin ``__builtin_dynamic_object_size``, the semantics are +the same as GCC's ``__builtin_object_size`` (which Clang also supports), but +``__builtin_dynamic_object_size`` can evaluate the object's size at runtime. +``__builtin_dynamic_object_size`` is meant to be used as a drop-in replacement +for ``__builtin_object_size`` in libraries that support it. + +For instance, here is a program that ``__builtin_dynamic_object_size`` will make +safer: + +.. code-block:: c + + void copy_into_buffer(size_t size) { + char* buffer = malloc(size); + strlcpy(buffer, "some string", strlen("some string")); + // Previous line preprocesses to: + // __builtin___strlcpy_chk(buffer, "some string", strlen("some string"), __builtin_object_size(buffer, 0)) + } + +Since the size of ``buffer`` can't be known at compile time, Clang will fold +``__builtin_object_size(buffer, 0)`` into ``-1``. However, if this was written +as ``__builtin_dynamic_object_size(buffer, 0)``, Clang will fold it into +``size``, providing some extra runtime safety. diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 4efd843..2e8c6d9 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -511,6 +511,7 @@ BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t // GCC Object size checking builtins BUILTIN(__builtin_object_size, "zvC*i", "nu") +BUILTIN(__builtin_dynamic_object_size, "zvC*i", "nu") // Clang only. BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___memccpy_chk, "v*v*vC*izz", "nF") BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF") diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 62845a4..8f20e12 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8190,6 +8190,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, default: return ExprEvaluatorBaseTy::VisitCallExpr(E); + case Builtin::BI__builtin_dynamic_object_size: case Builtin::BI__builtin_object_size: { // The type was checked when we built the expression. unsigned Type = diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 0a62ed2..f6b8291 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2458,7 +2458,8 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { NoReturn = true; if (FD->hasAttr()) AddEHEdge = false; - if (FD->getBuiltinID() == Builtin::BI__builtin_object_size) + if (FD->getBuiltinID() == Builtin::BI__builtin_object_size || + FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size) OmitArguments = true; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f1014b6..93b5775 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -494,10 +494,11 @@ getDefaultBuiltinObjectSizeResult(unsigned Type, llvm::IntegerType *ResType) { llvm::Value * CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, llvm::IntegerType *ResType, - llvm::Value *EmittedE) { + llvm::Value *EmittedE, + bool IsDynamic) { uint64_t ObjectSize; if (!E->tryEvaluateObjectSize(ObjectSize, getContext(), Type)) - return emitBuiltinObjectSize(E, Type, ResType, EmittedE); + return emitBuiltinObjectSize(E, Type, ResType, EmittedE, IsDynamic); return ConstantInt::get(ResType, ObjectSize, /*isSigned=*/true); } @@ -513,7 +514,7 @@ CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, llvm::Value * CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, llvm::IntegerType *ResType, - llvm::Value *EmittedE) { + llvm::Value *EmittedE, bool IsDynamic) { // We need to reference an argument if the pointer is a parameter with the // pass_object_size attribute. if (auto *D = dyn_cast(E->IgnoreParenImpCasts())) { @@ -549,7 +550,7 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, Value *Min = Builder.getInt1((Type & 2) != 0); // For GCC compatibility, __builtin_object_size treat NULL as unknown size. Value *NullIsUnknown = Builder.getTrue(); - Value *Dynamic = Builder.getFalse(); + Value *Dynamic = Builder.getInt1(IsDynamic); return Builder.CreateCall(F, {Ptr, Min, NullIsUnknown, Dynamic}); } @@ -1978,6 +1979,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/false); return RValue::get(Result); } + case Builtin::BI__builtin_dynamic_object_size: case Builtin::BI__builtin_object_size: { unsigned Type = E->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue(); @@ -1985,8 +1987,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // We pass this builtin onto the optimizer so that it can figure out the // object size in more complex cases. + bool IsDynamic = BuiltinID == Builtin::BI__builtin_dynamic_object_size; return RValue::get(emitBuiltinObjectSize(E->getArg(0), Type, ResType, - /*EmittedE=*/nullptr)); + /*EmittedE=*/nullptr, IsDynamic)); } case Builtin::BI__builtin_prefetch: { Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 829821a..893a6f2 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3459,7 +3459,8 @@ void CodeGenFunction::EmitCallArgs( auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); assert(EmittedArg.getScalarVal() && "We emitted nothing for the arg?"); llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T, - EmittedArg.getScalarVal()); + EmittedArg.getScalarVal(), + /*IsDynamic=*/false); Args.add(RValue::get(V), SizeTy); // If we're emitting args in reverse, be sure to do so with // pass_object_size, as well. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 87d141fe..a989a0e 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4177,14 +4177,16 @@ private: /// If EmittedExpr is non-null, this will use that instead of re-emitting E. llvm::Value *evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, llvm::IntegerType *ResType, - llvm::Value *EmittedE); + llvm::Value *EmittedE, + bool IsDynamic); /// Emits the size of E, as required by __builtin_object_size. This /// function is aware of pass_object_size parameters, and will act accordingly /// if E is a parameter with the pass_object_size attribute. llvm::Value *emitBuiltinObjectSize(const Expr *E, unsigned Type, llvm::IntegerType *ResType, - llvm::Value *EmittedE); + llvm::Value *EmittedE, + bool IsDynamic); public: #ifndef NDEBUG diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 5a5e561..4b5c68a 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1076,6 +1076,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinAssumeAligned(TheCall)) return ExprError(); break; + case Builtin::BI__builtin_dynamic_object_size: case Builtin::BI__builtin_object_size: if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3)) return ExprError(); diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index f35ee0f..290a035 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -95,6 +95,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, return true; } + case Builtin::BI__builtin_dynamic_object_size: case Builtin::BI__builtin_object_size: case Builtin::BI__builtin_constant_p: { // This must be resolvable at compile time, so we defer to the constant diff --git a/clang/test/CodeGen/alloc-size.c b/clang/test/CodeGen/alloc-size.c index 7953d02..aa5b295 100644 --- a/clang/test/CodeGen/alloc-size.c +++ b/clang/test/CodeGen/alloc-size.c @@ -1,4 +1,11 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s +// RUN: %clang_cc1 -DDYNAMIC -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s + +#ifdef DYNAMIC +#define OBJECT_SIZE_BUILTIN __builtin_dynamic_object_size +#else +#define OBJECT_SIZE_BUILTIN __builtin_object_size +#endif #define NULL ((void *)0) @@ -20,86 +27,86 @@ void *my_calloc(size_t, size_t) __attribute__((alloc_size(1, 2))); void test1() { void *const vp = my_malloc(100); // CHECK: store i32 100 - gi = __builtin_object_size(vp, 0); + gi = OBJECT_SIZE_BUILTIN(vp, 0); // CHECK: store i32 100 - gi = __builtin_object_size(vp, 1); + gi = OBJECT_SIZE_BUILTIN(vp, 1); // CHECK: store i32 100 - gi = __builtin_object_size(vp, 2); + gi = OBJECT_SIZE_BUILTIN(vp, 2); // CHECK: store i32 100 - gi = __builtin_object_size(vp, 3); + gi = OBJECT_SIZE_BUILTIN(vp, 3); void *const arr = my_calloc(100, 5); // CHECK: store i32 500 - gi = __builtin_object_size(arr, 0); + gi = OBJECT_SIZE_BUILTIN(arr, 0); // CHECK: store i32 500 - gi = __builtin_object_size(arr, 1); + gi = OBJECT_SIZE_BUILTIN(arr, 1); // CHECK: store i32 500 - gi = __builtin_object_size(arr, 2); + gi = OBJECT_SIZE_BUILTIN(arr, 2); // CHECK: store i32 500 - gi = __builtin_object_size(arr, 3); + gi = OBJECT_SIZE_BUILTIN(arr, 3); // CHECK: store i32 100 - gi = __builtin_object_size(my_malloc(100), 0); + gi = OBJECT_SIZE_BUILTIN(my_malloc(100), 0); // CHECK: store i32 100 - gi = __builtin_object_size(my_malloc(100), 1); + gi = OBJECT_SIZE_BUILTIN(my_malloc(100), 1); // CHECK: store i32 100 - gi = __builtin_object_size(my_malloc(100), 2); + gi = OBJECT_SIZE_BUILTIN(my_malloc(100), 2); // CHECK: store i32 100 - gi = __builtin_object_size(my_malloc(100), 3); + gi = OBJECT_SIZE_BUILTIN(my_malloc(100), 3); // CHECK: store i32 500 - gi = __builtin_object_size(my_calloc(100, 5), 0); + gi = OBJECT_SIZE_BUILTIN(my_calloc(100, 5), 0); // CHECK: store i32 500 - gi = __builtin_object_size(my_calloc(100, 5), 1); + gi = OBJECT_SIZE_BUILTIN(my_calloc(100, 5), 1); // CHECK: store i32 500 - gi = __builtin_object_size(my_calloc(100, 5), 2); + gi = OBJECT_SIZE_BUILTIN(my_calloc(100, 5), 2); // CHECK: store i32 500 - gi = __builtin_object_size(my_calloc(100, 5), 3); + gi = OBJECT_SIZE_BUILTIN(my_calloc(100, 5), 3); void *const zeroPtr = my_malloc(0); // CHECK: store i32 0 - gi = __builtin_object_size(zeroPtr, 0); + gi = OBJECT_SIZE_BUILTIN(zeroPtr, 0); // CHECK: store i32 0 - gi = __builtin_object_size(my_malloc(0), 0); + gi = OBJECT_SIZE_BUILTIN(my_malloc(0), 0); void *const zeroArr1 = my_calloc(0, 1); void *const zeroArr2 = my_calloc(1, 0); // CHECK: store i32 0 - gi = __builtin_object_size(zeroArr1, 0); + gi = OBJECT_SIZE_BUILTIN(zeroArr1, 0); // CHECK: store i32 0 - gi = __builtin_object_size(zeroArr2, 0); + gi = OBJECT_SIZE_BUILTIN(zeroArr2, 0); // CHECK: store i32 0 - gi = __builtin_object_size(my_calloc(1, 0), 0); + gi = OBJECT_SIZE_BUILTIN(my_calloc(1, 0), 0); // CHECK: store i32 0 - gi = __builtin_object_size(my_calloc(0, 1), 0); + gi = OBJECT_SIZE_BUILTIN(my_calloc(0, 1), 0); } // CHECK-LABEL: @test2 void test2() { void *const vp = my_malloc(gi); // CHECK: @llvm.objectsize - gi = __builtin_object_size(vp, 0); + gi = OBJECT_SIZE_BUILTIN(vp, 0); void *const arr1 = my_calloc(gi, 1); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr1, 0); + gi = OBJECT_SIZE_BUILTIN(arr1, 0); void *const arr2 = my_calloc(1, gi); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr2, 0); + gi = OBJECT_SIZE_BUILTIN(arr2, 0); } // CHECK-LABEL: @test3 void test3() { char *const buf = (char *)my_calloc(100, 5); // CHECK: store i32 500 - gi = __builtin_object_size(buf, 0); + gi = OBJECT_SIZE_BUILTIN(buf, 0); // CHECK: store i32 500 - gi = __builtin_object_size(buf, 1); + gi = OBJECT_SIZE_BUILTIN(buf, 1); // CHECK: store i32 500 - gi = __builtin_object_size(buf, 2); + gi = OBJECT_SIZE_BUILTIN(buf, 2); // CHECK: store i32 500 - gi = __builtin_object_size(buf, 3); + gi = OBJECT_SIZE_BUILTIN(buf, 3); } struct Data { @@ -113,41 +120,41 @@ struct Data { void test5() { struct Data *const data = my_malloc(sizeof(*data)); // CHECK: store i32 48 - gi = __builtin_object_size(data, 0); + gi = OBJECT_SIZE_BUILTIN(data, 0); // CHECK: store i32 48 - gi = __builtin_object_size(data, 1); + gi = OBJECT_SIZE_BUILTIN(data, 1); // CHECK: store i32 48 - gi = __builtin_object_size(data, 2); + gi = OBJECT_SIZE_BUILTIN(data, 2); // CHECK: store i32 48 - gi = __builtin_object_size(data, 3); + gi = OBJECT_SIZE_BUILTIN(data, 3); // CHECK: store i32 40 - gi = __builtin_object_size(&data->t[1], 0); + gi = OBJECT_SIZE_BUILTIN(&data->t[1], 0); // CHECK: store i32 36 - gi = __builtin_object_size(&data->t[1], 1); + gi = OBJECT_SIZE_BUILTIN(&data->t[1], 1); // CHECK: store i32 40 - gi = __builtin_object_size(&data->t[1], 2); + gi = OBJECT_SIZE_BUILTIN(&data->t[1], 2); // CHECK: store i32 36 - gi = __builtin_object_size(&data->t[1], 3); + gi = OBJECT_SIZE_BUILTIN(&data->t[1], 3); struct Data *const arr = my_calloc(sizeof(*data), 2); // CHECK: store i32 96 - gi = __builtin_object_size(arr, 0); + gi = OBJECT_SIZE_BUILTIN(arr, 0); // CHECK: store i32 96 - gi = __builtin_object_size(arr, 1); + gi = OBJECT_SIZE_BUILTIN(arr, 1); // CHECK: store i32 96 - gi = __builtin_object_size(arr, 2); + gi = OBJECT_SIZE_BUILTIN(arr, 2); // CHECK: store i32 96 - gi = __builtin_object_size(arr, 3); + gi = OBJECT_SIZE_BUILTIN(arr, 3); // CHECK: store i32 88 - gi = __builtin_object_size(&arr->t[1], 0); + gi = OBJECT_SIZE_BUILTIN(&arr->t[1], 0); // CHECK: store i32 36 - gi = __builtin_object_size(&arr->t[1], 1); + gi = OBJECT_SIZE_BUILTIN(&arr->t[1], 1); // CHECK: store i32 88 - gi = __builtin_object_size(&arr->t[1], 2); + gi = OBJECT_SIZE_BUILTIN(&arr->t[1], 2); // CHECK: store i32 36 - gi = __builtin_object_size(&arr->t[1], 3); + gi = OBJECT_SIZE_BUILTIN(&arr->t[1], 3); } // CHECK-LABEL: @test6 @@ -156,13 +163,13 @@ void test6() { // so when we know the source of the allocation. struct Data *const data = my_malloc(sizeof(*data) + 10); // CHECK: store i32 11 - gi = __builtin_object_size(data->end, 0); + gi = OBJECT_SIZE_BUILTIN(data->end, 0); // CHECK: store i32 11 - gi = __builtin_object_size(data->end, 1); + gi = OBJECT_SIZE_BUILTIN(data->end, 1); // CHECK: store i32 11 - gi = __builtin_object_size(data->end, 2); + gi = OBJECT_SIZE_BUILTIN(data->end, 2); // CHECK: store i32 11 - gi = __builtin_object_size(data->end, 3); + gi = OBJECT_SIZE_BUILTIN(data->end, 3); struct Data *const arr = my_calloc(sizeof(*arr) + 5, 3); // AFAICT, GCC treats malloc and calloc identically. So, we should do the @@ -178,67 +185,67 @@ void test6() { // or "allocate M smaller `Data`s with extra padding". // CHECK: store i32 112 - gi = __builtin_object_size(arr->end, 0); + gi = OBJECT_SIZE_BUILTIN(arr->end, 0); // CHECK: store i32 112 - gi = __builtin_object_size(arr->end, 1); + gi = OBJECT_SIZE_BUILTIN(arr->end, 1); // CHECK: store i32 112 - gi = __builtin_object_size(arr->end, 2); + gi = OBJECT_SIZE_BUILTIN(arr->end, 2); // CHECK: store i32 112 - gi = __builtin_object_size(arr->end, 3); + gi = OBJECT_SIZE_BUILTIN(arr->end, 3); // CHECK: store i32 112 - gi = __builtin_object_size(arr[0].end, 0); + gi = OBJECT_SIZE_BUILTIN(arr[0].end, 0); // CHECK: store i32 112 - gi = __builtin_object_size(arr[0].end, 1); + gi = OBJECT_SIZE_BUILTIN(arr[0].end, 1); // CHECK: store i32 112 - gi = __builtin_object_size(arr[0].end, 2); + gi = OBJECT_SIZE_BUILTIN(arr[0].end, 2); // CHECK: store i32 112 - gi = __builtin_object_size(arr[0].end, 3); + gi = OBJECT_SIZE_BUILTIN(arr[0].end, 3); // CHECK: store i32 64 - gi = __builtin_object_size(arr[1].end, 0); + gi = OBJECT_SIZE_BUILTIN(arr[1].end, 0); // CHECK: store i32 64 - gi = __builtin_object_size(arr[1].end, 1); + gi = OBJECT_SIZE_BUILTIN(arr[1].end, 1); // CHECK: store i32 64 - gi = __builtin_object_size(arr[1].end, 2); + gi = OBJECT_SIZE_BUILTIN(arr[1].end, 2); // CHECK: store i32 64 - gi = __builtin_object_size(arr[1].end, 3); + gi = OBJECT_SIZE_BUILTIN(arr[1].end, 3); // CHECK: store i32 16 - gi = __builtin_object_size(arr[2].end, 0); + gi = OBJECT_SIZE_BUILTIN(arr[2].end, 0); // CHECK: store i32 16 - gi = __builtin_object_size(arr[2].end, 1); + gi = OBJECT_SIZE_BUILTIN(arr[2].end, 1); // CHECK: store i32 16 - gi = __builtin_object_size(arr[2].end, 2); + gi = OBJECT_SIZE_BUILTIN(arr[2].end, 2); // CHECK: store i32 16 - gi = __builtin_object_size(arr[2].end, 3); + gi = OBJECT_SIZE_BUILTIN(arr[2].end, 3); } // CHECK-LABEL: @test7 void test7() { struct Data *const data = my_malloc(sizeof(*data) + 5); // CHECK: store i32 9 - gi = __builtin_object_size(data->pad, 0); + gi = OBJECT_SIZE_BUILTIN(data->pad, 0); // CHECK: store i32 3 - gi = __builtin_object_size(data->pad, 1); + gi = OBJECT_SIZE_BUILTIN(data->pad, 1); // CHECK: store i32 9 - gi = __builtin_object_size(data->pad, 2); + gi = OBJECT_SIZE_BUILTIN(data->pad, 2); // CHECK: store i32 3 - gi = __builtin_object_size(data->pad, 3); + gi = OBJECT_SIZE_BUILTIN(data->pad, 3); } // CHECK-LABEL: @test8 void test8() { // Non-const pointers aren't currently supported. void *buf = my_calloc(100, 5); - // CHECK: @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 false) - gi = __builtin_object_size(buf, 0); + // CHECK: @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 + gi = OBJECT_SIZE_BUILTIN(buf, 0); // CHECK: @llvm.objectsize - gi = __builtin_object_size(buf, 1); + gi = OBJECT_SIZE_BUILTIN(buf, 1); // CHECK: @llvm.objectsize - gi = __builtin_object_size(buf, 2); + gi = OBJECT_SIZE_BUILTIN(buf, 2); // CHECK: store i32 0 - gi = __builtin_object_size(buf, 3); + gi = OBJECT_SIZE_BUILTIN(buf, 3); } // CHECK-LABEL: @test9 @@ -249,11 +256,11 @@ void test9() { short *const buf2 = ((short*)(my_malloc(100))); // CHECK: store i32 100 - gi = __builtin_object_size(buf0, 0); + gi = OBJECT_SIZE_BUILTIN(buf0, 0); // CHECK: store i32 100 - gi = __builtin_object_size(buf1, 0); + gi = OBJECT_SIZE_BUILTIN(buf1, 0); // CHECK: store i32 100 - gi = __builtin_object_size(buf2, 0); + gi = OBJECT_SIZE_BUILTIN(buf2, 0); } // CHECK-LABEL: @test10 @@ -261,36 +268,36 @@ void test10() { // Yay overflow short *const arr = my_calloc((size_t)-1 / 2 + 1, 2); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr, 0); + gi = OBJECT_SIZE_BUILTIN(arr, 0); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr, 1); + gi = OBJECT_SIZE_BUILTIN(arr, 1); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr, 2); + gi = OBJECT_SIZE_BUILTIN(arr, 2); // CHECK: store i32 0 - gi = __builtin_object_size(arr, 3); + gi = OBJECT_SIZE_BUILTIN(arr, 3); // As an implementation detail, CharUnits can't handle numbers greater than or // equal to 2**63. Realistically, this shouldn't be a problem, but we should // be sure we don't emit crazy results for this case. short *const buf = my_malloc((size_t)-1); // CHECK: @llvm.objectsize - gi = __builtin_object_size(buf, 0); + gi = OBJECT_SIZE_BUILTIN(buf, 0); // CHECK: @llvm.objectsize - gi = __builtin_object_size(buf, 1); + gi = OBJECT_SIZE_BUILTIN(buf, 1); // CHECK: @llvm.objectsize - gi = __builtin_object_size(buf, 2); + gi = OBJECT_SIZE_BUILTIN(buf, 2); // CHECK: store i32 0 - gi = __builtin_object_size(buf, 3); + gi = OBJECT_SIZE_BUILTIN(buf, 3); short *const arr_big = my_calloc((size_t)-1 / 2 - 1, 2); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr_big, 0); + gi = OBJECT_SIZE_BUILTIN(arr_big, 0); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr_big, 1); + gi = OBJECT_SIZE_BUILTIN(arr_big, 1); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr_big, 2); + gi = OBJECT_SIZE_BUILTIN(arr_big, 2); // CHECK: store i32 0 - gi = __builtin_object_size(arr_big, 3); + gi = OBJECT_SIZE_BUILTIN(arr_big, 3); } void *my_tiny_malloc(char) __attribute__((alloc_size(1))); @@ -300,25 +307,25 @@ void *my_tiny_calloc(char, char) __attribute__((alloc_size(1, 2))); void test11() { void *const vp = my_tiny_malloc(100); // CHECK: store i32 100 - gi = __builtin_object_size(vp, 0); + gi = OBJECT_SIZE_BUILTIN(vp, 0); // CHECK: store i32 100 - gi = __builtin_object_size(vp, 1); + gi = OBJECT_SIZE_BUILTIN(vp, 1); // CHECK: store i32 100 - gi = __builtin_object_size(vp, 2); + gi = OBJECT_SIZE_BUILTIN(vp, 2); // CHECK: store i32 100 - gi = __builtin_object_size(vp, 3); + gi = OBJECT_SIZE_BUILTIN(vp, 3); // N.B. This causes char overflow, but not size_t overflow, so it should be // supported. void *const arr = my_tiny_calloc(100, 5); // CHECK: store i32 500 - gi = __builtin_object_size(arr, 0); + gi = OBJECT_SIZE_BUILTIN(arr, 0); // CHECK: store i32 500 - gi = __builtin_object_size(arr, 1); + gi = OBJECT_SIZE_BUILTIN(arr, 1); // CHECK: store i32 500 - gi = __builtin_object_size(arr, 2); + gi = OBJECT_SIZE_BUILTIN(arr, 2); // CHECK: store i32 500 - gi = __builtin_object_size(arr, 3); + gi = OBJECT_SIZE_BUILTIN(arr, 3); } void *my_signed_malloc(long) __attribute__((alloc_size(1))); @@ -327,26 +334,26 @@ void *my_signed_calloc(long, long) __attribute__((alloc_size(1, 2))); // CHECK-LABEL: @test12 void test12() { // CHECK: store i32 100 - gi = __builtin_object_size(my_signed_malloc(100), 0); + gi = OBJECT_SIZE_BUILTIN(my_signed_malloc(100), 0); // CHECK: store i32 500 - gi = __builtin_object_size(my_signed_calloc(100, 5), 0); + gi = OBJECT_SIZE_BUILTIN(my_signed_calloc(100, 5), 0); void *const vp = my_signed_malloc(-2); // CHECK: @llvm.objectsize - gi = __builtin_object_size(vp, 0); + gi = OBJECT_SIZE_BUILTIN(vp, 0); // N.B. These get lowered to -1 because the function calls may have // side-effects, and we can't determine the objectsize. // CHECK: store i32 -1 - gi = __builtin_object_size(my_signed_malloc(-2), 0); + gi = OBJECT_SIZE_BUILTIN(my_signed_malloc(-2), 0); void *const arr1 = my_signed_calloc(-2, 1); void *const arr2 = my_signed_calloc(1, -2); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr1, 0); + gi = OBJECT_SIZE_BUILTIN(arr1, 0); // CHECK: @llvm.objectsize - gi = __builtin_object_size(arr2, 0); + gi = OBJECT_SIZE_BUILTIN(arr2, 0); // CHECK: store i32 -1 - gi = __builtin_object_size(my_signed_calloc(1, -2), 0); + gi = OBJECT_SIZE_BUILTIN(my_signed_calloc(1, -2), 0); // CHECK: store i32 -1 - gi = __builtin_object_size(my_signed_calloc(-2, 1), 0); + gi = OBJECT_SIZE_BUILTIN(my_signed_calloc(-2, 1), 0); } diff --git a/clang/test/CodeGen/object-size.c b/clang/test/CodeGen/object-size.c index 9014e04..561fd4d 100644 --- a/clang/test/CodeGen/object-size.c +++ b/clang/test/CodeGen/object-size.c @@ -1,12 +1,19 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s +// RUN: %clang_cc1 -DDYNAMIC -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s + +#ifndef DYNAMIC +#define OBJECT_SIZE_BUILTIN __builtin_object_size +#else +#define OBJECT_SIZE_BUILTIN __builtin_dynamic_object_size +#endif #define strcpy(dest, src) \ - ((__builtin_object_size(dest, 0) != -1ULL) \ - ? __builtin___strcpy_chk (dest, src, __builtin_object_size(dest, 1)) \ + ((OBJECT_SIZE_BUILTIN(dest, 0) != -1ULL) \ + ? __builtin___strcpy_chk (dest, src, OBJECT_SIZE_BUILTIN(dest, 1)) \ : __inline_strcpy_chk(dest, src)) static char *__inline_strcpy_chk (char *dest, const char *src) { - return __builtin___strcpy_chk(dest, src, __builtin_object_size(dest, 1)); + return __builtin___strcpy_chk(dest, src, OBJECT_SIZE_BUILTIN(dest, 1)); } char gbuf[63]; @@ -40,7 +47,7 @@ void test4() { // CHECK-LABEL: define void @test5 void test5() { // CHECK: = load i8*, i8** @gp - // CHECK-NEXT:= call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 false) + // CHECK-NEXT:= call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 strcpy(gp, "Hi there"); } @@ -130,13 +137,13 @@ void test16() { // CHECK-LABEL: @test17 void test17() { // CHECK: store i32 -1 - gi = __builtin_object_size(gp++, 0); + gi = OBJECT_SIZE_BUILTIN(gp++, 0); // CHECK: store i32 -1 - gi = __builtin_object_size(gp++, 1); + gi = OBJECT_SIZE_BUILTIN(gp++, 1); // CHECK: store i32 0 - gi = __builtin_object_size(gp++, 2); + gi = OBJECT_SIZE_BUILTIN(gp++, 2); // CHECK: store i32 0 - gi = __builtin_object_size(gp++, 3); + gi = OBJECT_SIZE_BUILTIN(gp++, 3); } // CHECK-LABEL: @test18 @@ -144,7 +151,7 @@ unsigned test18(int cond) { int a[4], b[4]; // CHECK: phi i32* // CHECK: call i64 @llvm.objectsize.i64 - return __builtin_object_size(cond ? a : b, 0); + return OBJECT_SIZE_BUILTIN(cond ? a : b, 0); } // CHECK-LABEL: @test19 @@ -154,22 +161,22 @@ void test19() { } foo; // CHECK: store i32 8 - gi = __builtin_object_size(&foo.a, 0); + gi = OBJECT_SIZE_BUILTIN(&foo.a, 0); // CHECK: store i32 4 - gi = __builtin_object_size(&foo.a, 1); + gi = OBJECT_SIZE_BUILTIN(&foo.a, 1); // CHECK: store i32 8 - gi = __builtin_object_size(&foo.a, 2); + gi = OBJECT_SIZE_BUILTIN(&foo.a, 2); // CHECK: store i32 4 - gi = __builtin_object_size(&foo.a, 3); + gi = OBJECT_SIZE_BUILTIN(&foo.a, 3); // CHECK: store i32 4 - gi = __builtin_object_size(&foo.b, 0); + gi = OBJECT_SIZE_BUILTIN(&foo.b, 0); // CHECK: store i32 4 - gi = __builtin_object_size(&foo.b, 1); + gi = OBJECT_SIZE_BUILTIN(&foo.b, 1); // CHECK: store i32 4 - gi = __builtin_object_size(&foo.b, 2); + gi = OBJECT_SIZE_BUILTIN(&foo.b, 2); // CHECK: store i32 4 - gi = __builtin_object_size(&foo.b, 3); + gi = OBJECT_SIZE_BUILTIN(&foo.b, 3); } // CHECK-LABEL: @test20 @@ -177,13 +184,13 @@ void test20() { struct { int t[10]; } t[10]; // CHECK: store i32 380 - gi = __builtin_object_size(&t[0].t[5], 0); + gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 0); // CHECK: store i32 20 - gi = __builtin_object_size(&t[0].t[5], 1); + gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 1); // CHECK: store i32 380 - gi = __builtin_object_size(&t[0].t[5], 2); + gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 2); // CHECK: store i32 20 - gi = __builtin_object_size(&t[0].t[5], 3); + gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 3); } // CHECK-LABEL: @test21 @@ -191,22 +198,22 @@ void test21() { struct { int t; } t; // CHECK: store i32 0 - gi = __builtin_object_size(&t + 1, 0); + gi = OBJECT_SIZE_BUILTIN(&t + 1, 0); // CHECK: store i32 0 - gi = __builtin_object_size(&t + 1, 1); + gi = OBJECT_SIZE_BUILTIN(&t + 1, 1); // CHECK: store i32 0 - gi = __builtin_object_size(&t + 1, 2); + gi = OBJECT_SIZE_BUILTIN(&t + 1, 2); // CHECK: store i32 0 - gi = __builtin_object_size(&t + 1, 3); + gi = OBJECT_SIZE_BUILTIN(&t + 1, 3); // CHECK: store i32 0 - gi = __builtin_object_size(&t.t + 1, 0); + gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 0); // CHECK: store i32 0 - gi = __builtin_object_size(&t.t + 1, 1); + gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 1); // CHECK: store i32 0 - gi = __builtin_object_size(&t.t + 1, 2); + gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 2); // CHECK: store i32 0 - gi = __builtin_object_size(&t.t + 1, 3); + gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 3); } // CHECK-LABEL: @test22 @@ -214,40 +221,40 @@ void test22() { struct { int t[10]; } t[10]; // CHECK: store i32 0 - gi = __builtin_object_size(&t[10], 0); + gi = OBJECT_SIZE_BUILTIN(&t[10], 0); // CHECK: store i32 0 - gi = __builtin_object_size(&t[10], 1); + gi = OBJECT_SIZE_BUILTIN(&t[10], 1); // CHECK: store i32 0 - gi = __builtin_object_size(&t[10], 2); + gi = OBJECT_SIZE_BUILTIN(&t[10], 2); // CHECK: store i32 0 - gi = __builtin_object_size(&t[10], 3); + gi = OBJECT_SIZE_BUILTIN(&t[10], 3); // CHECK: store i32 0 - gi = __builtin_object_size(&t[9].t[10], 0); + gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 0); // CHECK: store i32 0 - gi = __builtin_object_size(&t[9].t[10], 1); + gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 1); // CHECK: store i32 0 - gi = __builtin_object_size(&t[9].t[10], 2); + gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 2); // CHECK: store i32 0 - gi = __builtin_object_size(&t[9].t[10], 3); + gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 3); // CHECK: store i32 0 - gi = __builtin_object_size((char*)&t[0] + sizeof(t), 0); + gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 0); // CHECK: store i32 0 - gi = __builtin_object_size((char*)&t[0] + sizeof(t), 1); + gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 1); // CHECK: store i32 0 - gi = __builtin_object_size((char*)&t[0] + sizeof(t), 2); + gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 2); // CHECK: store i32 0 - gi = __builtin_object_size((char*)&t[0] + sizeof(t), 3); + gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 3); // CHECK: store i32 0 - gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 0); + gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 0); // CHECK: store i32 0 - gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 1); + gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 1); // CHECK: store i32 0 - gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 2); + gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 2); // CHECK: store i32 0 - gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 3); + gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 3); } struct Test23Ty { int a; int t[10]; }; @@ -255,73 +262,73 @@ struct Test23Ty { int a; int t[10]; }; // CHECK-LABEL: @test23 void test23(struct Test23Ty *p) { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(p, 0); + gi = OBJECT_SIZE_BUILTIN(p, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(p, 1); + gi = OBJECT_SIZE_BUILTIN(p, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(p, 2); + gi = OBJECT_SIZE_BUILTIN(p, 2); // Note: this is currently fixed at 0 because LLVM doesn't have sufficient // data to correctly handle type=3 // CHECK: store i32 0 - gi = __builtin_object_size(p, 3); + gi = OBJECT_SIZE_BUILTIN(p, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(&p->a, 0); + gi = OBJECT_SIZE_BUILTIN(&p->a, 0); // CHECK: store i32 4 - gi = __builtin_object_size(&p->a, 1); + gi = OBJECT_SIZE_BUILTIN(&p->a, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(&p->a, 2); + gi = OBJECT_SIZE_BUILTIN(&p->a, 2); // CHECK: store i32 4 - gi = __builtin_object_size(&p->a, 3); + gi = OBJECT_SIZE_BUILTIN(&p->a, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(&p->t[5], 0); + gi = OBJECT_SIZE_BUILTIN(&p->t[5], 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(&p->t[5], 1); + gi = OBJECT_SIZE_BUILTIN(&p->t[5], 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(&p->t[5], 2); + gi = OBJECT_SIZE_BUILTIN(&p->t[5], 2); // CHECK: store i32 20 - gi = __builtin_object_size(&p->t[5], 3); + gi = OBJECT_SIZE_BUILTIN(&p->t[5], 3); } -// PR24493 -- ICE if __builtin_object_size called with NULL and (Type & 1) != 0 +// PR24493 -- ICE if OBJECT_SIZE_BUILTIN called with NULL and (Type & 1) != 0 // CHECK-LABEL: @test24 void test24() { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size((void*)0, 0); + gi = OBJECT_SIZE_BUILTIN((void*)0, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size((void*)0, 1); + gi = OBJECT_SIZE_BUILTIN((void*)0, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size((void*)0, 2); + gi = OBJECT_SIZE_BUILTIN((void*)0, 2); // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. // Hopefully will be lowered properly in the future. // CHECK: store i32 0 - gi = __builtin_object_size((void*)0, 3); + gi = OBJECT_SIZE_BUILTIN((void*)0, 3); } // CHECK-LABEL: @test25 void test25() { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size((void*)0x1000, 0); + gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size((void*)0x1000, 1); + gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size((void*)0x1000, 2); + gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 2); // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. // Hopefully will be lowered properly in the future. // CHECK: store i32 0 - gi = __builtin_object_size((void*)0x1000, 3); + gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size((void*)0 + 0x1000, 0); + gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size((void*)0 + 0x1000, 1); + gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size((void*)0 + 0x1000, 2); + gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 2); // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. // Hopefully will be lowered properly in the future. // CHECK: store i32 0 - gi = __builtin_object_size((void*)0 + 0x1000, 3); + gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 3); } // CHECK-LABEL: @test26 @@ -329,13 +336,13 @@ void test26() { struct { int v[10]; } t[10]; // CHECK: store i32 316 - gi = __builtin_object_size(&t[1].v[11], 0); + gi = OBJECT_SIZE_BUILTIN(&t[1].v[11], 0); // CHECK: store i32 312 - gi = __builtin_object_size(&t[1].v[12], 1); + gi = OBJECT_SIZE_BUILTIN(&t[1].v[12], 1); // CHECK: store i32 308 - gi = __builtin_object_size(&t[1].v[13], 2); + gi = OBJECT_SIZE_BUILTIN(&t[1].v[13], 2); // CHECK: store i32 0 - gi = __builtin_object_size(&t[1].v[14], 3); + gi = OBJECT_SIZE_BUILTIN(&t[1].v[14], 3); } struct Test27IncompleteTy; @@ -343,29 +350,29 @@ struct Test27IncompleteTy; // CHECK-LABEL: @test27 void test27(struct Test27IncompleteTy *t) { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(t, 0); + gi = OBJECT_SIZE_BUILTIN(t, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(t, 1); + gi = OBJECT_SIZE_BUILTIN(t, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(t, 2); + gi = OBJECT_SIZE_BUILTIN(t, 2); // Note: this is currently fixed at 0 because LLVM doesn't have sufficient // data to correctly handle type=3 // CHECK: store i32 0 - gi = __builtin_object_size(t, 3); + gi = OBJECT_SIZE_BUILTIN(t, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(&test27, 0); + gi = OBJECT_SIZE_BUILTIN(&test27, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(&test27, 1); + gi = OBJECT_SIZE_BUILTIN(&test27, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(&test27, 2); + gi = OBJECT_SIZE_BUILTIN(&test27, 2); // Note: this is currently fixed at 0 because LLVM doesn't have sufficient // data to correctly handle type=3 // CHECK: store i32 0 - gi = __builtin_object_size(&test27, 3); + gi = OBJECT_SIZE_BUILTIN(&test27, 3); } -// The intent of this test is to ensure that __builtin_object_size treats `&foo` +// The intent of this test is to ensure that OBJECT_SIZE_BUILTIN treats `&foo` // and `(T*)&foo` identically, when used as the pointer argument. // CHECK-LABEL: @test28 void test28() { @@ -373,22 +380,22 @@ void test28() { #define addCasts(s) ((char*)((short*)(s))) // CHECK: store i32 360 - gi = __builtin_object_size(addCasts(&t[1]), 0); + gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 0); // CHECK: store i32 360 - gi = __builtin_object_size(addCasts(&t[1]), 1); + gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 1); // CHECK: store i32 360 - gi = __builtin_object_size(addCasts(&t[1]), 2); + gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 2); // CHECK: store i32 360 - gi = __builtin_object_size(addCasts(&t[1]), 3); + gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 3); // CHECK: store i32 356 - gi = __builtin_object_size(addCasts(&t[1].v[1]), 0); + gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 0); // CHECK: store i32 36 - gi = __builtin_object_size(addCasts(&t[1].v[1]), 1); + gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 1); // CHECK: store i32 356 - gi = __builtin_object_size(addCasts(&t[1].v[1]), 2); + gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 2); // CHECK: store i32 36 - gi = __builtin_object_size(addCasts(&t[1].v[1]), 3); + gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 3); #undef addCasts } @@ -416,40 +423,40 @@ struct StaticStruct { void test29(struct DynStructVar *dv, struct DynStruct0 *d0, struct DynStruct1 *d1, struct StaticStruct *ss) { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(dv->snd, 0); + gi = OBJECT_SIZE_BUILTIN(dv->snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(dv->snd, 1); + gi = OBJECT_SIZE_BUILTIN(dv->snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(dv->snd, 2); + gi = OBJECT_SIZE_BUILTIN(dv->snd, 2); // CHECK: store i32 0 - gi = __builtin_object_size(dv->snd, 3); + gi = OBJECT_SIZE_BUILTIN(dv->snd, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(d0->snd, 0); + gi = OBJECT_SIZE_BUILTIN(d0->snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(d0->snd, 1); + gi = OBJECT_SIZE_BUILTIN(d0->snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(d0->snd, 2); + gi = OBJECT_SIZE_BUILTIN(d0->snd, 2); // CHECK: store i32 0 - gi = __builtin_object_size(d0->snd, 3); + gi = OBJECT_SIZE_BUILTIN(d0->snd, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(d1->snd, 0); + gi = OBJECT_SIZE_BUILTIN(d1->snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(d1->snd, 1); + gi = OBJECT_SIZE_BUILTIN(d1->snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(d1->snd, 2); + gi = OBJECT_SIZE_BUILTIN(d1->snd, 2); // CHECK: store i32 1 - gi = __builtin_object_size(d1->snd, 3); + gi = OBJECT_SIZE_BUILTIN(d1->snd, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(ss->snd, 0); + gi = OBJECT_SIZE_BUILTIN(ss->snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(ss->snd, 1); + gi = OBJECT_SIZE_BUILTIN(ss->snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(ss->snd, 2); + gi = OBJECT_SIZE_BUILTIN(ss->snd, 2); // CHECK: store i32 2 - gi = __builtin_object_size(ss->snd, 3); + gi = OBJECT_SIZE_BUILTIN(ss->snd, 3); } // CHECK-LABEL: @test30 @@ -457,41 +464,41 @@ void test30() { struct { struct DynStruct1 fst, snd; } *nested; // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(nested->fst.snd, 0); + gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 0); // CHECK: store i32 1 - gi = __builtin_object_size(nested->fst.snd, 1); + gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(nested->fst.snd, 2); + gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 2); // CHECK: store i32 1 - gi = __builtin_object_size(nested->fst.snd, 3); + gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(nested->snd.snd, 0); + gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(nested->snd.snd, 1); + gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(nested->snd.snd, 2); + gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 2); // CHECK: store i32 1 - gi = __builtin_object_size(nested->snd.snd, 3); + gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 3); union { struct DynStruct1 d1; char c[1]; } *u; // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(u->c, 0); + gi = OBJECT_SIZE_BUILTIN(u->c, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(u->c, 1); + gi = OBJECT_SIZE_BUILTIN(u->c, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(u->c, 2); + gi = OBJECT_SIZE_BUILTIN(u->c, 2); // CHECK: store i32 1 - gi = __builtin_object_size(u->c, 3); + gi = OBJECT_SIZE_BUILTIN(u->c, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(u->d1.snd, 0); + gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(u->d1.snd, 1); + gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(u->d1.snd, 2); + gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 2); // CHECK: store i32 1 - gi = __builtin_object_size(u->d1.snd, 3); + gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 3); } // CHECK-LABEL: @test31 @@ -503,19 +510,19 @@ void test31() { struct StaticStruct *ss; // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(ds1[9].snd, 1); + gi = OBJECT_SIZE_BUILTIN(ds1[9].snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(&ss[9].snd[0], 1); + gi = OBJECT_SIZE_BUILTIN(&ss[9].snd[0], 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(&ds1[9].snd[0], 1); + gi = OBJECT_SIZE_BUILTIN(&ds1[9].snd[0], 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(&ds0[9].snd[0], 1); + gi = OBJECT_SIZE_BUILTIN(&ds0[9].snd[0], 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(&dsv[9].snd[0], 1); + gi = OBJECT_SIZE_BUILTIN(&dsv[9].snd[0], 1); } // CHECK-LABEL: @PR30346 @@ -528,26 +535,26 @@ void PR30346() { struct sockaddr *sa; // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(sa->sa_data, 0); + gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 - gi = __builtin_object_size(sa->sa_data, 1); + gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 - gi = __builtin_object_size(sa->sa_data, 2); + gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 2); // CHECK: store i32 14 - gi = __builtin_object_size(sa->sa_data, 3); + gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 3); } extern char incomplete_char_array[]; // CHECK-LABEL: @incomplete_and_function_types int incomplete_and_function_types() { // CHECK: call i64 @llvm.objectsize.i64.p0i8 - gi = __builtin_object_size(incomplete_char_array, 0); + gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8 - gi = __builtin_object_size(incomplete_char_array, 1); + gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8 - gi = __builtin_object_size(incomplete_char_array, 2); + gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 2); // CHECK: store i32 0 - gi = __builtin_object_size(incomplete_char_array, 3); + gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 3); } // Flips between the pointer and lvalue evaluator a lot. @@ -564,7 +571,7 @@ void deeply_nested() { } *a; // CHECK: store i32 4 - gi = __builtin_object_size(&a->b[1].c[1].d[1].e[1], 1); + gi = OBJECT_SIZE_BUILTIN(&a->b[1].c[1].d[1].e[1], 1); // CHECK: store i32 4 - gi = __builtin_object_size(&a->b[1].c[1].d[1].e[1], 3); + gi = OBJECT_SIZE_BUILTIN(&a->b[1].c[1].d[1].e[1], 3); } diff --git a/clang/test/Sema/builtin-object-size.c b/clang/test/Sema/builtin-object-size.c index fcf86f3..ff87074 100644 --- a/clang/test/Sema/builtin-object-size.c +++ b/clang/test/Sema/builtin-object-size.c @@ -1,22 +1,29 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin9 -verify %s +// RUN: %clang_cc1 -DDYNAMIC -fsyntax-only -triple x86_64-apple-darwin9 -verify %s + +#ifndef DYNAMIC +#define OBJECT_SIZE_BUILTIN __builtin_object_size +#else +#define OBJECT_SIZE_BUILTIN __builtin_dynamic_object_size +#endif int a[10]; int f0() { - return __builtin_object_size(&a); // expected-error {{too few arguments to function}} + return OBJECT_SIZE_BUILTIN(&a); // expected-error {{too few arguments to function}} } int f1() { - return (__builtin_object_size(&a, 0) + - __builtin_object_size(&a, 1) + - __builtin_object_size(&a, 2) + - __builtin_object_size(&a, 3)); + return (OBJECT_SIZE_BUILTIN(&a, 0) + + OBJECT_SIZE_BUILTIN(&a, 1) + + OBJECT_SIZE_BUILTIN(&a, 2) + + OBJECT_SIZE_BUILTIN(&a, 3)); } int f2() { - return __builtin_object_size(&a, -1); // expected-error {{argument value -1 is outside the valid range [0, 3]}} + return OBJECT_SIZE_BUILTIN(&a, -1); // expected-error {{argument value -1 is outside the valid range [0, 3]}} } int f3() { - return __builtin_object_size(&a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + return OBJECT_SIZE_BUILTIN(&a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} } @@ -31,9 +38,9 @@ typedef __typeof__(sizeof(int)) size_t; void * memcset(void *restrict dst, int src, size_t n); void * memcpy(void *restrict dst, const void *restrict src, size_t n); -#define memset(dest, src, len) __builtin___memset_chk(dest, src, len, __builtin_object_size(dest, 0)) -#define memcpy(dest, src, len) __builtin___memcpy_chk(dest, src, len, __builtin_object_size(dest, 0)) -#define memcpy1(dest, src, len) __builtin___memcpy_chk(dest, src, len, __builtin_object_size(dest, 4)) +#define memset(dest, src, len) __builtin___memset_chk(dest, src, len, OBJECT_SIZE_BUILTIN(dest, 0)) +#define memcpy(dest, src, len) __builtin___memcpy_chk(dest, src, len, OBJECT_SIZE_BUILTIN(dest, 0)) +#define memcpy1(dest, src, len) __builtin___memcpy_chk(dest, src, len, OBJECT_SIZE_BUILTIN(dest, 4)) #define NULL ((void *)0) void f5(void) @@ -49,8 +56,8 @@ void f6(void) { char b[5]; char buf[10]; - __builtin___memccpy_chk (buf, b, '\0', sizeof(b), __builtin_object_size (buf, 0)); - __builtin___memccpy_chk (b, buf, '\0', sizeof(buf), __builtin_object_size (b, 0)); // expected-warning {{'__builtin___memccpy_chk' will always overflow; destination buffer has size 5, but size argument is 10}} + __builtin___memccpy_chk (buf, b, '\0', sizeof(b), OBJECT_SIZE_BUILTIN (buf, 0)); + __builtin___memccpy_chk (b, buf, '\0', sizeof(buf), OBJECT_SIZE_BUILTIN (b, 0)); // expected-warning {{'__builtin___memccpy_chk' will always overflow; destination buffer has size 5, but size argument is 10}} } int pr28314(void) { @@ -70,10 +77,10 @@ int pr28314(void) { } *p3; int a = 0; - a += __builtin_object_size(&p->a, 0); - a += __builtin_object_size(p->b, 0); - a += __builtin_object_size(p2->b, 0); - a += __builtin_object_size(p3->b, 0); + a += OBJECT_SIZE_BUILTIN(&p->a, 0); + a += OBJECT_SIZE_BUILTIN(p->b, 0); + a += OBJECT_SIZE_BUILTIN(p2->b, 0); + a += OBJECT_SIZE_BUILTIN(p3->b, 0); return a; } @@ -82,12 +89,12 @@ int pr31843() { struct { int f; } a; int b; - n += __builtin_object_size(({&(b ? &a : &a)->f; pr31843;}), 0); // expected-warning{{expression result unused}} + n += OBJECT_SIZE_BUILTIN(({&(b ? &a : &a)->f; pr31843;}), 0); // expected-warning{{expression result unused}} struct statfs { char f_mntonname[1024];}; struct statfs *outStatFSBuf; - n += __builtin_object_size(outStatFSBuf->f_mntonname ? "" : "", 1); // expected-warning{{address of array}} - n += __builtin_object_size(outStatFSBuf->f_mntonname ?: "", 1); + n += OBJECT_SIZE_BUILTIN(outStatFSBuf->f_mntonname ? "" : "", 1); // expected-warning{{address of array}} + n += OBJECT_SIZE_BUILTIN(outStatFSBuf->f_mntonname ?: "", 1); return n; } @@ -104,7 +111,7 @@ typedef struct { void rd36094951_IAS_builtin_object_size_assertion(IncompleteArrayStruct *p) { #define rd36094951_CHECK(mode) \ __builtin___strlcpy_chk(p->session[0].string, "ab", 2, \ - __builtin_object_size(p->session[0].string, mode)) + OBJECT_SIZE_BUILTIN(p->session[0].string, mode)) rd36094951_CHECK(0); rd36094951_CHECK(1); rd36094951_CHECK(2); -- 2.7.4