Revert "Revert "Temporarily do not drop volatile stores before unreachable""

This reverts commit 52aeacfbf5.
There isn't full agreement on a path forward yet, but there is agreement that
this shouldn't land as-is.  See discussion on https://reviews.llvm.org/D105338

Also reverts unreviewed "[clang] Improve `-Wnull-dereference` diag to be more in-line with reality"
This reverts commit f4877c78c0.

And all the related changes to tests:
This reverts commit 9a0152799f.
This reverts commit 3f7c9cc274.
This reverts commit 329f8197ef.
This reverts commit aa9f58cc2c.
This reverts commit 2df37d5ddd.
This reverts commit a72a441812.
This commit is contained in:
Nico Weber 2021-07-09 11:39:40 -04:00
parent 5035e7be1a
commit 97c675d3d4
38 changed files with 222 additions and 172 deletions

View file

@ -6744,13 +6744,13 @@ def ext_typecheck_indirection_through_void_pointer : ExtWarn<
"ISO C++ does not allow indirection on operand of type %0">, "ISO C++ does not allow indirection on operand of type %0">,
InGroup<DiagGroup<"void-ptr-dereference">>; InGroup<DiagGroup<"void-ptr-dereference">>;
def warn_indirection_through_null : Warning< def warn_indirection_through_null : Warning<
"indirection of null pointer will be deleted, not trap">, "indirection of non-volatile null pointer will be deleted, not trap">,
InGroup<NullDereference>; InGroup<NullDereference>;
def warn_binding_null_to_reference : Warning< def warn_binding_null_to_reference : Warning<
"binding dereferenced null pointer to reference has undefined behavior">, "binding dereferenced null pointer to reference has undefined behavior">,
InGroup<NullDereference>; InGroup<NullDereference>;
def note_indirection_through_null : Note< def note_indirection_through_null : Note<
"consider using __builtin_trap()">; "consider using __builtin_trap() or qualifying pointer with 'volatile'">;
def warn_pointer_indirection_from_incompatible_type : Warning< def warn_pointer_indirection_from_incompatible_type : Warning<
"dereference of type %1 that was reinterpret_cast from type %0 has undefined " "dereference of type %1 that was reinterpret_cast from type %0 has undefined "
"behavior">, "behavior">,

View file

@ -533,16 +533,21 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
} }
static void CheckForNullPointerDereference(Sema &S, Expr *E) { static void CheckForNullPointerDereference(Sema &S, Expr *E) {
// Check to see if we are dereferencing a null pointer. // Check to see if we are dereferencing a null pointer. If so,
// If so, this is undefined behavior that the optimizer will delete, // and if not volatile-qualified, this is undefined behavior that the
// so warn about it. People sometimes try to use this to get a deterministic // optimizer will delete, so warn about it. People sometimes try to use this
// trap and are surprised by clang's behavior. This only handles the pattern // to get a deterministic trap and are surprised by clang's behavior. This
// "*null", which is a very syntactic check. // only handles the pattern "*null", which is a very syntactic check.
const auto *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts()); const auto *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts());
if (UO && UO->getOpcode() == UO_Deref && if (UO && UO->getOpcode() == UO_Deref &&
UO->getSubExpr()->getType()->isPointerType()) { UO->getSubExpr()->getType()->isPointerType()) {
if (UO->getSubExpr()->IgnoreParenCasts()->isNullPointerConstant( const LangAS AS =
S.Context, Expr::NPC_ValueDependentIsNotNull)) { UO->getSubExpr()->getType()->getPointeeType().getAddressSpace();
if ((!isTargetAddressSpace(AS) ||
(isTargetAddressSpace(AS) && toTargetAddressSpace(AS) == 0)) &&
UO->getSubExpr()->IgnoreParenCasts()->isNullPointerConstant(
S.Context, Expr::NPC_ValueDependentIsNotNull) &&
!UO->getType().isVolatileQualified()) {
S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
S.PDiag(diag::warn_indirection_through_null) S.PDiag(diag::warn_indirection_through_null)
<< UO->getSubExpr()->getSourceRange()); << UO->getSubExpr()->getSourceRange());

View file

@ -83,7 +83,7 @@ void testGlobalPointerPlacementNew() {
//----- Other cases //----- Other cases
void testNewMemoryIsInHeap() { void testNewMemoryIsInHeap() {
int *p = new int; int *p = new int;
if (global != p) // condition is always true as 'p' wraps a heap region that if (global != p) // condition is always true as 'p' wraps a heap region that
// is different from a region wrapped by 'global' // is different from a region wrapped by 'global'
global = p; // pointer escapes global = p; // pointer escapes
} }
@ -263,13 +263,13 @@ void testUninitFree() {
void testUninitDeleteSink() { void testUninitDeleteSink() {
int *x; int *x;
delete x; // expected-warning{{Argument to 'delete' is uninitialized}} delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
(*(volatile int *)0 = 1); // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} (*(volatile int *)0 = 1); // no warn
} }
void testUninitDeleteArraySink() { void testUninitDeleteArraySink() {
int *x; int *x;
delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}} delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
(*(volatile int *)0 = 1); // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} (*(volatile int *)0 = 1); // no warn
} }
namespace reference_count { namespace reference_count {

View file

@ -59,7 +59,7 @@ void testDiagnosableBranch(int a) {
if (a) { if (a) {
// expected-note@-1 {{Assuming 'a' is not equal to 0}} // expected-note@-1 {{Assuming 'a' is not equal to 0}}
// expected-note@-2 {{Taking true branch}} // expected-note@-2 {{Taking true branch}}
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning{{Dereference of null pointer}}
// expected-note@-1 {{Dereference of null pointer}} // expected-note@-1 {{Dereference of null pointer}}
} }
} }
@ -70,7 +70,7 @@ void testDiagnosableBranchLogical(int a, int b) {
// expected-note@-2 {{Left side of '&&' is true}} // expected-note@-2 {{Left side of '&&' is true}}
// expected-note@-3 {{Assuming 'b' is not equal to 0}} // expected-note@-3 {{Assuming 'b' is not equal to 0}}
// expected-note@-4 {{Taking true branch}} // expected-note@-4 {{Taking true branch}}
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning{{Dereference of null pointer}}
// expected-note@-1 {{Dereference of null pointer}} // expected-note@-1 {{Dereference of null pointer}}
} }
} }
@ -79,7 +79,7 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
if (a - b) { if (a - b) {
// expected-note@-1 {{Taking true branch}} // expected-note@-1 {{Taking true branch}}
// expected-note@-2 {{Assuming the condition is true}} // expected-note@-2 {{Assuming the condition is true}}
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning{{Dereference of null pointer}}
// expected-note@-1 {{Dereference of null pointer}} // expected-note@-1 {{Dereference of null pointer}}
} }
} }

View file

@ -9,13 +9,13 @@ void testLoop() {
work(); work();
work(); work();
if (y == 2) if (y == 2)
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
work(); work();
work(); work();
(void)y; (void)y;
} }
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *(volatile int *)0 = 1; // no-warning
} }
class MagicVector { class MagicVector {
@ -30,7 +30,7 @@ public:
MagicVector get(bool fail = false) { MagicVector get(bool fail = false) {
if (fail) if (fail)
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
return MagicVector{}; return MagicVector{};
} }
@ -39,13 +39,13 @@ void testLoopOpaqueCollection() {
work(); work();
work(); work();
if (y == 2) if (y == 2)
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
work(); work();
work(); work();
(void)y; (void)y;
} }
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
} }
@ -74,13 +74,13 @@ void testLoopOpaqueIterator() {
work(); work();
work(); work();
if (y == 2) if (y == 2)
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
work(); work();
work(); work();
(void)y; (void)y;
} }
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
} }
@ -89,13 +89,13 @@ void testLoopErrorInRange() {
work(); work();
work(); work();
if (y == 2) if (y == 2)
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *(volatile int *)0 = 1; // no-warning
work(); work();
work(); work();
(void)y; (void)y;
} }
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *(volatile int *)0 = 1; // no-warning
} }
void testForRangeInit() { void testForRangeInit() {

View file

@ -16,5 +16,6 @@ void test() {
// expected-note@-3 {{Returning from 'helper'}} // expected-note@-3 {{Returning from 'helper'}}
#endif #endif
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} expected-note {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
// expected-note@-1 {{Dereference of null pointer}}
} }

View file

@ -278,7 +278,7 @@ namespace PR17746 {
class Inner { class Inner {
public: public:
~Inner() { ~Inner() {
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
// expected-note@-1 {{Dereference of null pointer}} // expected-note@-1 {{Dereference of null pointer}}
} }
}; };

View file

@ -119,7 +119,7 @@ void rdar9424882() {
id x = [NSObject alloc]; // expected-warning {{Value stored to 'x' during its initialization is never read}} id x = [NSObject alloc]; // expected-warning {{Value stored to 'x' during its initialization is never read}}
} }
// Test // Test
typedef const void *CFTypeRef; typedef const void *CFTypeRef;
typedef const struct __CFString *CFStringRef; typedef const struct __CFString *CFStringRef;
@ -208,7 +208,7 @@ void dispatch_set_context(dispatch_object_t object, const void *context);
void rdar11059275(dispatch_object_t object) { void rdar11059275(dispatch_object_t object) {
NSObject *o = [[NSObject alloc] init]; NSObject *o = [[NSObject alloc] init];
dispatch_set_context(object, CFBridgingRetain(o)); // no-warning dispatch_set_context(object, CFBridgingRetain(o)); // no-warning
} }
void rdar11059275_positive() { void rdar11059275_positive() {
NSObject *o = [[NSObject alloc] init]; // expected-warning {{leak}} NSObject *o = [[NSObject alloc] init]; // expected-warning {{leak}}
@ -227,7 +227,7 @@ id rdar14061675() {
// ARC produces an implicit cast here. We need to make sure the combination // ARC produces an implicit cast here. We need to make sure the combination
// of that and the inlined call don't produce a spurious edge cycle. // of that and the inlined call don't produce a spurious edge cycle.
id result = rdar14061675_helper(); id result = rdar14061675_helper();
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} expected-warning {{Dereference of null pointer}} *(volatile int *)0 = 1; // expected-warning{{Dereference of null pointer}}
return result; return result;
} }

View file

@ -86,7 +86,7 @@ void testNonNil(id a, id b) {
if (b != nil) if (b != nil)
return; return;
for (id x in b) for (id x in b)
*(volatile int *)0 = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *(volatile int *)0 = 1; // no-warning
clang_analyzer_eval(b != nil); // expected-warning{{FALSE}} clang_analyzer_eval(b != nil); // expected-warning{{FALSE}}
} }

View file

@ -338,7 +338,7 @@ void constraintManagerShouldTreatAsOpaque(int rhs) {
if (i < rhs) if (i < rhs)
return; return;
if (i < rhs) if (i < rhs)
*(volatile int *)0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *(volatile int *) 0; // no-warning
} }

View file

@ -145,7 +145,7 @@ void is_sink(int fst, ...) {
va_list va; va_list va;
va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}} va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}}
// expected-note@-1{{va_end() is called on an uninitialized va_list}} // expected-note@-1{{va_end() is called on an uninitialized va_list}}
*((volatile int *)0) = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *((volatile int *)0) = 1;
} }
// NOTE: this is invalid, as the man page of va_end requires that "Each invocation of va_start() // NOTE: this is invalid, as the man page of va_end requires that "Each invocation of va_start()

View file

@ -3,10 +3,11 @@
// This is initially assumed convergent, but can be deduced to not require it. // This is initially assumed convergent, but can be deduced to not require it.
// CHECK-LABEL: define{{.*}} spir_func void @non_convfun(i32* %p) local_unnamed_addr #0 // CHECK-LABEL: define{{.*}} spir_func void @non_convfun() local_unnamed_addr #0
// CHECK: ret void // CHECK: ret void
__attribute__((noinline)) __attribute__((noinline))
void non_convfun(volatile int* p) { void non_convfun(void) {
volatile int* p;
*p = 0; *p = 0;
} }
@ -27,29 +28,29 @@ void g(void);
// non_convfun(); // non_convfun();
// } // }
// //
// CHECK-LABEL: define{{.*}} spir_func void @test_merge_if(i32 %a, i32* %p) local_unnamed_addr #1 { // CHECK-LABEL: define{{.*}} spir_func void @test_merge_if(i32 %a) local_unnamed_addr #1 {
// CHECK: %[[tobool:.+]] = icmp eq i32 %a, 0 // CHECK: %[[tobool:.+]] = icmp eq i32 %a, 0
// CHECK: br i1 %[[tobool]], label %[[if_end3_critedge:.+]], label %[[if_then:.+]] // CHECK: br i1 %[[tobool]], label %[[if_end3_critedge:.+]], label %[[if_then:.+]]
// CHECK: [[if_then]]: // CHECK: [[if_then]]:
// CHECK: tail call spir_func void @f() // CHECK: tail call spir_func void @f()
// CHECK: tail call spir_func void @non_convfun(i32* %p) // CHECK: tail call spir_func void @non_convfun()
// CHECK: tail call spir_func void @g() // CHECK: tail call spir_func void @g()
// CHECK: br label %[[if_end3:.+]] // CHECK: br label %[[if_end3:.+]]
// CHECK: [[if_end3_critedge]]: // CHECK: [[if_end3_critedge]]:
// CHECK: tail call spir_func void @non_convfun(i32* %p) // CHECK: tail call spir_func void @non_convfun()
// CHECK: br label %[[if_end3]] // CHECK: br label %[[if_end3]]
// CHECK: [[if_end3]]: // CHECK: [[if_end3]]:
// CHECK: ret void // CHECK: ret void
void test_merge_if(int a, volatile int* p) { void test_merge_if(int a) {
if (a) { if (a) {
f(); f();
} }
non_convfun(p); non_convfun();
if (a) { if (a) {
g(); g();
} }

View file

@ -39,13 +39,14 @@ void test_sizeof(){
// PR3418 // PR3418
int test_leading_extension() { int test_leading_extension() {
__extension__(*(char *)0) = 1; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} __extension__ (*(char*)0) = 1; // expected-warning {{indirection of non-volatile null pointer}} \
// expected-note {{consider using __builtin_trap}}
return 0; return 0;
} }
// PR3972 // PR3972
int test5(int); int test5(int);
int test6(void) { int test6(void) {
return test5( // expected-note {{to match}} return test5( // expected-note {{to match}}
test5(1) test5(1)
; // expected-error {{expected ')'}} ; // expected-error {{expected ')'}}

View file

@ -22,7 +22,7 @@ void radar9171946() {
int test_pr8876() { int test_pr8876() {
PR8876(0); // no-warning PR8876(0); // no-warning
PR8876_pos(0); // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} PR8876_pos(0); // expected-warning{{indirection of non-volatile null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap() or qualifying pointer with 'volatile'}}
return 0; return 0;
} }
@ -31,7 +31,7 @@ int test_pr8876() {
void pr8183(unsigned long long test) void pr8183(unsigned long long test)
{ {
(void)((((void*)0)) && (*((unsigned long long*)(((void*)0))) = ((unsigned long long)((test)) % (unsigned long long)((1000000000))))); // no-warning (void)((((void*)0)) && (*((unsigned long long*)(((void*)0))) = ((unsigned long long)((test)) % (unsigned long long)((1000000000))))); // no-warning
(*((unsigned long long *)(((void *)0))) = ((unsigned long long)((test)) % (unsigned long long)((1000000000)))); // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} (*((unsigned long long*)(((void*)0))) = ((unsigned long long)((test)) % (unsigned long long)((1000000000)))); // expected-warning {{indirection of non-volatile null pointer will be deleted, not trap}} expected-note {{consider using __builtin_trap() or qualifying pointer with 'volatile'}}
} }
// PR1966 // PR1966
@ -59,7 +59,7 @@ void test4() {
var =+5; // no warning when the subexpr of the unary op has no space before it. var =+5; // no warning when the subexpr of the unary op has no space before it.
var =-5; var =-5;
#define FIVE 5 #define FIVE 5
var=-FIVE; // no warning with macros. var=-FIVE; // no warning with macros.
var=-FIVE; var=-FIVE;
@ -159,7 +159,7 @@ void test17(int x) {
x = x % 0; // expected-warning {{remainder by zero is undefined}} x = x % 0; // expected-warning {{remainder by zero is undefined}}
x /= 0; // expected-warning {{division by zero is undefined}} x /= 0; // expected-warning {{division by zero is undefined}}
x %= 0; // expected-warning {{remainder by zero is undefined}} x %= 0; // expected-warning {{remainder by zero is undefined}}
x = sizeof(x/0); // no warning. x = sizeof(x/0); // no warning.
} }
@ -187,17 +187,21 @@ void test18(int b) {
typedef int __attribute__((address_space(256))) int_AS256; typedef int __attribute__((address_space(256))) int_AS256;
// PR7569 // PR7569
void test19() { void test19() {
*(int *)0 = 0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *(int *)0 = 0; // expected-warning {{indirection of non-volatile null pointer}} \
*(volatile int *)0 = 0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} // expected-note {{consider using __builtin_trap}}
*(int __attribute__((address_space(256))) *)0 = 0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *(volatile int *)0 = 0; // Ok.
*(int __attribute__((address_space(0))) *)0 = 0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *(int __attribute__((address_space(256))) *)0 = 0; // Ok.
*(int_AS256 *)0 = 0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} *(int __attribute__((address_space(0))) *)0 = 0; // expected-warning {{indirection of non-volatile null pointer}} \
// expected-note {{consider using __builtin_trap}}
*(int_AS256 *)0 = 0; // Ok.
// rdar://9269271 // rdar://9269271
int x = *(int *)0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} int x = *(int *)0; // expected-warning {{indirection of non-volatile null pointer}} \
int x2 = *(volatile int *)0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} // expected-note {{consider using __builtin_trap}}
int x3 = *(int __attribute__((address_space(0))) *)0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} int x2 = *(volatile int *)0; // Ok.
int x4 = *(int_AS256 *)0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} int x3 = *(int __attribute__((address_space(0))) *)0; // expected-warning {{indirection of non-volatile null pointer}} \
// expected-note {{consider using __builtin_trap}}
int x4 = *(int_AS256 *)0; // Ok.
int *p = &(*(int *)0); // Ok. int *p = &(*(int *)0); // Ok.
int_AS256 *p1 = &(*(int __attribute__((address_space(256))) *)0); // Ok. int_AS256 *p1 = &(*(int __attribute__((address_space(256))) *)0); // Ok.
int __attribute__((address_space(0))) *p2 = &(*(int __attribute__((address_space(0))) *)0); // Ok. int __attribute__((address_space(0))) *p2 = &(*(int __attribute__((address_space(0))) *)0); // Ok.
@ -209,7 +213,7 @@ int test20(int x) {
// expected-note {{remove constant to silence this warning}} // expected-note {{remove constant to silence this warning}}
return x && sizeof(int) == 4; // no warning, RHS is logical op. return x && sizeof(int) == 4; // no warning, RHS is logical op.
// no warning, this is an idiom for "true" in old C style. // no warning, this is an idiom for "true" in old C style.
return x && (signed char)1; return x && (signed char)1;

View file

@ -5,9 +5,10 @@
typedef struct P { int i; float f; } PT; typedef struct P { int i; float f; } PT;
struct external_sun3_core struct external_sun3_core
{ {
unsigned c_regs; unsigned c_regs;
PT X[100]; PT X[100];
}; };
void swap() void swap()
@ -15,30 +16,24 @@ void swap()
int x; int x;
x = offsetof(struct external_sun3_core, c_regs); x = offsetof(struct external_sun3_core, c_regs);
x = __builtin_offsetof(struct external_sun3_core, X[42].f); x = __builtin_offsetof(struct external_sun3_core, X[42].f);
x = __builtin_offsetof(struct external_sun3_core, X[42].f2); // expected-error {{no member named 'f2'}} x = __builtin_offsetof(struct external_sun3_core, X[42].f2); // expected-error {{no member named 'f2'}}
x = __builtin_offsetof(int, X[42].f2); // expected-error {{offsetof requires struct}} x = __builtin_offsetof(int, X[42].f2); // expected-error {{offsetof requires struct}}
int a[__builtin_offsetof(struct external_sun3_core, X) == 4 ? 1 : -1]; int a[__builtin_offsetof(struct external_sun3_core, X) == 4 ? 1 : -1];
int b[__builtin_offsetof(struct external_sun3_core, X[42]) == 340 ? 1 : -1]; int b[__builtin_offsetof(struct external_sun3_core, X[42]) == 340 ? 1 : -1];
int c[__builtin_offsetof(struct external_sun3_core, X[42].f2) == 344 ? 1 : -1]; // expected-error {{no member named 'f2'}} int c[__builtin_offsetof(struct external_sun3_core, X[42].f2) == 344 ? 1 : -1]; // expected-error {{no member named 'f2'}}
} }
extern int f(); extern int f();
struct s1 { struct s1 { int a; };
int a;
};
int v1 = offsetof (struct s1, a) == 0 ? 0 : f(); int v1 = offsetof (struct s1, a) == 0 ? 0 : f();
struct s2 { struct s2 { int a; };
int a;
};
int v2 = (int)(&((struct s2 *) 0)->a) == 0 ? 0 : f(); int v2 = (int)(&((struct s2 *) 0)->a) == 0 ? 0 : f();
struct s3 { struct s3 { int a; };
int a;
};
int v3 = __builtin_offsetof(struct s3, a) == 0 ? 0 : f(); int v3 = __builtin_offsetof(struct s3, a) == 0 ? 0 : f();
// PR3396 // PR3396
@ -72,6 +67,6 @@ typedef struct Array { int array[1]; } Array;
int test4 = __builtin_offsetof(Array, array); int test4 = __builtin_offsetof(Array, array);
int test5() { int test5() {
return __builtin_offsetof(Array, array[*(int *)0]); // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
} }

View file

@ -47,7 +47,7 @@ void f() {
// Conversion to member of base. // Conversion to member of base.
pdi1 = pdid; // expected-error {{assigning to 'int A::*' from incompatible type 'int D::*'}} pdi1 = pdid; // expected-error {{assigning to 'int A::*' from incompatible type 'int D::*'}}
// Comparisons // Comparisons
int (A::*pf2)(int, int); int (A::*pf2)(int, int);
int (D::*pf3)(int, int) = 0; int (D::*pf3)(int, int) = 0;
@ -106,7 +106,7 @@ void h() {
int i = phm->*pi; int i = phm->*pi;
(void)&(hm.*pi); (void)&(hm.*pi);
(void)&(phm->*pi); (void)&(phm->*pi);
(void)&((&hm)->*pi); (void)&((&hm)->*pi);
void (HasMembers::*pf)() = &HasMembers::f; void (HasMembers::*pf)() = &HasMembers::f;
(hm.*pf)(); (hm.*pf)();
@ -204,7 +204,7 @@ namespace rdar8358512 {
static void stat(); static void stat();
static void stat(int); static void stat(int);
template <typename T> struct Test0 { template <typename T> struct Test0 {
void test() { void test() {
bind(&nonstat); // expected-error {{no matching function for call}} bind(&nonstat); // expected-error {{no matching function for call}}
@ -295,8 +295,8 @@ namespace PR9973 {
{ call(u); } // expected-note{{in instantiation of}} { call(u); } // expected-note{{in instantiation of}}
}; };
template <class R, class T> template<class R, class T>
dm<R, T> mem_fn(R T::*); dm<R, T> mem_fn(R T::*) ;
struct test struct test
{ int nullary_v(); }; { int nullary_v(); };
@ -312,13 +312,14 @@ namespace test8 {
struct A { int foo; }; struct A { int foo; };
int test1() { int test1() {
// Verify that we perform (and check) an lvalue conversion on the operands here. // Verify that we perform (and check) an lvalue conversion on the operands here.
return (*((A **)0)) // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} return (*((A**) 0)) // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
->**(int A::**)0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} ->**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
} }
int test2() { int test2() {
// Verify that we perform (and check) an lvalue conversion on the operands here. // Verify that we perform (and check) an lvalue conversion on the operands here.
// TODO: the .* should itself warn about being a dereference of null. // TODO: the .* should itself warn about being a dereference of null.
return (*((A *)0)).**(int A::**)0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} return (*((A*) 0))
.**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
} }
} }

View file

@ -12,7 +12,7 @@
static void __declspec(noinline) CrashOnProcessDetach() { static void __declspec(noinline) CrashOnProcessDetach() {
printf("CrashOnProcessDetach\n"); printf("CrashOnProcessDetach\n");
fflush(stdout); fflush(stdout);
__builtin_trap(); *static_cast<volatile int *>(0) = 0x356;
} }
bool g_is_child = false; bool g_is_child = false;

View file

@ -5,10 +5,11 @@
// Simple test for a fuzzer. The fuzzer must find the string "Hi!". // Simple test for a fuzzer. The fuzzer must find the string "Hi!".
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstdio>
static volatile int Sink; static volatile int Sink;
static volatile int *Null = 0;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size > 0 && Data[0] == 'H') { if (Size > 0 && Data[0] == 'H') {
@ -16,10 +17,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size > 1 && Data[1] == 'i') { if (Size > 1 && Data[1] == 'i') {
Sink = 2; Sink = 2;
if (Size > 2 && Data[2] == '!') { if (Size > 2 && Data[2] == '!') {
printf("Found the target, trapping\n"); printf("Found the target, dereferencing NULL\n");
__builtin_trap(); *Null = 1;
} }
} }
} }
return 0; return 0;
} }

View file

@ -16,7 +16,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
Sink = new int[1 << 28]; // instant OOM with -rss_limit_mb=128. Sink = new int[1 << 28]; // instant OOM with -rss_limit_mb=128.
if (Size >= 4 && Data[0] == 'F' && Data[1] == 'U' && Data[2] == 'Z' && if (Size >= 4 && Data[0] == 'F' && Data[1] == 'U' && Data[2] == 'Z' &&
Data[3] == 'Z') // a bit deeper crash. Data[3] == 'Z') // a bit deeper crash.
__builtin_trap(); *Zero = 42;
return 0; return 0;
} }

View file

@ -2,14 +2,14 @@
UNSUPPORTED: windows UNSUPPORTED: windows
# FIXME: CreatePCArray() emits PLT stub addresses for entry blocks, which are ignored by TracePC::PrintCoverage(). # FIXME: CreatePCArray() emits PLT stub addresses for entry blocks, which are ignored by TracePC::PrintCoverage().
XFAIL: s390x XFAIL: s390x
RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/TrapTest.cpp -o %t-TrapTest RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/NullDerefTest.cpp -o %t-NullDerefTest
RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO1.cpp -fPIC %ld_flags_rpath_so1 -O0 -shared -o %dynamiclib1 RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO1.cpp -fPIC %ld_flags_rpath_so1 -O0 -shared -o %dynamiclib1
RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO2.cpp -fPIC %ld_flags_rpath_so2 -O0 -shared -o %dynamiclib2 RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO2.cpp -fPIC %ld_flags_rpath_so2 -O0 -shared -o %dynamiclib2
RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSOTestMain.cpp %S/DSOTestExtra.cpp %ld_flags_rpath_exe1 %ld_flags_rpath_exe2 -o %t-DSOTest RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSOTestMain.cpp %S/DSOTestExtra.cpp %ld_flags_rpath_exe1 %ld_flags_rpath_exe2 -o %t-DSOTest
CHECK: COVERAGE: CHECK: COVERAGE:
CHECK: COVERED_FUNC: {{.*}}LLVMFuzzerTestOneInput {{.*}}TrapTest.cpp:13 CHECK: COVERED_FUNC: {{.*}}LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:14
RUN: not %run %t-TrapTest -print_coverage=1 2>&1 | FileCheck %s RUN: not %run %t-NullDerefTest -print_coverage=1 2>&1 | FileCheck %s
RUN: %run %t-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO RUN: %run %t-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO
DSO: COVERAGE: DSO: COVERAGE:

View file

@ -12,7 +12,7 @@ RUN: %cpp_compiler %S/OutOfMemoryTest.cpp -o %t-OutOfMemoryTest
RUN: not %run %t-OutOfMemoryTest -fork=1 -ignore_ooms=0 -rss_limit_mb=128 2>&1 | FileCheck %s --check-prefix=OOM RUN: not %run %t-OutOfMemoryTest -fork=1 -ignore_ooms=0 -rss_limit_mb=128 2>&1 | FileCheck %s --check-prefix=OOM
# access-violation is the error thrown on Windows. Address will be smaller on i386. # access-violation is the error thrown on Windows. Address will be smaller on i386.
CRASH: == ERROR: libFuzzer: deadly signal CRASH: {{SEGV|access-violation}} on unknown address 0x00000000
RUN: %cpp_compiler %S/ShallowOOMDeepCrash.cpp -o %t-ShallowOOMDeepCrash RUN: %cpp_compiler %S/ShallowOOMDeepCrash.cpp -o %t-ShallowOOMDeepCrash
RUN: not %run %t-ShallowOOMDeepCrash -fork=1 -rss_limit_mb=128 2>&1 | FileCheck %s --check-prefix=CRASH RUN: not %run %t-ShallowOOMDeepCrash -fork=1 -rss_limit_mb=128 2>&1 | FileCheck %s --check-prefix=CRASH

View file

@ -1,4 +1,4 @@
RUN: %cpp_compiler %S/TrapTest.cpp -o %t-SimpleCmpTest RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-SimpleCmpTest
RUN: %run %t-SimpleCmpTest -seed=-1 -runs=0 2>&1 | FileCheck %s --check-prefix=CHECK_SEED_MINUS_ONE RUN: %run %t-SimpleCmpTest -seed=-1 -runs=0 2>&1 | FileCheck %s --check-prefix=CHECK_SEED_MINUS_ONE
CHECK_SEED_MINUS_ONE: Seed: 4294967295 CHECK_SEED_MINUS_ONE: Seed: 4294967295

View file

@ -1,6 +1,8 @@
RUN: %cpp_compiler %S/TrapTest.cpp -o %t-TrapTest RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest
RUN: %env_asan_opts=handle_segv=0 not %run %t-TrapTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER RUN: %env_asan_opts=handle_segv=0 not %run %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER
RUN: %env_asan_opts=handle_segv=1 not %run %t-TrapTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER
LIBFUZZER_OWN_SEGV_HANDLER: == ERROR: libFuzzer: deadly signal LIBFUZZER_OWN_SEGV_HANDLER: == ERROR: libFuzzer: deadly signal
LIBFUZZER_OWN_SEGV_HANDLER: SUMMARY: libFuzzer: deadly signal LIBFUZZER_OWN_SEGV_HANDLER: SUMMARY: libFuzzer: deadly signal
LIBFUZZER_OWN_SEGV_HANDLER: Test unit written to ./crash- LIBFUZZER_OWN_SEGV_HANDLER: Test unit written to ./crash-
RUN: %env_asan_opts=handle_segv=1 not %run %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_ASAN_SEGV_HANDLER
LIBFUZZER_ASAN_SEGV_HANDLER: ERROR: AddressSanitizer: {{SEGV|access-violation}} on unknown address

View file

@ -1,7 +1,7 @@
RUN: %cpp_compiler %S/TrapTest.cpp -o %t-TrapTest RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest
RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
RUN: not %run %t-TrapTest %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput RUN: not %run %t-NullDerefTest %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput
SingleInput-NOT: Test unit written to ./crash- SingleInput-NOT: Test unit written to ./crash-
RUN: rm -rf %tmp/SINGLE_INPUTS RUN: rm -rf %tmp/SINGLE_INPUTS

View file

@ -1,11 +1,11 @@
RUN: %cpp_compiler %S/TrapTest.cpp -o %t-TrapTest RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest
RUN: %cpp_compiler %S/SingleByteInputTest.cpp -o %t-SingleByteInputTest RUN: %cpp_compiler %S/SingleByteInputTest.cpp -o %t-SingleByteInputTest
RUN: mkdir -p %t.dir RUN: mkdir -p %t.dir
RUN: echo 'Hi!rv349f34t3gg' > %t.dir/not_minimal_crash RUN: echo 'Hi!rv349f34t3gg' > %t.dir/not_minimal_crash
RUN: %run %t-TrapTest -minimize_crash=1 %t.dir/not_minimal_crash -max_total_time=2 2>&1 | FileCheck %s RUN: %run %t-NullDerefTest -minimize_crash=1 %t.dir/not_minimal_crash -max_total_time=2 2>&1 | FileCheck %s
CHECK: CRASH_MIN: failed to minimize beyond {{.*}}minimized-from{{.*}} (3 bytes), exiting CHECK: CRASH_MIN: failed to minimize beyond {{.*}}minimized-from{{.*}} (3 bytes), exiting
RUN: %run %t-TrapTest -minimize_crash=1 %t.dir/not_minimal_crash -max_total_time=2 -exact_artifact_path=%t.exact_minimized_path 2>&1 | FileCheck %s --check-prefix=CHECK_EXACT RUN: %run %t-NullDerefTest -minimize_crash=1 %t.dir/not_minimal_crash -max_total_time=2 -exact_artifact_path=%t.exact_minimized_path 2>&1 | FileCheck %s --check-prefix=CHECK_EXACT
CHECK_EXACT: CRASH_MIN: failed to minimize beyond {{.*}}exact_minimized_path{{.*}} (3 bytes), exiting CHECK_EXACT: CRASH_MIN: failed to minimize beyond {{.*}}exact_minimized_path{{.*}} (3 bytes), exiting
RUN: rm %t.dir/not_minimal_crash %t.exact_minimized_path RUN: rm %t.dir/not_minimal_crash %t.exact_minimized_path

View file

@ -0,0 +1,10 @@
RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest
RUN: not %run %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest
RUN: not %run %t-NullDerefTest -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=NullDerefTest
NullDerefTest: ERROR: AddressSanitizer: {{SEGV|access-violation}} on unknown address
NullDerefTest: Test unit written to ./crash-
RUN: not %run %t-NullDerefTest -artifact_prefix=ZZZ 2>&1 | FileCheck %s --check-prefix=NullDerefTestPrefix
NullDerefTestPrefix: Test unit written to ZZZcrash-
RUN: not %run %t-NullDerefTest -artifact_prefix=ZZZ -exact_artifact_path=FOOBAR 2>&1 | FileCheck %s --check-prefix=NullDerefTestExactPath
NullDerefTestExactPath: Test unit written to FOOBAR

View file

@ -1,10 +0,0 @@
RUN: %cpp_compiler %S/TrapTest.cpp -o %t-TrapTest
RUN: not %run %t-TrapTest 2>&1 | FileCheck %s --check-prefix=TrapTest
RUN: not %run %t-TrapTest -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=TrapTest
TrapTest: SUMMARY: libFuzzer: deadly signal
TrapTest: Test unit written to ./crash-
RUN: not %run %t-TrapTest -artifact_prefix=ZZZ 2>&1 | FileCheck %s --check-prefix=TrapTestPrefix
TrapTestPrefix: Test unit written to ZZZcrash-
RUN: not %run %t-TrapTest -artifact_prefix=ZZZ -exact_artifact_path=FOOBAR 2>&1 | FileCheck %s --check-prefix=TrapTestExactPath
TrapTestExactPath: Test unit written to FOOBAR

View file

@ -14,11 +14,13 @@
int main(int argc, char **argv) { int main(int argc, char **argv) {
int n = atoi(argv[1]); int n = atoi(argv[1]);
*((volatile int *)(n - 1)) = __LINE__; if (n == 1)
*((volatile int *)0x0) = __LINE__;
// CHECK1: #{{[0-9]+ .*}}main {{.*}}signal_line.cpp:[[@LINE-1]]:[[TAB:[0-9]+]]
// CHECK1: SUMMARY: [[SAN]]: SEGV {{.*}}signal_line.cpp:[[@LINE-2]]:[[TAB]] in main
// CHECK1: #{{[0-9]+ .*}}main {{.*}}signal_line.cpp:[[@LINE-2]]:[[TAB:[0-9]+]] if (n == 2)
// CHECK1: SUMMARY: [[SAN]]: SEGV {{.*}}signal_line.cpp:[[@LINE-3]]:[[TAB]] in main *((volatile int *)0x1) = __LINE__;
// CHECK2: #{{[0-9]+ .*}}main {{.*}}signal_line.cpp:[[@LINE-1]]:[[TAB:[0-9]+]]
// CHECK2: #{{[0-9]+ .*}}main {{.*}}signal_line.cpp:[[@LINE-5]]:[[TAB:[0-9]+]] // CHECK2: SUMMARY: [[SAN]]: SEGV {{.*}}signal_line.cpp:[[@LINE-2]]:[[TAB]] in main
// CHECK2: SUMMARY: [[SAN]]: SEGV {{.*}}signal_line.cpp:[[@LINE-6]]:[[TAB]] in main
} }

View file

@ -2888,6 +2888,14 @@ Instruction *InstCombinerImpl::visitUnreachableInst(UnreachableInst &I) {
// Otherwise, this instruction can be freely erased, // Otherwise, this instruction can be freely erased,
// even if it is not side-effect free. // even if it is not side-effect free.
// Temporarily disable removal of volatile stores preceding unreachable,
// pending a potential LangRef change permitting volatile stores to trap.
// TODO: Either remove this code, or properly integrate the check into
// isGuaranteedToTransferExecutionToSuccessor().
if (auto *SI = dyn_cast<StoreInst>(Prev))
if (SI->isVolatile())
return nullptr; // Can not drop this instruction. We're done here.
// A value may still have uses before we process it here (for example, in // A value may still have uses before we process it here (for example, in
// another unreachable block), so convert those to poison. // another unreachable block), so convert those to poison.
replaceInstUsesWith(*Prev, PoisonValue::get(Prev->getType())); replaceInstUsesWith(*Prev, PoisonValue::get(Prev->getType()));

View file

@ -2302,6 +2302,9 @@ static bool markAliveBlocks(Function &F,
// that they should be changed to unreachable by passes that can't // that they should be changed to unreachable by passes that can't
// modify the CFG. // modify the CFG.
// Don't touch volatile stores.
if (SI->isVolatile()) continue;
Value *Ptr = SI->getOperand(1); Value *Ptr = SI->getOperand(1);
if (isa<UndefValue>(Ptr) || if (isa<UndefValue>(Ptr) ||

View file

@ -4672,6 +4672,14 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
// Otherwise, this instruction can be freely erased, // Otherwise, this instruction can be freely erased,
// even if it is not side-effect free. // even if it is not side-effect free.
// Temporarily disable removal of volatile stores preceding unreachable,
// pending a potential LangRef change permitting volatile stores to trap.
// TODO: Either remove this code, or properly integrate the check into
// isGuaranteedToTransferExecutionToSuccessor().
if (auto *SI = dyn_cast<StoreInst>(&*BBI))
if (SI->isVolatile())
break; // Can not drop this instruction. We're done here.
// Note that deleting EH's here is in fact okay, although it involves a bit // Note that deleting EH's here is in fact okay, although it involves a bit
// of subtle reasoning. If this inst is an EH, all the predecessors of this // of subtle reasoning. If this inst is an EH, all the predecessors of this
// block will be the unwind edges of Invoke/CatchSwitch/CleanupReturn, // block will be the unwind edges of Invoke/CatchSwitch/CleanupReturn,

View file

@ -4,7 +4,7 @@
; Long branch is assumed because the block has a higher alignment ; Long branch is assumed because the block has a higher alignment
; requirement than the function. ; requirement than the function.
define i32 @invert_bcc_block_align_higher_func(i32 %x, i32 %y, i32* %dst) align 4 #0 { define i32 @invert_bcc_block_align_higher_func(i32 %x, i32 %y) align 4 #0 {
; CHECK-LABEL: invert_bcc_block_align_higher_func: ; CHECK-LABEL: invert_bcc_block_align_higher_func:
; CHECK: ; %bb.0: ; %common.ret ; CHECK: ; %bb.0: ; %common.ret
; CHECK-NEXT: cmp w0, w1 ; CHECK-NEXT: cmp w0, w1
@ -12,17 +12,17 @@ define i32 @invert_bcc_block_align_higher_func(i32 %x, i32 %y, i32* %dst) align
; CHECK-NEXT: mov w9, #42 ; CHECK-NEXT: mov w9, #42
; CHECK-NEXT: cset w0, ne ; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: csel w8, w9, w8, eq ; CHECK-NEXT: csel w8, w9, w8, eq
; CHECK-NEXT: str w8, [x2] ; CHECK-NEXT: str w8, [x8]
; CHECK-NEXT: ret ; CHECK-NEXT: ret
%1 = icmp eq i32 %x, %y %1 = icmp eq i32 %x, %y
br i1 %1, label %bb1, label %bb2 br i1 %1, label %bb1, label %bb2
bb2: bb2:
store volatile i32 9, i32* %dst store volatile i32 9, i32* undef
ret i32 1 ret i32 1
bb1: bb1:
store volatile i32 42, i32* %dst store volatile i32 42, i32* undef
ret i32 0 ret i32 0
} }

View file

@ -1,28 +1,27 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=aarch64-apple-darwin -aarch64-bcc-offset-bits=3 < %s | FileCheck %s ; RUN: llc -mtriple=aarch64-apple-darwin -aarch64-bcc-offset-bits=3 < %s | FileCheck %s
define i32 @invert_bcc(float %x, float %y, i32* %dst0, i32* %dst1) #0 { define i32 @invert_bcc(float %x, float %y) #0 {
; CHECK-LABEL: invert_bcc: ; CHECK-LABEL: invert_bcc:
; CHECK: ; %bb.0: ; CHECK: ; %bb.0:
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: fcmp s0, s1 ; CHECK-NEXT: fcmp s0, s1
; CHECK-NEXT: b.ne LBB0_3 ; CHECK-NEXT: mov w8, #42
; CHECK-NEXT: b.pl LBB0_3
; CHECK-NEXT: b LBB0_2 ; CHECK-NEXT: b LBB0_2
; CHECK-NEXT: LBB0_3: ; CHECK-NEXT: LBB0_3:
; CHECK-NEXT: b.vc LBB0_1 ; CHECK-NEXT: b.gt LBB0_2
; CHECK-NEXT: b LBB0_2 ; CHECK-NEXT: ; %bb.1: ; %common.ret
; CHECK-NEXT: LBB0_1: ; %bb2 ; CHECK-NEXT: str w8, [x8]
; CHECK-NEXT: ret
; CHECK-NEXT: LBB0_2: ; %bb2
; CHECK-NEXT: mov w0, #1
; CHECK-NEXT: mov w8, #9 ; CHECK-NEXT: mov w8, #9
; CHECK-NEXT: ; InlineAsm Start ; CHECK-NEXT: ; InlineAsm Start
; CHECK-NEXT: nop ; CHECK-NEXT: nop
; CHECK-NEXT: nop ; CHECK-NEXT: nop
; CHECK-NEXT: ; InlineAsm End ; CHECK-NEXT: ; InlineAsm End
; CHECK-NEXT: str w8, [x0] ; CHECK-NEXT: str w8, [x8]
; CHECK-NEXT: mov w0, #1
; CHECK-NEXT: ret
; CHECK-NEXT: LBB0_2: ; %bb1
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: mov w8, #42
; CHECK-NEXT: str w8, [x1]
; CHECK-NEXT: ret ; CHECK-NEXT: ret
%1 = fcmp ueq float %x, %y %1 = fcmp ueq float %x, %y
br i1 %1, label %bb1, label %bb2 br i1 %1, label %bb1, label %bb2
@ -32,11 +31,11 @@ bb2:
"nop "nop
nop", nop",
""() #0 ""() #0
store volatile i32 9, i32* %dst0 store volatile i32 9, i32* undef
ret i32 1 ret i32 1
bb1: bb1:
store volatile i32 42, i32* %dst1 store volatile i32 42, i32* undef
ret i32 0 ret i32 0
} }

View file

@ -16,18 +16,18 @@ entry:
; CHECK: mul i32 ; CHECK: mul i32
; CHECK-NOT: call i32 ; CHECK-NOT: call i32
define amdgpu_kernel void @caller(i32 %x, i32 addrspace(1)* %dst) { define amdgpu_kernel void @caller(i32 %x) {
entry: entry:
%res = call i32 @callee(i32 %x) %res = call i32 @callee(i32 %x)
store volatile i32 %res, i32 addrspace(1)* %dst store volatile i32 %res, i32 addrspace(1)* undef
ret void ret void
} }
; CHECK-LABEL: @alias_caller( ; CHECK-LABEL: @alias_caller(
; CHECK-NOT: call ; CHECK-NOT: call
define amdgpu_kernel void @alias_caller(i32 %x, i32 addrspace(1)* %dst) { define amdgpu_kernel void @alias_caller(i32 %x) {
entry: entry:
%res = call i32 @c_alias(i32 %x) %res = call i32 @c_alias(i32 %x)
store volatile i32 %res, i32 addrspace(1)* %dst store volatile i32 %res, i32 addrspace(1)* undef
ret void ret void
} }

View file

@ -3,38 +3,51 @@
; NUM-COUNT-3: endbr64 ; NUM-COUNT-3: endbr64
; SJLJ-LABEL: main: ;SJLJ: main: # @main
; SJLJ: # %bb.0: # %entry ;SJLJ-NEXT: .Lfunc_begin0:
; SJLJ-NEXT: endbr64 ;SJLJ-NEXT: # %bb.0: # %entry
; SJLJ: callq _Unwind_SjLj_Register@PLT ;SJLJ-NEXT: endbr64
; SJLJ-NEXT: .Ltmp0: ;SJLJ-NEXT: pushq %rbp
; SJLJ-NEXT: callq _Z3foov ;SJLJ: callq _Unwind_SjLj_Register
; SJLJ-NEXT: .Ltmp1: ;SJLJ-NEXT: .Ltmp0:
; SJLJ-NEXT: # %bb.1: # %invoke.cont ;SJLJ-NEXT: callq _Z3foov
; SJLJ: .LBB0_6: # %return ;SJLJ-NEXT: .Ltmp1:
; SJLJ: callq _Unwind_SjLj_Unregister@PLT ;SJLJ-NEXT: # %bb.1: # %invoke.cont
; SJLJ: retq ;SJLJ-NEXT: movl
; SJLJ-NEXT: .LBB0_7: ;SJLJ-NEXT: .LBB0_7: # %return
; SJLJ-NEXT: endbr64 ;SJLJ: callq _Unwind_SjLj_Unregister
; SJLJ: jb .LBB0_8 ;SJLJ: retq
; SJLJ-NEXT: # %bb.9: ;SJLJ-NEXT: .LBB0_9:
; SJLJ-NEXT: ud2 ;SJLJ-NEXT: endbr64
; SJLJ-NEXT: .LBB0_8: ;SJLJ-NEXT: movl
; SJLJ: jmpq *(%rcx,%rax,8) ;SJLJ-NEXT: cmpl
; SJLJ-NEXT: .LBB0_2: # %lpad ;SJLJ-NEXT: jb .LBB0_10
; SJLJ-NEXT: .Ltmp2: ;SJLJ-NEXT: # %bb.11:
; SJLJ-NEXT: endbr64 ;SJLJ-NEXT: ud2
; SJLJ: jne .LBB0_4 ;SJLJ-NEXT: .LBB0_10:
; SJLJ-NEXT: # %bb.3: # %catch3 ;SJLJ-NEXT: leaq .LJTI0_0(%rip), %rcx
; SJLJ: callq __cxa_begin_catch ;SJLJ-NEXT: jmpq *(%rcx,%rax,8)
; SJLJ: jmp .LBB0_5 ;SJLJ-NEXT: .LBB0_2: # %lpad
; SJLJ-NEXT: .LBB0_4: # %catch ;SJLJ-NEXT: .Ltmp2:
; SJLJ: callq __cxa_begin_catch ;SJLJ-NEXT: endbr64
; SJLJ: cmpb $3, %al ;SJLJ: jne .LBB0_4
; SJLJ-NEXT: .LBB0_5: # %return ;SJLJ-NEXT: # %bb.3: # %catch3
; SJLJ-NEXT: setne %cl ;SJLJ: callq __cxa_begin_catch
; SJLJ: callq __cxa_end_catch ;SJLJ: jmp .LBB0_6
; SJLJ-NEXT: jmp .LBB0_6 ;SJLJ-NEXT: .LBB0_4: # %catch.fallthrough
;SJLJ-NEXT: cmpl
;SJLJ-NEXT: jne .LBB0_8
;SJLJ-NEXT: # %bb.5: # %catch
;SJLJ: callq __cxa_begin_catch
;SJLJ: cmpb
;SJLJ-NEXT: .LBB0_6: # %return
;SJLJ: callq __cxa_end_catch
;SJLJ-NEXT: jmp .LBB0_7
;SJLJ-NEXT: .LBB0_8: # %eh.resume
;SJLJ-NEXT: movl
;SJLJ-NEXT: .Lfunc_end0:
;SJLJ: .LJTI0_0:
;SJLJ-NEXT: .quad .LBB0_2
@_ZTIi = external dso_local constant i8* @_ZTIi = external dso_local constant i8*
@_ZTIc = external dso_local constant i8* @_ZTIc = external dso_local constant i8*

View file

@ -25,6 +25,7 @@ define void @volatile_store_before_unreachable(i1 %c, i8* %p) {
; CHECK-LABEL: @volatile_store_before_unreachable( ; CHECK-LABEL: @volatile_store_before_unreachable(
; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
; CHECK: true: ; CHECK: true:
; CHECK-NEXT: store volatile i8 0, i8* [[P:%.*]], align 1
; CHECK-NEXT: unreachable ; CHECK-NEXT: unreachable
; CHECK: false: ; CHECK: false:
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void

View file

@ -76,8 +76,8 @@ entry:
define void @test3() nounwind { define void @test3() nounwind {
; CHECK-LABEL: @test3( ; CHECK-LABEL: @test3(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: call void @llvm.trap() ; CHECK-NEXT: store volatile i32 4, i32* null, align 4
; CHECK-NEXT: unreachable ; CHECK-NEXT: ret void
; ;
entry: entry:
store volatile i32 4, i32* null store volatile i32 4, i32* null
@ -101,8 +101,11 @@ entry:
define void @test4(i1 %C, i32* %P) { define void @test4(i1 %C, i32* %P) {
; CHECK-LABEL: @test4( ; CHECK-LABEL: @test4(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true ; CHECK-NEXT: br i1 [[C:%.*]], label [[T:%.*]], label [[F:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK: T:
; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4
; CHECK-NEXT: unreachable
; CHECK: F:
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
entry: entry:

View file

@ -4813,9 +4813,10 @@ void UnitTest::AddTestPartResult(
// with clang/gcc we can achieve the same effect on x86 by invoking int3 // with clang/gcc we can achieve the same effect on x86 by invoking int3
asm("int3"); asm("int3");
#else #else
// While some debuggers don't correctly trap abort(), we can't perform // Dereference nullptr through a volatile pointer to prevent the compiler
// volatile store to null since it will be removed by clang and not trap. // from removing. We use this rather than abort() or __builtin_trap() for
__builtin_trap(); // portability: some debuggers don't correctly trap abort().
*static_cast<volatile int*>(nullptr) = 1;
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
} else if (GTEST_FLAG(throw_on_failure)) { } else if (GTEST_FLAG(throw_on_failure)) {
#if GTEST_HAS_EXCEPTIONS #if GTEST_HAS_EXCEPTIONS