Index: cfe/trunk/docs/LanguageExtensions.rst =================================================================== --- cfe/trunk/docs/LanguageExtensions.rst +++ cfe/trunk/docs/LanguageExtensions.rst @@ -2922,3 +2922,29 @@ 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. Index: cfe/trunk/include/clang/Basic/Builtins.def =================================================================== --- cfe/trunk/include/clang/Basic/Builtins.def +++ cfe/trunk/include/clang/Basic/Builtins.def @@ -511,6 +511,7 @@ // 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") Index: cfe/trunk/lib/AST/ExprConstant.cpp =================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp +++ cfe/trunk/lib/AST/ExprConstant.cpp @@ -8190,6 +8190,7 @@ 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 = Index: cfe/trunk/lib/Analysis/CFG.cpp =================================================================== --- cfe/trunk/lib/Analysis/CFG.cpp +++ cfe/trunk/lib/Analysis/CFG.cpp @@ -2458,7 +2458,8 @@ 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; } Index: cfe/trunk/lib/CodeGen/CGBuiltin.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp @@ -494,10 +494,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ // 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)); Index: cfe/trunk/lib/CodeGen/CGCall.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGCall.cpp +++ cfe/trunk/lib/CodeGen/CGCall.cpp @@ -3459,7 +3459,8 @@ 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. Index: cfe/trunk/lib/CodeGen/CodeGenFunction.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h @@ -4177,14 +4177,16 @@ /// 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 Index: cfe/trunk/lib/Sema/SemaChecking.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp +++ cfe/trunk/lib/Sema/SemaChecking.cpp @@ -1076,6 +1076,7 @@ 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(); Index: cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -95,6 +95,7 @@ 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 Index: cfe/trunk/test/CodeGen/alloc-size.c =================================================================== --- cfe/trunk/test/CodeGen/alloc-size.c +++ cfe/trunk/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 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 @@ 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 @@ // 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 @@ // 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 @@ 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 @@ // 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 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 @@ // 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); } Index: cfe/trunk/test/CodeGen/object-size.c =================================================================== --- cfe/trunk/test/CodeGen/object-size.c +++ cfe/trunk/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 @@ // 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 @@ // 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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 @@ // 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } *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); } Index: cfe/trunk/test/Sema/builtin-object-size.c =================================================================== --- cfe/trunk/test/Sema/builtin-object-size.c +++ cfe/trunk/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 @@ 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 @@ { 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 @@ } *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 @@ 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 @@ 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);