aboutsummaryrefslogtreecommitdiff
path: root/clang/test
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/AST/HLSL/resource_binding_attr.hlsl3
-rw-r--r--clang/test/AST/HLSL/vk_binding_attr.hlsl27
-rw-r--r--clang/test/AST/ast-print-record-decl.c7
-rw-r--r--clang/test/Analysis/Checkers/WebKit/objc-mock-types.h16
-rw-r--r--clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm9
-rw-r--r--clang/test/Analysis/LifetimeSafety/benchmark.py82
-rw-r--r--clang/test/CIR/CodeGen/new.cpp53
-rw-r--r--clang/test/CIR/IR/dynamic-cast.cir59
-rw-r--r--clang/test/CIR/IR/invalid-dyn-cast.cir43
-rw-r--r--clang/test/Driver/aarch64-cpu-defaults-appleos26.c10
-rw-r--r--clang/test/Driver/darwin-maccatalyst-error.c6
-rw-r--r--clang/test/Driver/darwin-maccatalyst.c5
-rw-r--r--clang/test/Driver/env.c4
-rw-r--r--clang/test/Driver/print-supported-extensions-riscv.c2
-rw-r--r--clang/test/Driver/riscv-arch.c4
-rw-r--r--clang/test/Preprocessor/riscv-target-features.c6
-rw-r--r--clang/test/Sema/warn-lifetime-safety.cpp138
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}}
}