Skip to content

Commit 965c511

Browse files
committed
[feature availablity] Improve diagnostic for goto jumping into if
@available(domain: ...) Use the existing logic that warns about goto jumping into branches of if @available. rdar://137999979
1 parent 32ac3cb commit 965c511

File tree

7 files changed

+46
-14
lines changed

7 files changed

+46
-14
lines changed

clang/include/clang/AST/Stmt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,6 +2418,8 @@ class IfStmt final
24182418

24192419
bool isObjCAvailabilityCheck() const;
24202420

2421+
bool isObjCAvailabilityCheckWithDomainName() const;
2422+
24212423
SourceLocation getBeginLoc() const { return getIfLoc(); }
24222424
SourceLocation getEndLoc() const LLVM_READONLY {
24232425
if (getElse())

clang/lib/AST/Stmt.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,13 @@ bool IfStmt::isObjCAvailabilityCheck() const {
10041004
return isa<ObjCAvailabilityCheckExpr>(getCond());
10051005
}
10061006

1007+
bool IfStmt::isObjCAvailabilityCheckWithDomainName() const {
1008+
if (auto *ACE = dyn_cast<ObjCAvailabilityCheckExpr>(getCond());
1009+
ACE && ACE->hasDomainName())
1010+
return true;
1011+
return false;
1012+
}
1013+
10071014
std::optional<Stmt *> IfStmt::getNondiscardedCase(const ASTContext &Ctx) {
10081015
if (!isConstexpr() || getCond()->isValueDependent())
10091016
return std::nullopt;

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,8 @@ class ScalarExprEmitter
556556
auto DomainName = E->getDomainName();
557557
ASTContext::AvailabilityDomainInfo Info =
558558
CGF.getContext().getFeatureAvailInfo(DomainName);
559+
assert((Info.Kind == FeatureAvailKind::Dynamic && Info.Call) &&
560+
"ObjCAvailabilityCheckExpr should have been constant evaluated");
559561
return CGF.EmitScalarExpr(Info.Call);
560562
}
561563

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
818818
// the condition and the dead arm of the if/else.
819819
bool CondConstant;
820820
if (ConstantFoldsToSimpleInteger(S.getCond(), CondConstant,
821-
S.isConstexpr())) {
821+
(S.isConstexpr() || S.isObjCAvailabilityCheckWithDomainName()))) {
822822
// Figure out which block (then or else) is executed.
823823
const Stmt *Executed = S.getThen();
824824
const Stmt *Skipped = S.getElse();
@@ -827,7 +827,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
827827

828828
// If the skipped block has no labels in it, just emit the executed block.
829829
// This avoids emitting dead code and simplifies the CFG substantially.
830-
if (S.isConstexpr() || !ContainsLabel(Skipped)) {
830+
if ((S.isConstexpr() || S.isObjCAvailabilityCheckWithDomainName()) || !ContainsLabel(Skipped)) {
831831
if (CondConstant)
832832
incrementProfileCounter(&S);
833833
if (Executed) {

clang/lib/Sema/SemaFeatureAvailability.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,6 @@ class DiagnoseUnguardedFeatureAvailability
8383
return true;
8484
}
8585

86-
bool VisitLabelStmt(LabelStmt *LS) {
87-
if (isConditionallyGuardedByFeature())
88-
SemaRef.Diag(LS->getBeginLoc(),
89-
diag::err_label_in_conditionally_guarded_feature);
90-
return true;
91-
}
92-
9386
bool VisitTypeLoc(TypeLoc Ty);
9487

9588
void IssueDiagnostics() {

clang/test/CodeGen/feature-availability.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,22 @@ void test4(void) {
106106

107107
#endif
108108

109+
// CHECK-LABEL: define void @test5()
110+
// CHECK: br label %[[L1:.*]]
111+
// CHECK: [[L1]]:
112+
// CHECK-NEXT: call i32 @func0()
113+
// CHECK-NEXT: ret void
114+
115+
void test5(void) {
116+
if (__builtin_available(domain:feature1)) {
117+
goto L1;
118+
L1:
119+
func0();
120+
} else {
121+
goto L2;
122+
L2:
123+
func2();
124+
}
125+
}
126+
109127
#endif /* HEADER */

clang/test/Sema/feature-availability.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,22 @@ void test4(struct S0 *s0) { // expected-error {{use of 'S0' requires feature 'fe
175175
g11.i0 = 0; // expected-error {{use of 'g11' requires feature 'feature1' to be available}} expected-error {{use of 'i0' requires feature 'feature1' to be available}}
176176
}
177177

178-
void test5(void) {
179-
if (__builtin_available(domain:feature1))
180-
label0: // expected-error {{labels cannot appear in regions conditionally guarded by features}}
181-
;
182-
label1:
178+
void test5(int c) {
179+
if (c > 100)
180+
goto label0; // expected-error {{cannot jump from this goto statement to its label}}
181+
else if (c > 50)
182+
goto label1; // expected-error {{cannot jump from this goto statement to its label}}
183+
if (__builtin_available(domain:feature1)) { // expected-note 2 {{jump enters controlled statement of if available}}
184+
label0:
183185
;
186+
} else {
187+
if (c > 80)
188+
goto label2;
189+
label1:
190+
;
191+
label2:
192+
;
193+
}
184194
}
185195

186196
void test6(void) {

0 commit comments

Comments
 (0)