From 97c675d3d43fe02a0ff0a8350d79344c845758af Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 9 Jul 2021 11:39:40 -0400 Subject: [PATCH] Revert "Revert "Temporarily do not drop volatile stores before unreachable"" This reverts commit 52aeacfbf5ce5f949efe0eae029e56db171ea1f7. 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 f4877c78c0fc98be47b926439bbfe33d5e1d1b6d. And all the related changes to tests: This reverts commit 9a0152799f8e4a59e0483728c9f11c8a7805616f. This reverts commit 3f7c9cc27422f7302cf5a683eeb3978e6cb84270. This reverts commit 329f8197ef59f9bd23328b52d623ba768b51dbb2. This reverts commit aa9f58cc2c48ca6cfc853a2467cd775dc7622746. This reverts commit 2df37d5ddd38091aafbb7d338660e58836f4ac80. This reverts commit a72a44181264fd83e05be958c2712cbd4560aba7. --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 +- clang/lib/Sema/SemaExpr.cpp | 19 ++++-- clang/test/Analysis/NewDelete-checker-test.cpp | 6 +- clang/test/Analysis/conditional-path-notes.c | 6 +- clang/test/Analysis/cxx-for-range.cpp | 18 ++--- clang/test/Analysis/diagnostics/no-prune-paths.c | 3 +- clang/test/Analysis/inlining/path-notes.cpp | 2 +- clang/test/Analysis/objc-arc.m | 6 +- clang/test/Analysis/objc-for.m | 2 +- clang/test/Analysis/taint-generic.c | 2 +- clang/test/Analysis/valist-uninitialized.c | 2 +- clang/test/CodeGenOpenCL/convergent.cl | 15 +++-- clang/test/Parser/expressions.c | 5 +- clang/test/Sema/exprs.c | 32 +++++---- clang/test/Sema/offsetof.c | 23 +++---- clang/test/SemaCXX/member-pointer.cpp | 17 ++--- .../test/asan/TestCases/Windows/dll_control_c.cpp | 2 +- .../fuzzer/{TrapTest.cpp => NullDerefTest.cpp} | 8 ++- compiler-rt/test/fuzzer/ShallowOOMDeepCrash.cpp | 2 +- compiler-rt/test/fuzzer/coverage.test | 6 +- compiler-rt/test/fuzzer/fork.test | 2 +- compiler-rt/test/fuzzer/fuzzer-seed.test | 2 +- compiler-rt/test/fuzzer/fuzzer-segv.test | 8 ++- compiler-rt/test/fuzzer/fuzzer-singleinputs.test | 4 +- compiler-rt/test/fuzzer/minimize_crash.test | 6 +- compiler-rt/test/fuzzer/null-deref.test | 10 +++ compiler-rt/test/fuzzer/trap.test | 10 --- .../TestCases/Linux/signal_line.cpp | 14 ++-- .../InstCombine/InstructionCombining.cpp | 8 +++ llvm/lib/Transforms/Utils/Local.cpp | 3 + llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 8 +++ .../test/CodeGen/AArch64/branch-relax-alignment.ll | 8 +-- llvm/test/CodeGen/AArch64/branch-relax-bcc.ll | 27 ++++---- llvm/test/CodeGen/AMDGPU/early-inline.ll | 8 +-- .../CodeGen/X86/indirect-branch-tracking-eh2.ll | 77 +++++++++++++--------- llvm/test/Transforms/InstCombine/volatile_store.ll | 1 + .../SimplifyCFG/trapping-load-unreachable.ll | 11 ++-- llvm/utils/unittest/googletest/src/gtest.cc | 7 +- 38 files changed, 222 insertions(+), 172 deletions(-) rename compiler-rt/test/fuzzer/{TrapTest.cpp => NullDerefTest.cpp} (85%) create mode 100644 compiler-rt/test/fuzzer/null-deref.test delete mode 100644 compiler-rt/test/fuzzer/trap.test diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d33d488..a9d7388 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6744,13 +6744,13 @@ def ext_typecheck_indirection_through_void_pointer : ExtWarn< "ISO C++ does not allow indirection on operand of type %0">, InGroup>; 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; def warn_binding_null_to_reference : Warning< "binding dereferenced null pointer to reference has undefined behavior">, InGroup; 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< "dereference of type %1 that was reinterpret_cast from type %0 has undefined " "behavior">, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d0efe4c..a3a26d2 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -533,16 +533,21 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) { } static void CheckForNullPointerDereference(Sema &S, Expr *E) { - // Check to see if we are dereferencing a null pointer. - // If so, this is undefined behavior that the optimizer will delete, - // so warn about it. People sometimes try to use this to get a deterministic - // trap and are surprised by clang's behavior. This only handles the pattern - // "*null", which is a very syntactic check. + // Check to see if we are dereferencing a null pointer. If so, + // and if not volatile-qualified, this is undefined behavior that the + // optimizer will delete, so warn about it. People sometimes try to use this + // to get a deterministic trap and are surprised by clang's behavior. This + // only handles the pattern "*null", which is a very syntactic check. const auto *UO = dyn_cast(E->IgnoreParenCasts()); if (UO && UO->getOpcode() == UO_Deref && UO->getSubExpr()->getType()->isPointerType()) { - if (UO->getSubExpr()->IgnoreParenCasts()->isNullPointerConstant( - S.Context, Expr::NPC_ValueDependentIsNotNull)) { + const LangAS AS = + 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.PDiag(diag::warn_indirection_through_null) << UO->getSubExpr()->getSourceRange()); diff --git a/clang/test/Analysis/NewDelete-checker-test.cpp b/clang/test/Analysis/NewDelete-checker-test.cpp index 44a176a..86df9d0 100644 --- a/clang/test/Analysis/NewDelete-checker-test.cpp +++ b/clang/test/Analysis/NewDelete-checker-test.cpp @@ -83,7 +83,7 @@ void testGlobalPointerPlacementNew() { //----- Other cases void testNewMemoryIsInHeap() { 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' global = p; // pointer escapes } @@ -263,13 +263,13 @@ void testUninitFree() { void testUninitDeleteSink() { int *x; 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() { int *x; 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 { diff --git a/clang/test/Analysis/conditional-path-notes.c b/clang/test/Analysis/conditional-path-notes.c index df69488..5ef81d8 100644 --- a/clang/test/Analysis/conditional-path-notes.c +++ b/clang/test/Analysis/conditional-path-notes.c @@ -59,7 +59,7 @@ void testDiagnosableBranch(int a) { if (a) { // expected-note@-1 {{Assuming 'a' is not equal to 0}} // 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}} } } @@ -70,7 +70,7 @@ void testDiagnosableBranchLogical(int a, int b) { // expected-note@-2 {{Left side of '&&' is true}} // expected-note@-3 {{Assuming 'b' is not equal to 0}} // 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}} } } @@ -79,7 +79,7 @@ void testNonDiagnosableBranchArithmetic(int a, int b) { if (a - b) { // expected-note@-1 {{Taking true branch}} // 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}} } } diff --git a/clang/test/Analysis/cxx-for-range.cpp b/clang/test/Analysis/cxx-for-range.cpp index 6fa38b4..0340078 100644 --- a/clang/test/Analysis/cxx-for-range.cpp +++ b/clang/test/Analysis/cxx-for-range.cpp @@ -9,13 +9,13 @@ void testLoop() { work(); work(); 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(); (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 { @@ -30,7 +30,7 @@ public: MagicVector get(bool fail = false) { 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{}; } @@ -39,13 +39,13 @@ void testLoopOpaqueCollection() { work(); work(); 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(); (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(); 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(); (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(); 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(); (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() { diff --git a/clang/test/Analysis/diagnostics/no-prune-paths.c b/clang/test/Analysis/diagnostics/no-prune-paths.c index 53042ee..6e9e457 100644 --- a/clang/test/Analysis/diagnostics/no-prune-paths.c +++ b/clang/test/Analysis/diagnostics/no-prune-paths.c @@ -16,5 +16,6 @@ void test() { // expected-note@-3 {{Returning from 'helper'}} #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}} } diff --git a/clang/test/Analysis/inlining/path-notes.cpp b/clang/test/Analysis/inlining/path-notes.cpp index 4daa39e..59726df 100644 --- a/clang/test/Analysis/inlining/path-notes.cpp +++ b/clang/test/Analysis/inlining/path-notes.cpp @@ -278,7 +278,7 @@ namespace PR17746 { class Inner { public: ~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}} } }; diff --git a/clang/test/Analysis/objc-arc.m b/clang/test/Analysis/objc-arc.m index b599fca..7127232 100644 --- a/clang/test/Analysis/objc-arc.m +++ b/clang/test/Analysis/objc-arc.m @@ -119,7 +119,7 @@ void rdar9424882() { id x = [NSObject alloc]; // expected-warning {{Value stored to 'x' during its initialization is never read}} } -// Test +// Test typedef const void *CFTypeRef; 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) { NSObject *o = [[NSObject alloc] init]; - dispatch_set_context(object, CFBridgingRetain(o)); // no-warning + dispatch_set_context(object, CFBridgingRetain(o)); // no-warning } void rdar11059275_positive() { 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 // of that and the inlined call don't produce a spurious edge cycle. 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; } diff --git a/clang/test/Analysis/objc-for.m b/clang/test/Analysis/objc-for.m index cdbb069..d4a04c1 100644 --- a/clang/test/Analysis/objc-for.m +++ b/clang/test/Analysis/objc-for.m @@ -86,7 +86,7 @@ void testNonNil(id a, id b) { if (b != nil) return; 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}} } diff --git a/clang/test/Analysis/taint-generic.c b/clang/test/Analysis/taint-generic.c index dc1f2d4..2cbd5801 100644 --- a/clang/test/Analysis/taint-generic.c +++ b/clang/test/Analysis/taint-generic.c @@ -338,7 +338,7 @@ void constraintManagerShouldTreatAsOpaque(int rhs) { if (i < rhs) return; 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 } diff --git a/clang/test/Analysis/valist-uninitialized.c b/clang/test/Analysis/valist-uninitialized.c index 8ed05d2..0035929 100644 --- a/clang/test/Analysis/valist-uninitialized.c +++ b/clang/test/Analysis/valist-uninitialized.c @@ -145,7 +145,7 @@ void is_sink(int fst, ...) { va_list va; 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}} - *((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() diff --git a/clang/test/CodeGenOpenCL/convergent.cl b/clang/test/CodeGenOpenCL/convergent.cl index a69b3d7..1905d7d 100644 --- a/clang/test/CodeGenOpenCL/convergent.cl +++ b/clang/test/CodeGenOpenCL/convergent.cl @@ -3,10 +3,11 @@ // 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 __attribute__((noinline)) -void non_convfun(volatile int* p) { +void non_convfun(void) { + volatile int* p; *p = 0; } @@ -27,29 +28,29 @@ void g(void); // 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: br i1 %[[tobool]], label %[[if_end3_critedge:.+]], label %[[if_then:.+]] // CHECK: [[if_then]]: // 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: br label %[[if_end3:.+]] // 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: [[if_end3]]: // CHECK: ret void -void test_merge_if(int a, volatile int* p) { +void test_merge_if(int a) { if (a) { f(); } - non_convfun(p); + non_convfun(); if (a) { g(); } diff --git a/clang/test/Parser/expressions.c b/clang/test/Parser/expressions.c index bd0ef87..64b4447 100644 --- a/clang/test/Parser/expressions.c +++ b/clang/test/Parser/expressions.c @@ -39,13 +39,14 @@ void test_sizeof(){ // PR3418 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; } // PR3972 int test5(int); -int test6(void) { +int test6(void) { return test5( // expected-note {{to match}} test5(1) ; // expected-error {{expected ')'}} diff --git a/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c index a5ed610..4e14404 100644 --- a/clang/test/Sema/exprs.c +++ b/clang/test/Sema/exprs.c @@ -22,7 +22,7 @@ void radar9171946() { int test_pr8876() { 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; } @@ -31,7 +31,7 @@ int test_pr8876() { void pr8183(unsigned long long test) { (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 @@ -59,7 +59,7 @@ void test4() { var =+5; // no warning when the subexpr of the unary op has no space before it. var =-5; - + #define FIVE 5 var=-FIVE; // no warning with macros. var=-FIVE; @@ -159,7 +159,7 @@ void test17(int x) { x = x % 0; // expected-warning {{remainder by zero is undefined}} x /= 0; // expected-warning {{division by zero is undefined}} x %= 0; // expected-warning {{remainder by zero is undefined}} - + x = sizeof(x/0); // no warning. } @@ -187,17 +187,21 @@ void test18(int b) { typedef int __attribute__((address_space(256))) int_AS256; // PR7569 void test19() { - *(int *)0 = 0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} - *(volatile int *)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; // 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 null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} - *(int_AS256 *)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}} \ + // expected-note {{consider using __builtin_trap}} + *(volatile int *)0 = 0; // Ok. + *(int __attribute__((address_space(256))) *)0 = 0; // Ok. + *(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 - int x = *(int *)0; // expected-warning{{indirection of null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} - int x2 = *(volatile int *)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 null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap()}} - int x4 = *(int_AS256 *)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}} \ + // expected-note {{consider using __builtin_trap}} + int x2 = *(volatile int *)0; // Ok. + 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_AS256 *p1 = &(*(int __attribute__((address_space(256))) *)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}} return x && sizeof(int) == 4; // no warning, RHS is logical op. - + // no warning, this is an idiom for "true" in old C style. return x && (signed char)1; diff --git a/clang/test/Sema/offsetof.c b/clang/test/Sema/offsetof.c index 5cd8e67..b5e392d 100644 --- a/clang/test/Sema/offsetof.c +++ b/clang/test/Sema/offsetof.c @@ -5,9 +5,10 @@ typedef struct P { int i; float f; } PT; struct external_sun3_core { - unsigned c_regs; + unsigned c_regs; PT X[100]; + }; void swap() @@ -15,30 +16,24 @@ void swap() int x; 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].f2); // expected-error {{no member named 'f2'}} 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 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'}} -} +} extern int f(); -struct s1 { - int a; -}; +struct s1 { int a; }; int v1 = offsetof (struct s1, a) == 0 ? 0 : f(); -struct s2 { - int a; -}; +struct s2 { int a; }; int v2 = (int)(&((struct s2 *) 0)->a) == 0 ? 0 : f(); -struct s3 { - int a; -}; +struct s3 { int a; }; int v3 = __builtin_offsetof(struct s3, a) == 0 ? 0 : f(); // PR3396 @@ -72,6 +67,6 @@ typedef struct Array { int array[1]; } Array; int test4 = __builtin_offsetof(Array, array); 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}} } diff --git a/clang/test/SemaCXX/member-pointer.cpp b/clang/test/SemaCXX/member-pointer.cpp index e612fda..f3adb95 100644 --- a/clang/test/SemaCXX/member-pointer.cpp +++ b/clang/test/SemaCXX/member-pointer.cpp @@ -47,7 +47,7 @@ void f() { // Conversion to member of base. pdi1 = pdid; // expected-error {{assigning to 'int A::*' from incompatible type 'int D::*'}} - + // Comparisons int (A::*pf2)(int, int); int (D::*pf3)(int, int) = 0; @@ -106,7 +106,7 @@ void h() { int i = phm->*pi; (void)&(hm.*pi); (void)&(phm->*pi); - (void)&((&hm)->*pi); + (void)&((&hm)->*pi); void (HasMembers::*pf)() = &HasMembers::f; (hm.*pf)(); @@ -204,7 +204,7 @@ namespace rdar8358512 { static void stat(); static void stat(int); - + template struct Test0 { void test() { bind(&nonstat); // expected-error {{no matching function for call}} @@ -295,8 +295,8 @@ namespace PR9973 { { call(u); } // expected-note{{in instantiation of}} }; - template - dm mem_fn(R T::*); + template + dm mem_fn(R T::*) ; struct test { int nullary_v(); }; @@ -312,13 +312,14 @@ namespace test8 { struct A { int foo; }; int test1() { // 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()}} - ->**(int 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 non-volatile null pointer will be deleted}} expected-note {{consider}} } int test2() { // Verify that we perform (and check) an lvalue conversion on the operands here. // 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}} } } diff --git a/compiler-rt/test/asan/TestCases/Windows/dll_control_c.cpp b/compiler-rt/test/asan/TestCases/Windows/dll_control_c.cpp index f7c81e0..e302763 100644 --- a/compiler-rt/test/asan/TestCases/Windows/dll_control_c.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/dll_control_c.cpp @@ -12,7 +12,7 @@ static void __declspec(noinline) CrashOnProcessDetach() { printf("CrashOnProcessDetach\n"); fflush(stdout); - __builtin_trap(); + *static_cast(0) = 0x356; } bool g_is_child = false; diff --git a/compiler-rt/test/fuzzer/TrapTest.cpp b/compiler-rt/test/fuzzer/NullDerefTest.cpp similarity index 85% rename from compiler-rt/test/fuzzer/TrapTest.cpp rename to compiler-rt/test/fuzzer/NullDerefTest.cpp index d3e7c2b..32a3661 100644 --- a/compiler-rt/test/fuzzer/TrapTest.cpp +++ b/compiler-rt/test/fuzzer/NullDerefTest.cpp @@ -5,10 +5,11 @@ // Simple test for a fuzzer. The fuzzer must find the string "Hi!". #include #include -#include #include +#include static volatile int Sink; +static volatile int *Null = 0; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 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') { Sink = 2; if (Size > 2 && Data[2] == '!') { - printf("Found the target, trapping\n"); - __builtin_trap(); + printf("Found the target, dereferencing NULL\n"); + *Null = 1; } } } return 0; } + diff --git a/compiler-rt/test/fuzzer/ShallowOOMDeepCrash.cpp b/compiler-rt/test/fuzzer/ShallowOOMDeepCrash.cpp index 680d940..197fffa 100644 --- a/compiler-rt/test/fuzzer/ShallowOOMDeepCrash.cpp +++ b/compiler-rt/test/fuzzer/ShallowOOMDeepCrash.cpp @@ -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. if (Size >= 4 && Data[0] == 'F' && Data[1] == 'U' && Data[2] == 'Z' && Data[3] == 'Z') // a bit deeper crash. - __builtin_trap(); + *Zero = 42; return 0; } diff --git a/compiler-rt/test/fuzzer/coverage.test b/compiler-rt/test/fuzzer/coverage.test index cf6b4d8..07a10ba 100644 --- a/compiler-rt/test/fuzzer/coverage.test +++ b/compiler-rt/test/fuzzer/coverage.test @@ -2,14 +2,14 @@ UNSUPPORTED: windows # FIXME: CreatePCArray() emits PLT stub addresses for entry blocks, which are ignored by TracePC::PrintCoverage(). 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/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 CHECK: COVERAGE: -CHECK: COVERED_FUNC: {{.*}}LLVMFuzzerTestOneInput {{.*}}TrapTest.cpp:13 -RUN: not %run %t-TrapTest -print_coverage=1 2>&1 | FileCheck %s +CHECK: COVERED_FUNC: {{.*}}LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:14 +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 DSO: COVERAGE: diff --git a/compiler-rt/test/fuzzer/fork.test b/compiler-rt/test/fuzzer/fork.test index e78541b..6e76fe7 100644 --- a/compiler-rt/test/fuzzer/fork.test +++ b/compiler-rt/test/fuzzer/fork.test @@ -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 # 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: not %run %t-ShallowOOMDeepCrash -fork=1 -rss_limit_mb=128 2>&1 | FileCheck %s --check-prefix=CRASH diff --git a/compiler-rt/test/fuzzer/fuzzer-seed.test b/compiler-rt/test/fuzzer/fuzzer-seed.test index 6ca24c9..b6343ff 100644 --- a/compiler-rt/test/fuzzer/fuzzer-seed.test +++ b/compiler-rt/test/fuzzer/fuzzer-seed.test @@ -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 CHECK_SEED_MINUS_ONE: Seed: 4294967295 diff --git a/compiler-rt/test/fuzzer/fuzzer-segv.test b/compiler-rt/test/fuzzer/fuzzer-segv.test index a658b28..7ae9049 100644 --- a/compiler-rt/test/fuzzer/fuzzer-segv.test +++ b/compiler-rt/test/fuzzer/fuzzer-segv.test @@ -1,6 +1,8 @@ -RUN: %cpp_compiler %S/TrapTest.cpp -o %t-TrapTest -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=1 not %run %t-TrapTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER +RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest +RUN: %env_asan_opts=handle_segv=0 not %run %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER LIBFUZZER_OWN_SEGV_HANDLER: == ERROR: libFuzzer: deadly signal LIBFUZZER_OWN_SEGV_HANDLER: SUMMARY: libFuzzer: deadly signal 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 diff --git a/compiler-rt/test/fuzzer/fuzzer-singleinputs.test b/compiler-rt/test/fuzzer/fuzzer-singleinputs.test index 67b3ba9..704f9ca 100644 --- a/compiler-rt/test/fuzzer/fuzzer-singleinputs.test +++ b/compiler-rt/test/fuzzer/fuzzer-singleinputs.test @@ -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: 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- RUN: rm -rf %tmp/SINGLE_INPUTS diff --git a/compiler-rt/test/fuzzer/minimize_crash.test b/compiler-rt/test/fuzzer/minimize_crash.test index 33c9174..de44b87 100644 --- a/compiler-rt/test/fuzzer/minimize_crash.test +++ b/compiler-rt/test/fuzzer/minimize_crash.test @@ -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: mkdir -p %t.dir 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 -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 RUN: rm %t.dir/not_minimal_crash %t.exact_minimized_path diff --git a/compiler-rt/test/fuzzer/null-deref.test b/compiler-rt/test/fuzzer/null-deref.test new file mode 100644 index 0000000..31eb599 --- /dev/null +++ b/compiler-rt/test/fuzzer/null-deref.test @@ -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 diff --git a/compiler-rt/test/fuzzer/trap.test b/compiler-rt/test/fuzzer/trap.test deleted file mode 100644 index c5944ae..0000000 --- a/compiler-rt/test/fuzzer/trap.test +++ /dev/null @@ -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 diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_line.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_line.cpp index 0da531e..208ece3 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_line.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_line.cpp @@ -14,11 +14,13 @@ int main(int argc, char **argv) { 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]+]] - // CHECK1: SUMMARY: [[SAN]]: SEGV {{.*}}signal_line.cpp:[[@LINE-3]]:[[TAB]] in main - - // CHECK2: #{{[0-9]+ .*}}main {{.*}}signal_line.cpp:[[@LINE-5]]:[[TAB:[0-9]+]] - // CHECK2: SUMMARY: [[SAN]]: SEGV {{.*}}signal_line.cpp:[[@LINE-6]]:[[TAB]] in main + if (n == 2) + *((volatile int *)0x1) = __LINE__; + // CHECK2: #{{[0-9]+ .*}}main {{.*}}signal_line.cpp:[[@LINE-1]]:[[TAB:[0-9]+]] + // CHECK2: SUMMARY: [[SAN]]: SEGV {{.*}}signal_line.cpp:[[@LINE-2]]:[[TAB]] in main } diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 7e4b7d0..e00bcf8 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2888,6 +2888,14 @@ Instruction *InstCombinerImpl::visitUnreachableInst(UnreachableInst &I) { // Otherwise, this instruction can be freely erased, // 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(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 // another unreachable block), so convert those to poison. replaceInstUsesWith(*Prev, PoisonValue::get(Prev->getType())); diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 31b4c0c..4bc3747 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -2302,6 +2302,9 @@ static bool markAliveBlocks(Function &F, // that they should be changed to unreachable by passes that can't // modify the CFG. + // Don't touch volatile stores. + if (SI->isVolatile()) continue; + Value *Ptr = SI->getOperand(1); if (isa(Ptr) || diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index fa4b8c9..f08ab18 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4672,6 +4672,14 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) { // Otherwise, this instruction can be freely erased, // 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(&*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 // of subtle reasoning. If this inst is an EH, all the predecessors of this // block will be the unwind edges of Invoke/CatchSwitch/CleanupReturn, diff --git a/llvm/test/CodeGen/AArch64/branch-relax-alignment.ll b/llvm/test/CodeGen/AArch64/branch-relax-alignment.ll index 9c1e569..c1d824b 100644 --- a/llvm/test/CodeGen/AArch64/branch-relax-alignment.ll +++ b/llvm/test/CodeGen/AArch64/branch-relax-alignment.ll @@ -4,7 +4,7 @@ ; Long branch is assumed because the block has a higher alignment ; 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: ; %bb.0: ; %common.ret ; 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: cset w0, ne ; CHECK-NEXT: csel w8, w9, w8, eq -; CHECK-NEXT: str w8, [x2] +; CHECK-NEXT: str w8, [x8] ; CHECK-NEXT: ret %1 = icmp eq i32 %x, %y br i1 %1, label %bb1, label %bb2 bb2: - store volatile i32 9, i32* %dst + store volatile i32 9, i32* undef ret i32 1 bb1: - store volatile i32 42, i32* %dst + store volatile i32 42, i32* undef ret i32 0 } diff --git a/llvm/test/CodeGen/AArch64/branch-relax-bcc.ll b/llvm/test/CodeGen/AArch64/branch-relax-bcc.ll index 377cb2c..3f9be3a 100644 --- a/llvm/test/CodeGen/AArch64/branch-relax-bcc.ll +++ b/llvm/test/CodeGen/AArch64/branch-relax-bcc.ll @@ -1,28 +1,27 @@ ; 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 -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: ; %bb.0: +; CHECK-NEXT: mov w0, wzr ; 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: LBB0_3: -; CHECK-NEXT: b.vc LBB0_1 -; CHECK-NEXT: b LBB0_2 -; CHECK-NEXT: LBB0_1: ; %bb2 +; CHECK-NEXT: b.gt LBB0_2 +; CHECK-NEXT: ; %bb.1: ; %common.ret +; 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: ; InlineAsm Start ; CHECK-NEXT: nop ; CHECK-NEXT: nop ; CHECK-NEXT: ; InlineAsm End -; CHECK-NEXT: str w8, [x0] -; 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: str w8, [x8] ; CHECK-NEXT: ret %1 = fcmp ueq float %x, %y br i1 %1, label %bb1, label %bb2 @@ -32,11 +31,11 @@ bb2: "nop nop", ""() #0 - store volatile i32 9, i32* %dst0 + store volatile i32 9, i32* undef ret i32 1 bb1: - store volatile i32 42, i32* %dst1 + store volatile i32 42, i32* undef ret i32 0 } diff --git a/llvm/test/CodeGen/AMDGPU/early-inline.ll b/llvm/test/CodeGen/AMDGPU/early-inline.ll index 4a3731b..eb53304 100644 --- a/llvm/test/CodeGen/AMDGPU/early-inline.ll +++ b/llvm/test/CodeGen/AMDGPU/early-inline.ll @@ -16,18 +16,18 @@ entry: ; CHECK: mul i32 ; CHECK-NOT: call i32 -define amdgpu_kernel void @caller(i32 %x, i32 addrspace(1)* %dst) { +define amdgpu_kernel void @caller(i32 %x) { entry: %res = call i32 @callee(i32 %x) - store volatile i32 %res, i32 addrspace(1)* %dst + store volatile i32 %res, i32 addrspace(1)* undef ret void } ; CHECK-LABEL: @alias_caller( ; CHECK-NOT: call -define amdgpu_kernel void @alias_caller(i32 %x, i32 addrspace(1)* %dst) { +define amdgpu_kernel void @alias_caller(i32 %x) { entry: %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 } diff --git a/llvm/test/CodeGen/X86/indirect-branch-tracking-eh2.ll b/llvm/test/CodeGen/X86/indirect-branch-tracking-eh2.ll index 32e984d..b6a6ff3 100644 --- a/llvm/test/CodeGen/X86/indirect-branch-tracking-eh2.ll +++ b/llvm/test/CodeGen/X86/indirect-branch-tracking-eh2.ll @@ -3,38 +3,51 @@ ; NUM-COUNT-3: endbr64 -; SJLJ-LABEL: main: -; SJLJ: # %bb.0: # %entry -; SJLJ-NEXT: endbr64 -; SJLJ: callq _Unwind_SjLj_Register@PLT -; SJLJ-NEXT: .Ltmp0: -; SJLJ-NEXT: callq _Z3foov -; SJLJ-NEXT: .Ltmp1: -; SJLJ-NEXT: # %bb.1: # %invoke.cont -; SJLJ: .LBB0_6: # %return -; SJLJ: callq _Unwind_SjLj_Unregister@PLT -; SJLJ: retq -; SJLJ-NEXT: .LBB0_7: -; SJLJ-NEXT: endbr64 -; SJLJ: jb .LBB0_8 -; SJLJ-NEXT: # %bb.9: -; SJLJ-NEXT: ud2 -; SJLJ-NEXT: .LBB0_8: -; SJLJ: jmpq *(%rcx,%rax,8) -; SJLJ-NEXT: .LBB0_2: # %lpad -; SJLJ-NEXT: .Ltmp2: -; SJLJ-NEXT: endbr64 -; SJLJ: jne .LBB0_4 -; SJLJ-NEXT: # %bb.3: # %catch3 -; SJLJ: callq __cxa_begin_catch -; SJLJ: jmp .LBB0_5 -; SJLJ-NEXT: .LBB0_4: # %catch -; SJLJ: callq __cxa_begin_catch -; SJLJ: cmpb $3, %al -; SJLJ-NEXT: .LBB0_5: # %return -; SJLJ-NEXT: setne %cl -; SJLJ: callq __cxa_end_catch -; SJLJ-NEXT: jmp .LBB0_6 +;SJLJ: main: # @main +;SJLJ-NEXT: .Lfunc_begin0: +;SJLJ-NEXT: # %bb.0: # %entry +;SJLJ-NEXT: endbr64 +;SJLJ-NEXT: pushq %rbp +;SJLJ: callq _Unwind_SjLj_Register +;SJLJ-NEXT: .Ltmp0: +;SJLJ-NEXT: callq _Z3foov +;SJLJ-NEXT: .Ltmp1: +;SJLJ-NEXT: # %bb.1: # %invoke.cont +;SJLJ-NEXT: movl +;SJLJ-NEXT: .LBB0_7: # %return +;SJLJ: callq _Unwind_SjLj_Unregister +;SJLJ: retq +;SJLJ-NEXT: .LBB0_9: +;SJLJ-NEXT: endbr64 +;SJLJ-NEXT: movl +;SJLJ-NEXT: cmpl +;SJLJ-NEXT: jb .LBB0_10 +;SJLJ-NEXT: # %bb.11: +;SJLJ-NEXT: ud2 +;SJLJ-NEXT: .LBB0_10: +;SJLJ-NEXT: leaq .LJTI0_0(%rip), %rcx +;SJLJ-NEXT: jmpq *(%rcx,%rax,8) +;SJLJ-NEXT: .LBB0_2: # %lpad +;SJLJ-NEXT: .Ltmp2: +;SJLJ-NEXT: endbr64 +;SJLJ: jne .LBB0_4 +;SJLJ-NEXT: # %bb.3: # %catch3 +;SJLJ: callq __cxa_begin_catch +;SJLJ: 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* @_ZTIc = external dso_local constant i8* diff --git a/llvm/test/Transforms/InstCombine/volatile_store.ll b/llvm/test/Transforms/InstCombine/volatile_store.ll index ae9e512..105ec83 100644 --- a/llvm/test/Transforms/InstCombine/volatile_store.ll +++ b/llvm/test/Transforms/InstCombine/volatile_store.ll @@ -25,6 +25,7 @@ define void @volatile_store_before_unreachable(i1 %c, i8* %p) { ; CHECK-LABEL: @volatile_store_before_unreachable( ; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: +; CHECK-NEXT: store volatile i8 0, i8* [[P:%.*]], align 1 ; CHECK-NEXT: unreachable ; CHECK: false: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll b/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll index 06b0242..e437f40 100644 --- a/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll +++ b/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll @@ -76,8 +76,8 @@ entry: define void @test3() nounwind { ; CHECK-LABEL: @test3( ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.trap() -; CHECK-NEXT: unreachable +; CHECK-NEXT: store volatile i32 4, i32* null, align 4 +; CHECK-NEXT: ret void ; entry: store volatile i32 4, i32* null @@ -101,8 +101,11 @@ entry: define void @test4(i1 %C, i32* %P) { ; CHECK-LABEL: @test4( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) +; CHECK-NEXT: br i1 [[C:%.*]], label [[T:%.*]], label [[F:%.*]] +; CHECK: T: +; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4 +; CHECK-NEXT: unreachable +; CHECK: F: ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/utils/unittest/googletest/src/gtest.cc b/llvm/utils/unittest/googletest/src/gtest.cc index 5c58404..a5b4e5a 100644 --- a/llvm/utils/unittest/googletest/src/gtest.cc +++ b/llvm/utils/unittest/googletest/src/gtest.cc @@ -4813,9 +4813,10 @@ void UnitTest::AddTestPartResult( // with clang/gcc we can achieve the same effect on x86 by invoking int3 asm("int3"); #else - // While some debuggers don't correctly trap abort(), we can't perform - // volatile store to null since it will be removed by clang and not trap. - __builtin_trap(); + // Dereference nullptr through a volatile pointer to prevent the compiler + // from removing. We use this rather than abort() or __builtin_trap() for + // portability: some debuggers don't correctly trap abort(). + *static_cast(nullptr) = 1; #endif // GTEST_OS_WINDOWS } else if (GTEST_FLAG(throw_on_failure)) { #if GTEST_HAS_EXCEPTIONS -- 2.7.4