mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-20 20:15:49 -04:00

Because references must be initialized using some evaluated expression, they must point to something, and a callee can assume the reference parameter is dereferenceable. Taking advantage of a new attribute just added to LLVM, mark them as such. Because dereferenceability in addrspace(0) implies nonnull in the backend, we don't need both attributes. However, we need to know the size of the object to use the dereferenceable attribute, so for incomplete types we still emit only nonnull. llvm-svn: 213386
151 lines
3.8 KiB
C++
151 lines
3.8 KiB
C++
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
|
|
// rdar: // 8353567
|
|
// pr7726
|
|
|
|
extern "C" int printf(...);
|
|
|
|
void test0() {
|
|
// CHECK: call i32 (...)* @printf({{.*}}, i8* inttoptr (i64 3735928559 to i8*))
|
|
printf("%p\n", (void *)0xdeadbeef ? : (void *)0xaaaaaa);
|
|
}
|
|
|
|
// rdar://8446940
|
|
namespace radar8446940 {
|
|
extern "C" void abort();
|
|
|
|
int main () {
|
|
char x[1];
|
|
char *y = x ? : 0;
|
|
|
|
if (x != y)
|
|
abort();
|
|
}
|
|
}
|
|
|
|
namespace radar8453812 {
|
|
extern "C" void abort();
|
|
_Complex int getComplex(_Complex int val) {
|
|
static int count;
|
|
if (count++)
|
|
abort();
|
|
return val;
|
|
}
|
|
|
|
_Complex int cmplx() {
|
|
_Complex int cond;
|
|
_Complex int rhs;
|
|
|
|
return getComplex(1+2i) ? : rhs;
|
|
}
|
|
|
|
// lvalue test
|
|
void foo (int& lv) {
|
|
++lv;
|
|
}
|
|
|
|
int global = 1;
|
|
|
|
int &cond() {
|
|
static int count;
|
|
if (count++)
|
|
abort();
|
|
return global;
|
|
}
|
|
|
|
|
|
int main() {
|
|
cmplx();
|
|
int rhs = 10;
|
|
foo (cond()? : rhs);
|
|
return global-2;
|
|
}
|
|
}
|
|
|
|
namespace test3 {
|
|
struct A {
|
|
A();
|
|
A(const A&);
|
|
~A();
|
|
};
|
|
|
|
struct B {
|
|
B();
|
|
B(const B&);
|
|
~B();
|
|
operator bool();
|
|
operator A();
|
|
};
|
|
|
|
B test0(B &x) {
|
|
// CHECK-LABEL: define void @_ZN5test35test0ERNS_1BE(
|
|
// CHECK: [[X:%.*]] = alloca [[B:%.*]]*,
|
|
// CHECK-NEXT: store [[B]]* {{%.*}}, [[B]]** [[X]]
|
|
// CHECK-NEXT: [[T0:%.*]] = load [[B]]** [[X]]
|
|
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[T0]])
|
|
// CHECK-NEXT: br i1 [[BOOL]]
|
|
// CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* dereferenceable({{[0-9]+}}) [[T0]])
|
|
// CHECK-NEXT: br label
|
|
// CHECK: call void @_ZN5test31BC1Ev([[B]]* [[RESULT]])
|
|
// CHECK-NEXT: br label
|
|
// CHECK: ret void
|
|
return x ?: B();
|
|
}
|
|
|
|
B test1() {
|
|
// CHECK-LABEL: define void @_ZN5test35test1Ev(
|
|
// CHECK: [[TEMP:%.*]] = alloca [[B]],
|
|
// CHECK-NEXT: call void @_ZN5test312test1_helperEv([[B]]* sret [[TEMP]])
|
|
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]])
|
|
// CHECK-NEXT: br i1 [[BOOL]]
|
|
// CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* dereferenceable({{[0-9]+}}) [[TEMP]])
|
|
// CHECK-NEXT: br label
|
|
// CHECK: call void @_ZN5test31BC1Ev([[B]]* [[RESULT]])
|
|
// CHECK-NEXT: br label
|
|
// CHECK: call void @_ZN5test31BD1Ev([[B]]* [[TEMP]])
|
|
// CHECK-NEXT: ret void
|
|
extern B test1_helper();
|
|
return test1_helper() ?: B();
|
|
}
|
|
|
|
|
|
A test2(B &x) {
|
|
// CHECK-LABEL: define void @_ZN5test35test2ERNS_1BE(
|
|
// CHECK: [[X:%.*]] = alloca [[B]]*,
|
|
// CHECK-NEXT: store [[B]]* {{%.*}}, [[B]]** [[X]]
|
|
// CHECK-NEXT: [[T0:%.*]] = load [[B]]** [[X]]
|
|
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[T0]])
|
|
// CHECK-NEXT: br i1 [[BOOL]]
|
|
// CHECK: call void @_ZN5test31BcvNS_1AEEv([[A:%.*]]* sret [[RESULT:%.*]], [[B]]* [[T0]])
|
|
// CHECK-NEXT: br label
|
|
// CHECK: call void @_ZN5test31AC1Ev([[A]]* [[RESULT]])
|
|
// CHECK-NEXT: br label
|
|
// CHECK: ret void
|
|
return x ?: A();
|
|
}
|
|
|
|
A test3() {
|
|
// CHECK-LABEL: define void @_ZN5test35test3Ev(
|
|
// CHECK: [[TEMP:%.*]] = alloca [[B]],
|
|
// CHECK-NEXT: call void @_ZN5test312test3_helperEv([[B]]* sret [[TEMP]])
|
|
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]])
|
|
// CHECK-NEXT: br i1 [[BOOL]]
|
|
// CHECK: call void @_ZN5test31BcvNS_1AEEv([[A]]* sret [[RESULT:%.*]], [[B]]* [[TEMP]])
|
|
// CHECK-NEXT: br label
|
|
// CHECK: call void @_ZN5test31AC1Ev([[A]]* [[RESULT]])
|
|
// CHECK-NEXT: br label
|
|
// CHECK: call void @_ZN5test31BD1Ev([[B]]* [[TEMP]])
|
|
// CHECK-NEXT: ret void
|
|
extern B test3_helper();
|
|
return test3_helper() ?: A();
|
|
}
|
|
|
|
}
|
|
|
|
namespace test4 {
|
|
// Make sure this doesn't crash.
|
|
void f() {
|
|
const int a = 10, b = 20;
|
|
const int *c = &(a ?: b);
|
|
}
|
|
}
|