Mordante created this revision. Mordante added reviewers: aaron.ballman, rjmccall, rsmith. Mordante added a project: clang. Mordante requested review of this revision.
Adds a diagnostic when the user annotates an `if constexpr` with a likelihood attribute. The `if constexpr` statement is evaluated at compile time so the attribute has no effect. Annotating the accompanied `else` with a likelihood attribute has the same effect as annotating a generic statement. Since the attribute there is most likely not intended, a diagnostic will be issued. Since the attributes can't conflict, the "conflict" won't be diagnosed for an `if constexpr`. It extends diagnostics on a patch in review. Depends on D89899 <https://reviews.llvm.org/D89899> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D90336 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaStmt.cpp clang/test/SemaCXX/attr-likelihood.cpp Index: clang/test/SemaCXX/attr-likelihood.cpp =================================================================== --- clang/test/SemaCXX/attr-likelihood.cpp +++ clang/test/SemaCXX/attr-likelihood.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify +// RUN: %clang_cc1 %s -std=c++17 -fsyntax-only -verify // RUN: %clang_cc1 %s -DPEDANTIC -pedantic -fsyntax-only -verify #if PEDANTIC @@ -129,4 +129,23 @@ catch (...) [[likely]] { // expected-error {{expected expression}} } } + +void o() +{ + // expected-warning@+2 {{attribute 'likely' has no effect when annotating an 'if constexpr' statement}} + // expected-note@+1 {{annotating the 'if constexpr' statement here}} + if constexpr (true) [[likely]]; + + // expected-note@+1 {{annotating the 'if constexpr' statement here}} + if constexpr (true) { + // expected-warning@+1 {{attribute 'unlikely' has no effect when annotating an 'if constexpr' statement}} + } else [[unlikely]]; + + // Annotating both branches with conflicting likelihoods generates no diagnostic regarding the conflict. + // expected-warning@+2 {{attribute 'likely' has no effect when annotating an 'if constexpr' statement}} + // expected-note@+1 2 {{annotating the 'if constexpr' statement here}} + if constexpr (true) [[likely]] { + // expected-warning@+1 {{attribute 'likely' has no effect when annotating an 'if constexpr' statement}} + } else [[likely]]; +} #endif Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -597,16 +597,29 @@ DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt, diag::warn_empty_if_body); - std::tuple<bool, const Attr *, const Attr *> LHC = - Stmt::determineLikelihoodConflict(thenStmt, elseStmt); - if (std::get<0>(LHC)) { - const Attr *ThenAttr = std::get<1>(LHC); - const Attr *ElseAttr = std::get<2>(LHC); - Diags.Report(ThenAttr->getLocation(), - diag::warn_attributes_likelihood_ifstmt_conflict) - << ThenAttr << ThenAttr->getRange(); - Diags.Report(ElseAttr->getLocation(), diag::note_conflicting_attribute) - << ElseAttr << ElseAttr->getRange(); + if (IsConstexpr) { + auto DiagnoseLikelihood = [&](const Stmt *S) { + if (const Attr *A = Stmt::getLikelihoodAttr(S)) { + Diags.Report(A->getLocation(), diag::warn_attribute_has_no_effect) + << A << 1 << A->getRange(); + Diags.Report(IfLoc, diag::note_attribute_has_no_effect_here) + << 1 << SourceRange(IfLoc, LParenLoc.getLocWithOffset(-1)); + } + }; + DiagnoseLikelihood(thenStmt); + DiagnoseLikelihood(elseStmt); + } else { + std::tuple<bool, const Attr *, const Attr *> LHC = + Stmt::determineLikelihoodConflict(thenStmt, elseStmt); + if (std::get<0>(LHC)) { + const Attr *ThenAttr = std::get<1>(LHC); + const Attr *ElseAttr = std::get<2>(LHC); + Diags.Report(ThenAttr->getLocation(), + diag::warn_attributes_likelihood_ifstmt_conflict) + << ThenAttr << ThenAttr->getRange(); + Diags.Report(ElseAttr->getLocation(), diag::note_conflicting_attribute) + << ElseAttr << ElseAttr->getRange(); + } } return BuildIfStmt(IfLoc, IsConstexpr, LParenLoc, InitStmt, Cond, RParenLoc, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3156,10 +3156,11 @@ "__declspec attribute %0 is not supported">, InGroup<IgnoredAttributes>; def warn_attribute_has_no_effect : Warning< - "attribute %0 has no effect when annotating %select{an infinite loop}1">, + "attribute %0 has no effect when annotating %select{an infinite loop|" + "an 'if constexpr' statement}1">, InGroup<IgnoredAttributes>; def note_attribute_has_no_effect_here : Note< - "annotating the %select{infinite loop}0 here">; + "annotating the %select{infinite loop|'if constexpr' statement}0 here">; def err_decl_attribute_invalid_on_stmt : Error< "%0 attribute cannot be applied to a statement">; def err_stmt_attribute_invalid_on_decl : Error<
Index: clang/test/SemaCXX/attr-likelihood.cpp =================================================================== --- clang/test/SemaCXX/attr-likelihood.cpp +++ clang/test/SemaCXX/attr-likelihood.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify +// RUN: %clang_cc1 %s -std=c++17 -fsyntax-only -verify // RUN: %clang_cc1 %s -DPEDANTIC -pedantic -fsyntax-only -verify #if PEDANTIC @@ -129,4 +129,23 @@ catch (...) [[likely]] { // expected-error {{expected expression}} } } + +void o() +{ + // expected-warning@+2 {{attribute 'likely' has no effect when annotating an 'if constexpr' statement}} + // expected-note@+1 {{annotating the 'if constexpr' statement here}} + if constexpr (true) [[likely]]; + + // expected-note@+1 {{annotating the 'if constexpr' statement here}} + if constexpr (true) { + // expected-warning@+1 {{attribute 'unlikely' has no effect when annotating an 'if constexpr' statement}} + } else [[unlikely]]; + + // Annotating both branches with conflicting likelihoods generates no diagnostic regarding the conflict. + // expected-warning@+2 {{attribute 'likely' has no effect when annotating an 'if constexpr' statement}} + // expected-note@+1 2 {{annotating the 'if constexpr' statement here}} + if constexpr (true) [[likely]] { + // expected-warning@+1 {{attribute 'likely' has no effect when annotating an 'if constexpr' statement}} + } else [[likely]]; +} #endif Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -597,16 +597,29 @@ DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt, diag::warn_empty_if_body); - std::tuple<bool, const Attr *, const Attr *> LHC = - Stmt::determineLikelihoodConflict(thenStmt, elseStmt); - if (std::get<0>(LHC)) { - const Attr *ThenAttr = std::get<1>(LHC); - const Attr *ElseAttr = std::get<2>(LHC); - Diags.Report(ThenAttr->getLocation(), - diag::warn_attributes_likelihood_ifstmt_conflict) - << ThenAttr << ThenAttr->getRange(); - Diags.Report(ElseAttr->getLocation(), diag::note_conflicting_attribute) - << ElseAttr << ElseAttr->getRange(); + if (IsConstexpr) { + auto DiagnoseLikelihood = [&](const Stmt *S) { + if (const Attr *A = Stmt::getLikelihoodAttr(S)) { + Diags.Report(A->getLocation(), diag::warn_attribute_has_no_effect) + << A << 1 << A->getRange(); + Diags.Report(IfLoc, diag::note_attribute_has_no_effect_here) + << 1 << SourceRange(IfLoc, LParenLoc.getLocWithOffset(-1)); + } + }; + DiagnoseLikelihood(thenStmt); + DiagnoseLikelihood(elseStmt); + } else { + std::tuple<bool, const Attr *, const Attr *> LHC = + Stmt::determineLikelihoodConflict(thenStmt, elseStmt); + if (std::get<0>(LHC)) { + const Attr *ThenAttr = std::get<1>(LHC); + const Attr *ElseAttr = std::get<2>(LHC); + Diags.Report(ThenAttr->getLocation(), + diag::warn_attributes_likelihood_ifstmt_conflict) + << ThenAttr << ThenAttr->getRange(); + Diags.Report(ElseAttr->getLocation(), diag::note_conflicting_attribute) + << ElseAttr << ElseAttr->getRange(); + } } return BuildIfStmt(IfLoc, IsConstexpr, LParenLoc, InitStmt, Cond, RParenLoc, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3156,10 +3156,11 @@ "__declspec attribute %0 is not supported">, InGroup<IgnoredAttributes>; def warn_attribute_has_no_effect : Warning< - "attribute %0 has no effect when annotating %select{an infinite loop}1">, + "attribute %0 has no effect when annotating %select{an infinite loop|" + "an 'if constexpr' statement}1">, InGroup<IgnoredAttributes>; def note_attribute_has_no_effect_here : Note< - "annotating the %select{infinite loop}0 here">; + "annotating the %select{infinite loop|'if constexpr' statement}0 here">; def err_decl_attribute_invalid_on_stmt : Error< "%0 attribute cannot be applied to a statement">; def err_stmt_attribute_invalid_on_decl : Error<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits