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.
// 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")
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 =
NoReturn = true;
if (FD->hasAttr<NoThrowAttr>())
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;
}
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);
}
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<DeclRefExpr>(E->IgnoreParenImpCasts())) {
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});
}
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();
// 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));
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.
/// 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
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();
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
-// 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)
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 {
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
// 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
// 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
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
// 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)));
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)));
// 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);
}
-// 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];
// 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");
}
// 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
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
} 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
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
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
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]; };
// 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
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;
// 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() {
#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
}
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
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
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
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.
} *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);
}
// 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]}}
}
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)
{
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) {
} *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;
}
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;
}
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);