Skip to content

Commit b556bfc

Browse files
usx95ronlieb
authored andcommitted
[LifetimeSafety] Add language option for experimental lifetime safety (llvm#149592)
Add a language option flag for experimental lifetime safety analysis in C++. This change provides a language option to control the experimental lifetime safety analysis feature, making it more explicit and easier to enable/disable. Previously, the feature was controlled indirectly through a diagnostic warning flag, which we do not want to accidentally enable with `-Weverything` (atm)! - Added a new language option `EnableLifetimeSafety` in `LangOptions.def` for experimental lifetime safety analysis in C++ - Added corresponding driver options `-fexperimental-lifetime-safety` and `-fno-experimental-lifetime-safety` in `Options.td` - Modified `AnalysisBasedWarnings.cpp` to use the new language option flag instead of checking if a specific diagnostic is ignored - Updated a test case to use the new flag instead of relying on the warning flag alone
1 parent 93965b0 commit b556bfc

File tree

4 files changed

+12
-88
lines changed

4 files changed

+12
-88
lines changed

clang/include/clang/Basic/LangOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,8 @@ LANGOPT(CheckConstexprFunctionBodies, 1, 1, Benign,
506506

507507
LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
508508

509+
LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety analysis for C++")
510+
509511
LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
510512

511513
#undef LANGOPT

clang/include/clang/Driver/Options.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,6 +1913,14 @@ defm bounds_safety : BoolFOption<
19131913
BothFlags<[], [CC1Option],
19141914
" experimental bounds safety extension for C">>;
19151915

1916+
defm lifetime_safety : BoolFOption<
1917+
"experimental-lifetime-safety",
1918+
LangOpts<"EnableLifetimeSafety">, DefaultFalse,
1919+
PosFlag<SetTrue, [], [CC1Option], "Enable">,
1920+
NegFlag<SetFalse, [], [CC1Option], "Disable">,
1921+
BothFlags<[], [CC1Option],
1922+
" experimental lifetime safety for C++">>;
1923+
19161924
defm addrsig : BoolFOption<"addrsig",
19171925
CodeGenOpts<"Addrsig">, DefaultFalse,
19181926
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2890,8 +2890,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
28902890
.setAlwaysAdd(Stmt::UnaryOperatorClass);
28912891
}
28922892

2893-
bool EnableLifetimeSafetyAnalysis = !Diags.isIgnored(
2894-
diag::warn_experimental_lifetime_safety_dummy_warning, D->getBeginLoc());
2893+
bool EnableLifetimeSafetyAnalysis = S.getLangOpts().EnableLifetimeSafety;
28952894
// Install the logical handler.
28962895
std::optional<LogicalErrorHandler> LEH;
28972896
if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {

clang/test/Sema/warn-lifetime-safety-dataflow.cpp

Lines changed: 1 addition & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -mllvm -debug-only=LifetimeFacts,LifetimeLoanPropagation -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s
1+
// RUN: %clang_cc1 -fexperimental-lifetime-safety -mllvm -debug-only=LifetimeFacts -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s
22
// REQUIRES: asserts
33

44
struct MyObj {
@@ -19,10 +19,6 @@ MyObj* return_local_addr() {
1919
// CHECK: ReturnOfOrigin (OriginID: [[O_RET_VAL]])
2020
// CHECK: Expire (LoanID: [[L_X]])
2121
}
22-
// CHECK: LoanPropagation results:
23-
// CHECK-DAG: Origin [[O_ADDR_X]] contains Loan [[L_X]]
24-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_X]]
25-
// CHECK-DAG: Origin [[O_RET_VAL]] contains Loan [[L_X]]
2622

2723

2824
// Pointer Assignment and Return
@@ -47,15 +43,6 @@ MyObj* assign_and_return_local_addr() {
4743
// CHECK: ReturnOfOrigin (OriginID: [[O_PTR2_RVAL_2]])
4844
// CHECK: Expire (LoanID: [[L_Y]])
4945
}
50-
// CHECK: LoanPropagation results:
51-
// CHECK-DAG: Origin [[O_ADDR_Y]] contains Loan [[L_Y]]
52-
// CHECK-DAG: Origin [[O_PTR1]] contains Loan [[L_Y]]
53-
// CHECK-DAG: Origin [[O_PTR2]] contains Loan [[L_Y]]
54-
// CHECK-DAG: Origin [[O_PTR1_RVAL]] contains Loan [[L_Y]]
55-
// CHECK-DAG: Origin [[O_PTR1_RVAL_2]] contains Loan [[L_Y]]
56-
// CHECK-DAG: Origin [[O_PTR2_RVAL]] contains Loan [[L_Y]]
57-
// CHECK-DAG: Origin [[O_PTR2_RVAL_2]] contains Loan [[L_Y]]
58-
5946

6047
// Return of Non-Pointer Type
6148
// CHECK-LABEL: Function: return_int_val
@@ -65,8 +52,6 @@ int return_int_val() {
6552
return x;
6653
}
6754
// CHECK-NEXT: End of Block
68-
// CHECK: LoanPropagation results:
69-
// CHECK: <empty>
7055

7156

7257
// Loan Expiration (Automatic Variable, C++)
@@ -79,9 +64,6 @@ void loan_expires_cpp() {
7964
// CHECK: AssignOrigin (DestID: [[O_POBJ:[0-9]+]], SrcID: [[O_ADDR_OBJ]])
8065
// CHECK: Expire (LoanID: [[L_OBJ]])
8166
}
82-
// CHECK: LoanPropagation results:
83-
// CHECK-DAG: Origin [[O_ADDR_OBJ]] contains Loan [[L_OBJ]]
84-
// CHECK-DAG: Origin [[O_POBJ]] contains Loan [[L_OBJ]]
8567

8668

8769
// FIXME: No expire for Trivial Destructors
@@ -96,10 +78,6 @@ void loan_expires_trivial() {
9678
// CHECK-NEXT: End of Block
9779
// FIXME: Add check for Expire once trivial destructors are handled for expiration.
9880
}
99-
// CHECK: LoanPropagation results:
100-
// CHECK-DAG: Origin [[O_ADDR_TRIVIAL_OBJ]] contains Loan [[L_TRIVIAL_OBJ]]
101-
// CHECK-DAG: Origin [[O_PTOBJ]] contains Loan [[L_TRIVIAL_OBJ]]
102-
10381

10482
// CHECK-LABEL: Function: conditional
10583
void conditional(bool condition) {
@@ -119,13 +97,6 @@ void conditional(bool condition) {
11997
// CHECK: AssignOrigin (DestID: [[O_P_RVAL:[0-9]+]], SrcID: [[O_P]])
12098
// CHECK: AssignOrigin (DestID: [[O_Q:[0-9]+]], SrcID: [[O_P_RVAL]])
12199
}
122-
// CHECK: LoanPropagation results:
123-
// CHECK-DAG: Origin [[O_ADDR_A]] contains Loan [[L_A]]
124-
// CHECK-DAG: Origin [[O_ADDR_B]] contains Loan [[L_B]]
125-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_A]]
126-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_B]]
127-
// CHECK-DAG: Origin [[O_Q]] contains Loan [[L_A]]
128-
// CHECK-DAG: Origin [[O_Q]] contains Loan [[L_B]]
129100

130101

131102
// CHECK-LABEL: Function: pointers_in_a_cycle
@@ -161,25 +132,6 @@ void pointers_in_a_cycle(bool condition) {
161132
// CHECK: AssignOrigin (DestID: [[O_P3]], SrcID: [[O_TEMP_RVAL]])
162133
}
163134
}
164-
// At the end of the analysis, the origins for the pointers involved in the cycle
165-
// (p1, p2, p3, temp) should all contain the loans from v1, v2, and v3 at the fixed point.
166-
// CHECK: LoanPropagation results:
167-
// CHECK-DAG: Origin [[O_P1]] contains Loan [[L_V1]]
168-
// CHECK-DAG: Origin [[O_P1]] contains Loan [[L_V2]]
169-
// CHECK-DAG: Origin [[O_P1]] contains Loan [[L_V3]]
170-
// CHECK-DAG: Origin [[O_P2]] contains Loan [[L_V1]]
171-
// CHECK-DAG: Origin [[O_P2]] contains Loan [[L_V2]]
172-
// CHECK-DAG: Origin [[O_P2]] contains Loan [[L_V3]]
173-
// CHECK-DAG: Origin [[O_P3]] contains Loan [[L_V1]]
174-
// CHECK-DAG: Origin [[O_P3]] contains Loan [[L_V2]]
175-
// CHECK-DAG: Origin [[O_P3]] contains Loan [[L_V3]]
176-
// CHECK-DAG: Origin [[O_TEMP]] contains Loan [[L_V1]]
177-
// CHECK-DAG: Origin [[O_TEMP]] contains Loan [[L_V2]]
178-
// CHECK-DAG: Origin [[O_TEMP]] contains Loan [[L_V3]]
179-
// CHECK-DAG: Origin [[O_ADDR_V1]] contains Loan [[L_V1]]
180-
// CHECK-DAG: Origin [[O_ADDR_V2]] contains Loan [[L_V2]]
181-
// CHECK-DAG: Origin [[O_ADDR_V3]] contains Loan [[L_V3]]
182-
183135

184136
// CHECK-LABEL: Function: overwrite_origin
185137
void overwrite_origin() {
@@ -195,10 +147,6 @@ void overwrite_origin() {
195147
// CHECK: Expire (LoanID: [[L_S2]])
196148
// CHECK: Expire (LoanID: [[L_S1]])
197149
}
198-
// CHECK: LoanPropagation results:
199-
// CHECK: Origin [[O_P]] contains Loan [[L_S2]]
200-
// CHECK-NOT: Origin [[O_P]] contains Loan [[L_S1]]
201-
202150

203151
// CHECK-LABEL: Function: reassign_to_null
204152
void reassign_to_null() {
@@ -213,8 +161,6 @@ void reassign_to_null() {
213161
}
214162
// FIXME: Have a better representation for nullptr than just an empty origin.
215163
// It should be a separate loan and origin kind.
216-
// CHECK: LoanPropagation results:
217-
// CHECK: Origin [[O_P]] contains no loans
218164

219165

220166
// CHECK-LABEL: Function: reassign_in_if
@@ -235,11 +181,6 @@ void reassign_in_if(bool condition) {
235181
// CHECK: Expire (LoanID: [[L_S2]])
236182
// CHECK: Expire (LoanID: [[L_S1]])
237183
}
238-
// CHECK: LoanPropagation results:
239-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S1]]
240-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S2]]
241-
// CHECK-DAG: Origin [[O_ADDR_S1]] contains Loan [[L_S1]]
242-
// CHECK-DAG: Origin [[O_ADDR_S2]] contains Loan [[L_S2]]
243184

244185

245186
// CHECK-LABEL: Function: assign_in_switch
@@ -276,14 +217,6 @@ void assign_in_switch(int mode) {
276217
// CHECK-DAG: Expire (LoanID: [[L_S2]])
277218
// CHECK-DAG: Expire (LoanID: [[L_S1]])
278219
}
279-
// CHECK: LoanPropagation results:
280-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S1]]
281-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S2]]
282-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S3]]
283-
// CHECK-DAG: Origin [[O_ADDR_S1]] contains Loan [[L_S1]]
284-
// CHECK-DAG: Origin [[O_ADDR_S2]] contains Loan [[L_S2]]
285-
// CHECK-DAG: Origin [[O_ADDR_S3]] contains Loan [[L_S3]]
286-
287220

288221
// CHECK-LABEL: Function: loan_in_loop
289222
void loan_in_loop(bool condition) {
@@ -299,10 +232,6 @@ void loan_in_loop(bool condition) {
299232
// CHECK: Expire (LoanID: [[L_INNER]])
300233
}
301234
}
302-
// CHECK: LoanPropagation results:
303-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_INNER]]
304-
// CHECK-DAG: Origin [[O_ADDR_INNER]] contains Loan [[L_INNER]]
305-
306235

307236
// CHECK-LABEL: Function: loop_with_break
308237
void loop_with_break(int count) {
@@ -326,13 +255,6 @@ void loop_with_break(int count) {
326255
// CHECK: Expire (LoanID: [[L_S1]])
327256
}
328257

329-
// CHECK-LABEL: LoanPropagation results:
330-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S1]]
331-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S2]]
332-
// CHECK-DAG: Origin [[O_ADDR_S1]] contains Loan [[L_S1]]
333-
// CHECK-DAG: Origin [[O_ADDR_S2]] contains Loan [[L_S2]]
334-
335-
336258
// CHECK-LABEL: Function: nested_scopes
337259
void nested_scopes() {
338260
MyObj* p = nullptr;
@@ -355,13 +277,6 @@ void nested_scopes() {
355277
// CHECK: Expire (LoanID: [[L_OUTER]])
356278
}
357279

358-
// CHECK-LABEL: LoanPropagation results:
359-
// CHECK-DAG: Origin [[O_P]] contains Loan [[L_INNER]]
360-
// CHECK-DAG: Origin [[O_ADDR_INNER]] contains Loan [[L_INNER]]
361-
// CHECK-DAG: Origin [[O_ADDR_OUTER]] contains Loan [[L_OUTER]]
362-
// CHECK-NOT: Origin [[O_P]] contains Loan [[L_OUTER]]
363-
364-
365280
// CHECK-LABEL: Function: pointer_indirection
366281
void pointer_indirection() {
367282
int a;

0 commit comments

Comments
 (0)