diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/AST/HLSL/resource_binding_attr.hlsl | 3 | ||||
-rw-r--r-- | clang/test/AST/HLSL/vk_binding_attr.hlsl | 27 | ||||
-rw-r--r-- | clang/test/AST/ast-print-record-decl.c | 7 | ||||
-rw-r--r-- | clang/test/Analysis/Checkers/WebKit/objc-mock-types.h | 16 | ||||
-rw-r--r-- | clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm | 9 | ||||
-rw-r--r-- | clang/test/Analysis/LifetimeSafety/benchmark.py | 82 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/new.cpp | 53 | ||||
-rw-r--r-- | clang/test/CIR/IR/dynamic-cast.cir | 59 | ||||
-rw-r--r-- | clang/test/CIR/IR/invalid-dyn-cast.cir | 43 | ||||
-rw-r--r-- | clang/test/Driver/aarch64-cpu-defaults-appleos26.c | 10 | ||||
-rw-r--r-- | clang/test/Driver/darwin-maccatalyst-error.c | 6 | ||||
-rw-r--r-- | clang/test/Driver/darwin-maccatalyst.c | 5 | ||||
-rw-r--r-- | clang/test/Driver/env.c | 4 | ||||
-rw-r--r-- | clang/test/Driver/print-supported-extensions-riscv.c | 2 | ||||
-rw-r--r-- | clang/test/Driver/riscv-arch.c | 4 | ||||
-rw-r--r-- | clang/test/Preprocessor/riscv-target-features.c | 6 | ||||
-rw-r--r-- | clang/test/Sema/warn-lifetime-safety.cpp | 138 |
17 files changed, 394 insertions, 80 deletions
diff --git a/clang/test/AST/HLSL/resource_binding_attr.hlsl b/clang/test/AST/HLSL/resource_binding_attr.hlsl index c6d93b9..2de0674 100644 --- a/clang/test/AST/HLSL/resource_binding_attr.hlsl +++ b/clang/test/AST/HLSL/resource_binding_attr.hlsl @@ -92,9 +92,8 @@ cbuffer CB3 { StructuredBuffer<float> SB[10]; // CHECK: VarDecl {{.*}} SB2 'StructuredBuffer<float>[10]' +// CHECK: HLSLVkBindingAttr {{.*}} 2 0 // DXIL: HLSLResourceBindingAttr {{.*}} Implicit -// DXIL-NOT: HLSLVkBindingAttr -// SPV: HLSLVkBindingAttr {{.*}} 2 0 // SPV-NOT: HLSLResourceBindingAttr {{.*}} Implicit [[vk::binding(2)]] StructuredBuffer<float> SB2[10]; diff --git a/clang/test/AST/HLSL/vk_binding_attr.hlsl b/clang/test/AST/HLSL/vk_binding_attr.hlsl index d08165d..13e7544 100644 --- a/clang/test/AST/HLSL/vk_binding_attr.hlsl +++ b/clang/test/AST/HLSL/vk_binding_attr.hlsl @@ -10,8 +10,7 @@ // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 102 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 -// SPV: HLSLVkBindingAttr {{.*}} 23 102 -// DXIL-NOT: HLSLVkBindingAttr +// CHECK: HLSLVkBindingAttr {{.*}} 23 102 [[vk::binding(23, 102)]] StructuredBuffer<float> Buf; // CHECK: VarDecl {{.*}} Buf2 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>' @@ -23,8 +22,7 @@ // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 102 -// SPV: HLSLVkBindingAttr {{.*}} 14 1 -// DXIL-NOT: HLSLVkBindingAttr +// CHECK: HLSLVkBindingAttr {{.*}} 14 1 // CHECK: HLSLResourceBindingAttr {{.*}} "t23" "space102" [[vk::binding(14, 1)]] StructuredBuffer<float> Buf2 : register(t23, space102); @@ -37,15 +35,13 @@ // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 102 -// SPV: HLSLVkBindingAttr {{.*}} 14 0 -// DXIL-NOT: HLSLVkBindingAttr +// CHECK: HLSLVkBindingAttr {{.*}} 14 0 // CHECK: HLSLResourceBindingAttr {{.*}} "t23" "space102" [[vk::binding(14)]] StructuredBuffer<float> Buf3 : register(t23, space102); // CHECK: HLSLBufferDecl {{.*}} cbuffer CB // CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit CBuffer -// SPV-NEXT: HLSLVkBindingAttr {{.*}} 1 2 -// DXIL-NOT: HLSLVkBindingAttr +// CHECK: HLSLVkBindingAttr {{.*}} 1 2 [[vk::binding(1, 2)]] cbuffer CB { float a; } @@ -54,15 +50,14 @@ // CHECK-NEXT: CallExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::Buffer<int> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay> // SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)' -// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)' +// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)' // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 24 // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 103 -// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)' -// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)' +// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)' +// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)' // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 -// SPV: HLSLVkBindingAttr {{.*}} 24 103 -// DXIL-NOT: HLSLVkBindingAttr +// CHECK: HLSLVkBindingAttr {{.*}} 24 103 [[vk::binding(24, 103)]] Buffer<int> Buf4; // CHECK: VarDecl {{.*}} Buf5 'RWBuffer<int2>':'hlsl::RWBuffer<vector<int, 2>>' @@ -76,8 +71,7 @@ // DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer<int2> (unsigned int, unsigned int, int, unsigned int, const char *)' // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 -// SPV: HLSLVkBindingAttr {{.*}} 25 104 -// DXIL-NOT: HLSLVkBindingAttr +// CHECK: HLSLVkBindingAttr {{.*}} 25 104 [[vk::binding(25, 104)]] RWBuffer<int2> Buf5; // CHECK: VarDecl {{.*}} Buf6 'RWStructuredBuffer<int>':'hlsl::RWStructuredBuffer<int>' @@ -91,6 +85,5 @@ // DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)' // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 4 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 -// SPV: HLSLVkBindingAttr {{.*}} 26 105 -// DXIL-NOT: HLSLVkBindingAttr +// CHECK: HLSLVkBindingAttr {{.*}} 26 105 [[vk::binding(26, 105)]] RWStructuredBuffer<int> Buf6; diff --git a/clang/test/AST/ast-print-record-decl.c b/clang/test/AST/ast-print-record-decl.c index fd81588..394f837 100644 --- a/clang/test/AST/ast-print-record-decl.c +++ b/clang/test/AST/ast-print-record-decl.c @@ -315,4 +315,11 @@ template <int, int = 0> KW SmearedNTTPDefArgs; // PRINT-CXX-NEXT: template <int = 0, int> [[KW]] SmearedNTTPDefArgs; template <int = 0, int> KW SmearedNTTPDefArgs; +// PRINT-CXX-LABEL: Tpl +template <int> KW Tpl; +// PRINT-CXX-NEXT: template <template <int> class, template <int> class = Tpl> [[KW]] SmearedTplDefArgs; +template <template <int> class, template <int> class = Tpl> KW SmearedTplDefArgs; +// PRINT-CXX-NEXT: template <template <int> class = Tpl, template <int> class> [[KW]] SmearedTplDefArgs; +template <template <int> class = Tpl, template <int> class> KW SmearedTplDefArgs; + #endif diff --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h index dacb713..a5fc3d7 100644 --- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h @@ -178,6 +178,22 @@ __attribute__((objc_root_class)) + (NSNumber *)numberWithBool:(BOOL)value; @end +@interface NSResponder : NSObject +@end + +@interface NSApplication : NSResponder + +extern NSApplication * NSApp; + +@property (class, readonly, strong) NSApplication *sharedApplication; + +- (void)finishLaunching; +- (void)run; +- (void)stop:(id)sender; +- (void)terminate:(id)sender; + +@end + @interface SomeObj : NSObject - (instancetype)_init; - (SomeObj *)mutableCopy; diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm index c9d2fe8..a517dbc 100644 --- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm +++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm @@ -398,12 +398,18 @@ namespace call_with_cf_constant { void baz(const NSDictionary *); void boo(NSNumber *); void boo(CFTypeRef); - void foo() { + + struct Details { + int value; + }; + + void foo(Details* details) { CFArrayCreateMutable(kCFAllocatorDefault, 10); bar(@[@"hello"]); baz(@{@"hello": @3}); boo(@YES); boo(@NO); + boo(@(details->value)); } } @@ -582,6 +588,7 @@ struct Derived : Base { [self doWork:@"hello", RetainPtr<SomeObj> { provide() }.get(), RetainPtr<CFMutableArrayRef> { provide_cf() }.get(), OSObjectPtr { provide_dispatch() }.get()]; [self doWork:__null]; [self doWork:nil]; + [NSApp run]; } - (SomeObj *)getSomeObj { diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py b/clang/test/Analysis/LifetimeSafety/benchmark.py index d2e5f0b..cd5b3081 100644 --- a/clang/test/Analysis/LifetimeSafety/benchmark.py +++ b/clang/test/Analysis/LifetimeSafety/benchmark.py @@ -145,6 +145,60 @@ def generate_cpp_nested_loop_test(n: int) -> str: return cpp_code +def generate_cpp_switch_fan_out_test(n: int) -> str: + """ + Generates C++ code with a switch statement with N branches. + Each branch 'i' 'uses' (reads) a single, unique pointer 'pi'. + This pattern creates a "fan-in" join point for the backward + liveness analysis, stressing the LivenessMap::join operation + by forcing it to merge N disjoint, single-element sets of live origins. + The resulting complexity for LiveOrigins should be O(n log n) or higher. + + Example (n=3): + struct MyObj { int id; ~MyObj() {} }; + + void switch_fan_out_3(int condition) { + MyObj v1{1}; MyObj v2{1}; MyObj v3{1}; + MyObj* p1 = &v1; MyObj* p2 = &v2; MyObj* p3 = &v3; + + switch (condition % 3) { + case 0: + p1->id = 1; + break; + case 1: + p2->id = 1; + break; + case 2: + p3->id = 1; + break; + } + } + """ + if n <= 0: + return "// Number of variables must be positive." + + cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n" + cpp_code += f"void switch_fan_out{n}(int condition) {{\n" + # Generate N distinct objects + for i in range(1, n + 1): + cpp_code += f" MyObj v{i}{{1}};\n" + cpp_code += "\n" + # Generate N distinct pointers, each as a separate variable + for i in range(1, n + 1): + cpp_code += f" MyObj* p{i} = &v{i};\n" + cpp_code += "\n" + + cpp_code += f" switch (condition % {n}) {{\n" + for case_num in range(n): + cpp_code += f" case {case_num}:\n" + cpp_code += f" p{case_num + 1}->id = 1;\n" + cpp_code += " break;\n" + + cpp_code += " }\n}\n" + cpp_code += f"\nint main() {{ switch_fan_out{n}(0); return 0; }}\n" + return cpp_code + + def analyze_trace_file(trace_path: str) -> dict: """ Parses the -ftime-trace JSON output to find durations for the lifetime @@ -156,14 +210,14 @@ def analyze_trace_file(trace_path: str) -> dict: "total_us": 0.0, "fact_gen_us": 0.0, "loan_prop_us": 0.0, - "expired_loans_us": 0.0, + "live_origins_us": 0.0, } event_name_map = { "LifetimeSafetyAnalysis": "lifetime_us", "ExecuteCompiler": "total_us", "FactGenerator": "fact_gen_us", "LoanPropagation": "loan_prop_us", - "ExpiredLoans": "expired_loans_us", + "LiveOrigins": "live_origins_us", } try: with open(trace_path, "r") as f: @@ -227,7 +281,7 @@ def generate_markdown_report(results: dict) -> str: # Table header report.append( - "| N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Expired Loans (%) |" + "| N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Live Origins (%) |" ) report.append( "|:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:|" @@ -247,7 +301,7 @@ def generate_markdown_report(results: dict) -> str: f"{data['lifetime_ms'][i] / total_t * 100:>17.2f}% |", f"{data['fact_gen_ms'][i] / total_t * 100:>18.2f}% |", f"{data['loan_prop_ms'][i] / total_t * 100:>20.2f}% |", - f"{data['expired_loans_ms'][i] / total_t * 100:>17.2f}% |", + f"{data['live_origins_ms'][i] / total_t * 100:>17.2f}% |", ] report.append(" ".join(row)) @@ -259,7 +313,7 @@ def generate_markdown_report(results: dict) -> str: "Total Analysis": data["lifetime_ms"], "FactGenerator": data["fact_gen_ms"], "LoanPropagation": data["loan_prop_ms"], - "ExpiredLoans": data["expired_loans_ms"], + "LiveOrigins": data["live_origins_ms"], } for phase_name, y_data in analysis_phases.items(): @@ -302,7 +356,13 @@ def run_single_test( source_file, ] - result = subprocess.run(clang_command, capture_output=True, text=True, timeout=60) + try: + result = subprocess.run( + clang_command, capture_output=True, text=True, timeout=60 + ) + except subprocess.TimeoutExpired: + print(f"Compilation timed out for N={n}!", file=sys.stderr) + return {} if result.returncode != 0: print(f"Compilation failed for N={n}!", file=sys.stderr) @@ -354,6 +414,12 @@ if __name__ == "__main__": "generator_func": generate_cpp_nested_loop_test, "n_values": [50, 100, 150, 200], }, + { + "name": "switch_fan_out", + "title": "Switch Fan-out", + "generator_func": generate_cpp_switch_fan_out_test, + "n_values": [500, 1000, 2000, 4000], + }, ] results = {} @@ -368,7 +434,7 @@ if __name__ == "__main__": "total_ms": [], "fact_gen_ms": [], "loan_prop_ms": [], - "expired_loans_ms": [], + "live_origins_ms": [], } for n in config["n_values"]: durations_ms = run_single_test( @@ -387,7 +453,7 @@ if __name__ == "__main__": f" Total Analysis: {human_readable_time(durations_ms['lifetime_ms'])} | " f"FactGen: {human_readable_time(durations_ms['fact_gen_ms'])} | " f"LoanProp: {human_readable_time(durations_ms['loan_prop_ms'])} | " - f"ExpiredLoans: {human_readable_time(durations_ms['expired_loans_ms'])}" + f"LiveOrigins: {human_readable_time(durations_ms['live_origins_ms'])}" ) print("\n\n" + "=" * 80) diff --git a/clang/test/CIR/CodeGen/new.cpp b/clang/test/CIR/CodeGen/new.cpp index 3dcf7af..000ea5b 100644 --- a/clang/test/CIR/CodeGen/new.cpp +++ b/clang/test/CIR/CodeGen/new.cpp @@ -180,3 +180,56 @@ void test_new_with_complex_type() { // OGCG: store float 1.000000e+00, ptr %[[COMPLEX_REAL_PTR]], align 8 // OGCG: store float 2.000000e+00, ptr %[[COMPLEX_IMAG_PTR]], align 4 // OGCG: store ptr %[[NEW_COMPLEX]], ptr %[[A_ADDR]], align 8 + +void t_new_constant_size() { + auto p = new double[16]; +} + +// In this test, NUM_ELEMENTS isn't used because no cookie is needed and there +// are no constructor calls needed. + +// CHECK: cir.func{{.*}} @_Z19t_new_constant_sizev() +// CHECK: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!cir.double>, !cir.ptr<!cir.ptr<!cir.double>>, ["p", init] {alignment = 8 : i64} +// CHECK: %[[#NUM_ELEMENTS:]] = cir.const #cir.int<16> : !u64i +// CHECK: %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<128> : !u64i +// CHECK: %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : (!u64i) -> !cir.ptr<!void> +// CHECK: %[[TYPED_PTR:.*]] = cir.cast bitcast %[[RAW_PTR]] : !cir.ptr<!void> -> !cir.ptr<!cir.double> +// CHECK: cir.store align(8) %[[TYPED_PTR]], %[[P_ADDR]] : !cir.ptr<!cir.double>, !cir.ptr<!cir.ptr<!cir.double>> +// CHECK: cir.return +// CHECK: } + +// LLVM: define{{.*}} void @_Z19t_new_constant_sizev +// LLVM: %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[CALL:.*]] = call ptr @_Znam(i64 128) +// LLVM: store ptr %[[CALL]], ptr %[[P_ADDR]], align 8 + +// OGCG: define{{.*}} void @_Z19t_new_constant_sizev +// OGCG: %[[P_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[CALL:.*]] = call noalias noundef nonnull ptr @_Znam(i64 noundef 128) +// OGCG: store ptr %[[CALL]], ptr %[[P_ADDR]], align 8 + + +void t_new_multidim_constant_size() { + auto p = new double[2][3][4]; +} + +// As above, NUM_ELEMENTS isn't used. + +// CHECK: cir.func{{.*}} @_Z28t_new_multidim_constant_sizev() +// CHECK: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>, !cir.ptr<!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>>, ["p", init] {alignment = 8 : i64} +// CHECK: %[[#NUM_ELEMENTS:]] = cir.const #cir.int<24> : !u64i +// CHECK: %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<192> : !u64i +// CHECK: %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : (!u64i) -> !cir.ptr<!void> +// CHECK: %[[TYPED_PTR:.*]] = cir.cast bitcast %[[RAW_PTR]] : !cir.ptr<!void> -> !cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>> +// CHECK: cir.store align(8) %[[TYPED_PTR]], %[[P_ADDR]] : !cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>, !cir.ptr<!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>> +// CHECK: } + +// LLVM: define{{.*}} void @_Z28t_new_multidim_constant_sizev +// LLVM: %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[CALL:.*]] = call ptr @_Znam(i64 192) +// LLVM: store ptr %[[CALL]], ptr %[[P_ADDR]], align 8 + +// OGCG: define{{.*}} void @_Z28t_new_multidim_constant_sizev +// OGCG: %[[P_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[CALL:.*]] = call noalias noundef nonnull ptr @_Znam(i64 noundef 192) +// OGCG: store ptr %[[CALL]], ptr %[[P_ADDR]], align 8 diff --git a/clang/test/CIR/IR/dynamic-cast.cir b/clang/test/CIR/IR/dynamic-cast.cir new file mode 100644 index 0000000..283f11e --- /dev/null +++ b/clang/test/CIR/IR/dynamic-cast.cir @@ -0,0 +1,59 @@ +// RUN: cir-opt --verify-roundtrip %s | FileCheck %s + +!s64i = !cir.int<s, 64> +!u8i = !cir.int<u, 8> +!void = !cir.void + +!rec_Base = !cir.record<struct "Base" {!cir.vptr}> +!rec_Derived = !cir.record<struct "Derived" {!rec_Base}> + +#dyn_cast_info__ZTI4Base__ZTI7Derived = #cir.dyn_cast_info<src_rtti = #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>, dest_rtti = #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>, runtime_func = @__dynamic_cast, bad_cast_func = @__cxa_bad_cast, offset_hint = #cir.int<0> : !s64i> + +// CHECK: #dyn_cast_info__ZTI4Base__ZTI7Derived = #cir.dyn_cast_info<src_rtti = #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>, dest_rtti = #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>, runtime_func = @__dynamic_cast, bad_cast_func = @__cxa_bad_cast, offset_hint = #cir.int<0> : !s64i> + +module { + cir.global "private" constant external @_ZTI4Base : !cir.ptr<!u8i> + cir.global "private" constant external @_ZTI7Derived : !cir.ptr<!u8i> + cir.func private @__dynamic_cast(!cir.ptr<!void>, !cir.ptr<!u8i>, !cir.ptr<!u8i>, !s64i) -> !cir.ptr<!void> + cir.func private @__cxa_bad_cast() + + cir.func @test_ptr_cast(%arg0: !cir.ptr<!rec_Base>) -> !cir.ptr<!rec_Derived> { + %0 = cir.dyn_cast ptr %arg0 : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> #dyn_cast_info__ZTI4Base__ZTI7Derived + cir.return %0 : !cir.ptr<!rec_Derived> + } + + // CHECK: cir.func @test_ptr_cast(%arg0: !cir.ptr<!rec_Base>) -> !cir.ptr<!rec_Derived> { + // CHECK: %0 = cir.dyn_cast ptr %arg0 : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> #dyn_cast_info__ZTI4Base__ZTI7Derived + // CHECK: cir.return %0 : !cir.ptr<!rec_Derived> + // CHECK: } + + cir.func @test_ref_cast(%arg0: !cir.ptr<!rec_Base>) -> !cir.ptr<!rec_Derived> { + %0 = cir.dyn_cast ref %arg0 : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> #dyn_cast_info__ZTI4Base__ZTI7Derived + cir.return %0 : !cir.ptr<!rec_Derived> + } + + // CHECK: cir.func @test_ref_cast(%arg0: !cir.ptr<!rec_Base>) -> !cir.ptr<!rec_Derived> { + // CHECK: %0 = cir.dyn_cast ref %arg0 : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> #dyn_cast_info__ZTI4Base__ZTI7Derived + // CHECK: cir.return %0 : !cir.ptr<!rec_Derived> + // CHECK: } + + cir.func dso_local @test_cast_to_void(%arg0: !cir.ptr<!rec_Base>) -> !cir.ptr<!void> { + %0 = cir.dyn_cast ptr %arg0 : !cir.ptr<!rec_Base> -> !cir.ptr<!void> + cir.return %0 : !cir.ptr<!void> + } + + // CHECK: cir.func dso_local @test_cast_to_void(%arg0: !cir.ptr<!rec_Base>) -> !cir.ptr<!void> { + // CHECK: %0 = cir.dyn_cast ptr %arg0 : !cir.ptr<!rec_Base> -> !cir.ptr<!void> + // CHECK: cir.return %0 : !cir.ptr<!void> + // CHECK: } + + cir.func dso_local @test_relative_layout_cast(%arg0: !cir.ptr<!rec_Base>) -> !cir.ptr<!void> { + %0 = cir.dyn_cast ptr relative_layout %arg0 : !cir.ptr<!rec_Base> -> !cir.ptr<!void> + cir.return %0 : !cir.ptr<!void> + } + + // CHECK: cir.func dso_local @test_relative_layout_cast(%arg0: !cir.ptr<!rec_Base>) -> !cir.ptr<!void> { + // CHECK: %0 = cir.dyn_cast ptr relative_layout %arg0 : !cir.ptr<!rec_Base> -> !cir.ptr<!void> + // CHECK: cir.return %0 : !cir.ptr<!void> + // CHECK: } +} diff --git a/clang/test/CIR/IR/invalid-dyn-cast.cir b/clang/test/CIR/IR/invalid-dyn-cast.cir new file mode 100644 index 0000000..65c7fc1 --- /dev/null +++ b/clang/test/CIR/IR/invalid-dyn-cast.cir @@ -0,0 +1,43 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +!s64i = !cir.int<s, 64> +!s8i = !cir.int<s, 8> +!u32i = !cir.int<u, 32> +!u8i = !cir.int<u, 8> +!void = !cir.void + +!Base = !cir.record<struct "Base" {!cir.ptr<!cir.ptr<!cir.func<() -> !cir.int<u, 32>>>>}> +!Derived = !cir.record<struct "Derived" {!cir.record<struct "Base" {!cir.ptr<!cir.ptr<!cir.func<() -> !cir.int<u, 32>>>>}>}> + +module { + cir.global "private" constant external @_ZTI4Base : !cir.ptr<!u32i> + cir.global "private" constant external @_ZTI7Derived : !cir.ptr<!u8i> + cir.func private @__dynamic_cast(!cir.ptr<!void>, !cir.ptr<!u8i>, !cir.ptr<!u8i>, !s64i) -> !cir.ptr<!void> + cir.func private @__cxa_bad_cast() + cir.func @test(%arg0 : !cir.ptr<!Base>) { + // expected-error@+1 {{srcRtti must be an RTTI pointer}} + %0 = cir.dyn_cast ptr %arg0 : !cir.ptr<!Base> -> !cir.ptr<!Derived> #cir.dyn_cast_info<src_rtti = #cir.global_view<@_ZTI4Base> : !cir.ptr<!u32i>, dest_rtti = #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>, runtime_func = @__dynamic_cast, bad_cast_func = @__cxa_bad_cast, offset_hint = #cir.int<0> : !s64i> + } +} + +// ----- + +!s64i = !cir.int<s, 64> +!s8i = !cir.int<s, 8> +!u32i = !cir.int<u, 32> +!u8i = !cir.int<u, 8> +!void = !cir.void + +!Base = !cir.record<struct "Base" {!cir.ptr<!cir.ptr<!cir.func<() -> !cir.int<u, 32>>>>}> +!Derived = !cir.record<struct "Derived" {!cir.record<struct "Base" {!cir.ptr<!cir.ptr<!cir.func<() -> !cir.int<u, 32>>>>}>}> + +module { + cir.global "private" constant external @_ZTI4Base : !cir.ptr<!u8i> + cir.global "private" constant external @_ZTI7Derived : !cir.ptr<!u32i> + cir.func private @__dynamic_cast(!cir.ptr<!void>, !cir.ptr<!u8i>, !cir.ptr<!u8i>, !s64i) -> !cir.ptr<!void> + cir.func private @__cxa_bad_cast() + cir.func @test(%arg0 : !cir.ptr<!Base>) { + // expected-error@+1 {{destRtti must be an RTTI pointer}} + %0 = cir.dyn_cast ptr %arg0 : !cir.ptr<!Base> -> !cir.ptr<!Derived> #cir.dyn_cast_info<src_rtti = #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>, dest_rtti = #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u32i>, runtime_func = @__dynamic_cast, bad_cast_func = @__cxa_bad_cast, offset_hint = #cir.int<0> : !s64i> + } +} diff --git a/clang/test/Driver/aarch64-cpu-defaults-appleos26.c b/clang/test/Driver/aarch64-cpu-defaults-appleos26.c index 9917605..fe468a5 100644 --- a/clang/test/Driver/aarch64-cpu-defaults-appleos26.c +++ b/clang/test/Driver/aarch64-cpu-defaults-appleos26.c @@ -4,12 +4,16 @@ // RUN: %clang -target arm64-apple-ios26 -### -c %s 2>&1 | FileCheck %s --check-prefix=A12 // RUN: %clang -target arm64e-apple-ios26 -### -c %s 2>&1 | FileCheck %s --check-prefix=A12 +/// iOS 18 came before iOS 26, compare its defaults. +// RUN: %clang -target arm64-apple-ios18 -### -c %s 2>&1 | FileCheck %s --check-prefix=A10 +// RUN: %clang -target arm64e-apple-ios18 -### -c %s 2>&1 | FileCheck %s --check-prefix=A12 + /// arm64e/arm64_32 watchOS 26 default to apple-s6. // RUN: %clang -target arm64e-apple-watchos26 -### -c %s 2>&1 | FileCheck %s --check-prefix=S6 // RUN: %clang -target arm64_32-apple-watchos26 -### -c %s 2>&1 | FileCheck %s --check-prefix=S6 -/// arm64 is new in watchOS 26, and defaults to apple-s6. -// RUN: %clang -target arm64-apple-watchos26 -### -c %s 2>&1 | FileCheck %s --check-prefix=S6 +/// arm64 is new in watchOS 26, and defaults to apple-s9. +// RUN: %clang -target arm64-apple-watchos26 -### -c %s 2>&1 | FileCheck %s --check-prefix=S9 /// llvm usually treats tvOS like iOS, but it runs on different hardware. // RUN: %clang -target arm64-apple-tvos26 -### -c %s 2>&1 | FileCheck %s --check-prefix=A7 @@ -18,5 +22,7 @@ /// Simulators are tested with other Mac-like targets in aarch64-mac-cpus.c. // A12: "-target-cpu" "apple-a12" +// A10: "-target-cpu" "apple-a10" // S6: "-target-cpu" "apple-s6" +// S9: "-target-cpu" "apple-s9" // A7: "-target-cpu" "apple-a7" diff --git a/clang/test/Driver/darwin-maccatalyst-error.c b/clang/test/Driver/darwin-maccatalyst-error.c new file mode 100644 index 0000000..009249b --- /dev/null +++ b/clang/test/Driver/darwin-maccatalyst-error.c @@ -0,0 +1,6 @@ +// RUN: not %clang -target x86_64-apple-ios13.0-macabi -c %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-ERROR %s +// RUN: not %clang -target x86_64-apple-ios12.0-macabi -c %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-ERROR %s + +// CHECK-ERROR: error: invalid version number in '-target x86_64-apple-ios diff --git a/clang/test/Driver/darwin-maccatalyst.c b/clang/test/Driver/darwin-maccatalyst.c index 74a02ed..a8d53df 100644 --- a/clang/test/Driver/darwin-maccatalyst.c +++ b/clang/test/Driver/darwin-maccatalyst.c @@ -2,11 +2,6 @@ // RUN: FileCheck --check-prefix=CHECK-VERSION1 %s // RUN: %clang -target x86_64-apple-ios-macabi -c %s -### 2>&1 | \ // RUN: FileCheck --check-prefix=CHECK-VERSION1 %s -// RUN: not %clang -target x86_64-apple-ios13.0-macabi -c %s -### 2>&1 | \ -// RUN: FileCheck --check-prefix=CHECK-ERROR %s -// RUN: not %clang -target x86_64-apple-ios12.0-macabi -c %s -### 2>&1 | \ -// RUN: FileCheck --check-prefix=CHECK-ERROR %s // CHECK-VERSION1-NOT: error: // CHECK-VERSION1: "x86_64-apple-ios13.1.0-macabi" -// CHECK-ERROR: error: invalid version number in '-target x86_64-apple-ios diff --git a/clang/test/Driver/env.c b/clang/test/Driver/env.c index 56c037c..d1267c0 100644 --- a/clang/test/Driver/env.c +++ b/clang/test/Driver/env.c @@ -1,5 +1,7 @@ // Some assertions in this test use Linux style (/) file paths. -// UNSUPPORTED: system-windows +// TODO: Use LIBPATH on AIX +// UNSUPPORTED: system-windows, system-aix + // RUN: bash -c env | grep LD_LIBRARY_PATH | sed -ne 's/^.*=//p' | tr -d '\n' > %t.ld_library_path // The PATH variable is heavily used when trying to find a linker. // RUN: env -i LC_ALL=C LD_LIBRARY_PATH="%{readfile:%t.ld_library_path}" CLANG_NO_DEFAULT_CONFIG=1 \ diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c index c44a0e8..7972b9e 100644 --- a/clang/test/Driver/print-supported-extensions-riscv.c +++ b/clang/test/Driver/print-supported-extensions-riscv.c @@ -216,7 +216,7 @@ // CHECK-NEXT: zibi 0.1 'Zibi' (Branch with Immediate) // CHECK-NEXT: zicfilp 1.0 'Zicfilp' (Landing pad) // CHECK-NEXT: zicfiss 1.0 'Zicfiss' (Shadow stack) -// CHECK-NEXT: zalasr 0.1 'Zalasr' (Load-Acquire and Store-Release Instructions) +// CHECK-NEXT: zalasr 0.9 'Zalasr' (Load-Acquire and Store-Release Instructions) // CHECK-NEXT: zvbc32e 0.7 'Zvbc32e' (Vector Carryless Multiplication with 32-bits elements) // CHECK-NEXT: zvfbfa 0.1 'Zvfbfa' (Additional BF16 vector compute support) // CHECK-NEXT: zvfofp8min 0.2 'Zvfofp8min' (Vector OFP8 Converts) diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c index 1da8311..37fe7a0 100644 --- a/clang/test/Driver/riscv-arch.c +++ b/clang/test/Driver/riscv-arch.c @@ -384,9 +384,9 @@ // RUN: not %clang --target=riscv32-unknown-elf -march=rv32izalasr0p7 -menable-experimental-extensions -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-BADVERS %s // RV32-EXPERIMENTAL-BADVERS: error: invalid arch name 'rv32izalasr0p7' -// RV32-EXPERIMENTAL-BADVERS: unsupported version number 0.7 for experimental extension 'zalasr' (this compiler supports 0.1) +// RV32-EXPERIMENTAL-BADVERS: unsupported version number 0.7 for experimental extension 'zalasr' (this compiler supports 0.9) -// RUN: %clang --target=riscv32-unknown-elf -march=rv32izalasr0p1 -menable-experimental-extensions -### %s \ +// RUN: %clang --target=riscv32-unknown-elf -march=rv32izalasr0p9 -menable-experimental-extensions -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-GOODVERS %s // RV32-EXPERIMENTAL-GOODVERS: "-target-feature" "+experimental-zalasr" diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 71d8453..77731a9 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -1531,12 +1531,12 @@ // Experimental extensions // RUN: %clang --target=riscv32 -menable-experimental-extensions \ -// RUN: -march=rv32i_zalasr0p1 -E -dM %s \ +// RUN: -march=rv32i_zalasr0p9 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZALASR-EXT %s // RUN: %clang --target=riscv64 -menable-experimental-extensions \ -// RUN: -march=rv64i_zalasr0p1 -E -dM %s \ +// RUN: -march=rv64i_zalasr0p9 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZALASR-EXT %s -// CHECK-ZALASR-EXT: __riscv_zalasr 1000{{$}} +// CHECK-ZALASR-EXT: __riscv_zalasr 9000{{$}} // RUN: %clang --target=riscv32 -menable-experimental-extensions \ // RUN: -march=rv32izfbfmin1p0 -E -dM %s \ diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp index f6bec6e..4f234f0 100644 --- a/clang/test/Sema/warn-lifetime-safety.cpp +++ b/clang/test/Sema/warn-lifetime-safety.cpp @@ -126,11 +126,15 @@ void definite_single_pointer_multiple_loans_gsl(bool cond) { v.use(); // expected-note 2 {{later used here}} } - -//===----------------------------------------------------------------------===// -// Potential (Maybe) Use-After-Free (-W...strict) -// These are cases where the pointer *may* become dangling, depending on the path taken. -//===----------------------------------------------------------------------===// +void definite_if_branch(bool cond) { + MyObj safe; + MyObj* p = &safe; + if (cond) { + MyObj temp; + p = &temp; // expected-warning {{object whose reference is captured does not live long enough}} + } // expected-note {{destroyed here}} + (void)*p; // expected-note {{later used here}} +} void potential_if_branch(bool cond) { MyObj safe; @@ -139,15 +143,18 @@ void potential_if_branch(bool cond) { MyObj temp; p = &temp; // expected-warning {{object whose reference is captured may not live long enough}} } // expected-note {{destroyed here}} - (void)*p; // expected-note {{later used here}} + if (!cond) + (void)*p; // expected-note {{later used here}} + else + p = &safe; } -void potential_if_branch_gsl(bool cond) { +void definite_if_branch_gsl(bool cond) { MyObj safe; View v = safe; if (cond) { MyObj temp; - v = temp; // expected-warning {{object whose reference is captured may not live long enough}} + v = temp; // expected-warning {{object whose reference is captured does not live long enough}} } // expected-note {{destroyed here}} v.use(); // expected-note {{later used here}} } @@ -159,13 +166,14 @@ void definite_potential_together(bool cond) { { MyObj s; - p_definite = &s; // expected-warning {{does not live long enough}} - if (cond) { - p_maybe = &s; // expected-warning {{may not live long enough}} - } - } // expected-note 2 {{destroyed here}} - (void)*p_definite; // expected-note {{later used here}} - (void)*p_maybe; // expected-note {{later used here}} + if (cond) + p_definite = &s; // expected-warning {{does not live long enough}} + if (cond) + p_maybe = &s; // expected-warning {{may not live long enough}} + } // expected-note 2 {{destroyed here}} + (void)*p_definite; // expected-note {{later used here}} + if (!cond) + (void)*p_maybe; // expected-note {{later used here}} } void definite_overrides_potential(bool cond) { @@ -189,10 +197,19 @@ void definite_overrides_potential(bool cond) { (void)*q; } - -//===----------------------------------------------------------------------===// -// Control Flow Tests -//===----------------------------------------------------------------------===// +void potential_due_to_conditional_killing(bool cond) { + MyObj safe; + MyObj* q; + { + MyObj s; + q = &s; // expected-warning {{may not live long enough}} + } // expected-note {{destroyed here}} + if (cond) { + // 'q' is conditionally "rescued". 'p' is not. + q = &safe; + } + (void)*q; // expected-note {{later used here}} +} void potential_for_loop_use_after_loop_body(MyObj safe) { MyObj* p = &safe; @@ -215,34 +232,35 @@ void potential_for_loop_gsl() { void potential_for_loop_use_before_loop_body(MyObj safe) { MyObj* p = &safe; + // Prefer the earlier use for diagnsotics. for (int i = 0; i < 1; ++i) { (void)*p; // expected-note {{later used here}} MyObj s; - p = &s; // expected-warning {{may not live long enough}} + p = &s; // expected-warning {{does not live long enough}} } // expected-note {{destroyed here}} (void)*p; } -void potential_loop_with_break(bool cond) { +void definite_loop_with_break(bool cond) { MyObj safe; MyObj* p = &safe; for (int i = 0; i < 10; ++i) { if (cond) { MyObj temp; - p = &temp; // expected-warning {{may not live long enough}} + p = &temp; // expected-warning {{does not live long enough}} break; // expected-note {{destroyed here}} } } (void)*p; // expected-note {{later used here}} } -void potential_loop_with_break_gsl(bool cond) { +void definite_loop_with_break_gsl(bool cond) { MyObj safe; View v = safe; for (int i = 0; i < 10; ++i) { if (cond) { MyObj temp; - v = temp; // expected-warning {{object whose reference is captured may not live long enough}} + v = temp; // expected-warning {{object whose reference is captured does not live long enough}} break; // expected-note {{destroyed here}} } } @@ -250,37 +268,52 @@ void potential_loop_with_break_gsl(bool cond) { } void potential_multiple_expiry_of_same_loan(bool cond) { - // Choose the last expiry location for the loan. + // Choose the last expiry location for the loan (e.g., through scope-ends and break statements). MyObj safe; MyObj* p = &safe; for (int i = 0; i < 10; ++i) { MyObj unsafe; if (cond) { - p = &unsafe; // expected-warning {{may not live long enough}} - break; + p = &unsafe; // expected-warning {{does not live long enough}} + break; // expected-note {{destroyed here}} } - } // expected-note {{destroyed here}} + } (void)*p; // expected-note {{later used here}} p = &safe; for (int i = 0; i < 10; ++i) { MyObj unsafe; if (cond) { - p = &unsafe; // expected-warning {{may not live long enough}} + p = &unsafe; // expected-warning {{does not live long enough}} if (cond) - break; + break; // expected-note {{destroyed here}} } - } // expected-note {{destroyed here}} + } (void)*p; // expected-note {{later used here}} p = &safe; for (int i = 0; i < 10; ++i) { if (cond) { MyObj unsafe2; - p = &unsafe2; // expected-warning {{may not live long enough}} + p = &unsafe2; // expected-warning {{does not live long enough}} break; // expected-note {{destroyed here}} } } + + // TODO: This can be argued to be a "maybe" warning. This is because + // we only check for confidence of liveness and not the confidence of + // the loan contained in an origin. To deal with this, we can introduce + // a confidence in loan propagation analysis as well like liveness. + (void)*p; // expected-note {{later used here}} + + p = &safe; + for (int i = 0; i < 10; ++i) { + MyObj unsafe; + if (cond) + p = &unsafe; // expected-warning {{does not live long enough}} + if (cond) + break; // expected-note {{destroyed here}} + } (void)*p; // expected-note {{later used here}} } @@ -298,13 +331,14 @@ void potential_switch(int mode) { break; } } - (void)*p; // expected-note {{later used here}} + if (mode == 2) + (void)*p; // expected-note {{later used here}} } void definite_switch(int mode) { MyObj safe; MyObj* p = &safe; - // All cases are UaF --> Definite error. + // A use domintates all the loan expires --> all definite error. switch (mode) { case 1: { MyObj temp1; @@ -347,6 +381,21 @@ void definite_switch_gsl(int mode) { v.use(); // expected-note 3 {{later used here}} } +void loan_from_previous_iteration(MyObj safe, bool condition) { + MyObj* p = &safe; + MyObj* q = &safe; + + while (condition) { + MyObj x; + p = &x; // expected-warning {{may not live long enough}} + + if (condition) + q = p; + (void)*p; + (void)*q; // expected-note {{later used here}} + } // expected-note {{destroyed here}} +} + //===----------------------------------------------------------------------===// // No-Error Cases //===----------------------------------------------------------------------===// @@ -372,6 +421,19 @@ void no_error_if_dangle_then_rescue_gsl() { v.use(); // This is safe. } +void no_error_loan_from_current_iteration(bool cond) { + // See https://github.com/llvm/llvm-project/issues/156959. + MyObj b; + while (cond) { + MyObj a; + View p = b; + if (cond) { + p = a; + } + (void)p; + } +} + //===----------------------------------------------------------------------===// // Lifetimebound Attribute Tests @@ -415,9 +477,9 @@ void lifetimebound_multiple_args_potential(bool cond) { MyObj obj1; if (cond) { MyObj obj2; - v = Choose(true, - obj1, // expected-warning {{object whose reference is captured may not live long enough}} - obj2); // expected-warning {{object whose reference is captured may not live long enough}} + v = Choose(true, + obj1, // expected-warning {{object whose reference is captured does not live long enough}} + obj2); // expected-warning {{object whose reference is captured does not live long enough}} } // expected-note {{destroyed here}} } // expected-note {{destroyed here}} v.use(); // expected-note 2 {{later used here}} @@ -488,7 +550,7 @@ void lifetimebound_partial_safety(bool cond) { MyObj temp_obj; v = Choose(true, safe_obj, - temp_obj); // expected-warning {{object whose reference is captured may not live long enough}} + temp_obj); // expected-warning {{object whose reference is captured does not live long enough}} } // expected-note {{destroyed here}} v.use(); // expected-note {{later used here}} } |