https://github.com/higher-performance updated https://github.com/llvm/llvm-project/pull/229858
>From f52d3cd7aa11107723f741acff846ea5800e071c Mon Sep 17 00:00:00 2001 From: higher-performance <[email protected]> Date: Wed, 7 Oct 2026 13:39:55 -0400 Subject: [PATCH] [clang] Prevent __attribute__((diagnose_if(..., "error"))) from altering program behavior under SFINAE Fixes: #229664 --- clang/include/clang/Basic/Diagnostic.td | 3 ++ .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/include/clang/Sema/Sema.h | 8 ++--- clang/lib/Sema/SemaExpr.cpp | 10 +++--- clang/lib/Sema/SemaOverload.cpp | 19 +++++------ clang/test/SemaCXX/diagnose_if.cpp | 33 +++++++++++++++++++ 6 files changed, 51 insertions(+), 24 deletions(-) diff --git a/clang/include/clang/Basic/Diagnostic.td b/clang/include/clang/Basic/Diagnostic.td index c6146f8cca7167..b7f29b4c1f4c8e 100644 --- a/clang/include/clang/Basic/Diagnostic.td +++ b/clang/include/clang/Basic/Diagnostic.td @@ -116,6 +116,9 @@ class Diagnostic<string summary, DiagClass DC, Severity defaultmapping> { class SFINAEFailure { SFINAEResponse SFINAE = SFINAE_SubstitutionFailure; } +class SFINAESuppress { + SFINAEResponse SFINAE = SFINAE_Suppress; +} class NoSFINAE { SFINAEResponse SFINAE = SFINAE_Report; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 66155d9780e644..3e5bc46f7d4747 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5333,7 +5333,7 @@ def note_ovl_candidate_disabled_by_requirement : Note< def note_ovl_candidate_has_pass_object_size_params: Note< "candidate address cannot be taken because parameter %0 has " "pass_object_size attribute">; -def err_diagnose_if_succeeded : Error<"%0">; +def err_diagnose_if_succeeded : Error<"%0">, SFINAESuppress; def warn_diagnose_if_succeeded : Warning<"%0">, InGroup<UserDefinedWarnings>, ShowInSystemHeader; def note_ovl_candidate_disabled_by_function_cond_attr : Note< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7fbcc4aae7d6c5..9a245650e4c343 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10765,9 +10765,7 @@ class Sema final : public SemaBase { /// /// Argument-dependent diagnose_if attributes should be checked each time a /// function is used as a direct callee of a function call. - /// - /// Returns true if any errors were emitted. - bool diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function, + void diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function, const Expr *ThisArg, ArrayRef<const Expr *> Args, SourceLocation Loc); @@ -10777,9 +10775,7 @@ class Sema final : public SemaBase { /// /// Argument-independent diagnose_if attributes should be checked on every use /// of a function. - /// - /// Returns true if any errors were emitted. - bool diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND, + void diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND, SourceLocation Loc); /// Determine if \p A and \p B are equivalent internal linkage declarations diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 9b3384cdbdac8c..74d177efd33d4e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -342,12 +342,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, return MD->findPropertyDecl(); return nullptr; }; - if (const ObjCPropertyDecl *ObjCPDecl = getReferencedObjCProp(D)) { - if (diagnoseArgIndependentDiagnoseIfAttrs(ObjCPDecl, Loc)) - return true; - } else if (diagnoseArgIndependentDiagnoseIfAttrs(D, Loc)) { - return true; - } + if (const ObjCPropertyDecl *ObjCPDecl = getReferencedObjCProp(D)) + diagnoseArgIndependentDiagnoseIfAttrs(ObjCPDecl, Loc); + else + diagnoseArgIndependentDiagnoseIfAttrs(D, Loc); // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions // Only the variables omp_in and omp_out are allowed in the combiner. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index e5049d11480ac4..386763e2a35d82 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -7838,7 +7838,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, } template <typename CheckFn> -static bool diagnoseDiagnoseIfAttrsWith(Sema &S, const NamedDecl *ND, +static void diagnoseDiagnoseIfAttrsWith(Sema &S, const NamedDecl *ND, bool ArgDependent, SourceLocation Loc, CheckFn &&IsSuccessful) { SmallVector<const DiagnoseIfAttr *, 8> Attrs; @@ -7849,7 +7849,7 @@ static bool diagnoseDiagnoseIfAttrsWith(Sema &S, const NamedDecl *ND, // Common case: No diagnose_if attributes, so we can quit early. if (Attrs.empty()) - return false; + return; auto WarningBegin = std::stable_partition( Attrs.begin(), Attrs.end(), [](const DiagnoseIfAttr *DIA) { @@ -7866,7 +7866,7 @@ static bool diagnoseDiagnoseIfAttrsWith(Sema &S, const NamedDecl *ND, S.Diag(Loc, diag::err_diagnose_if_succeeded) << DIA->getMessage(); S.Diag(DIA->getLocation(), diag::note_from_diagnose_if) << DIA->getParent() << DIA->getCond()->getSourceRange(); - return true; + return; } auto ToSeverity = [](DiagnoseIfAttr::DefaultSeverity Sev) { @@ -7896,15 +7896,13 @@ static bool diagnoseDiagnoseIfAttrsWith(Sema &S, const NamedDecl *ND, S.Diag(Loc, DiagID) << DIA->getMessage(); } } - - return false; } -bool Sema::diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function, +void Sema::diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function, const Expr *ThisArg, ArrayRef<const Expr *> Args, SourceLocation Loc) { - return diagnoseDiagnoseIfAttrsWith( + diagnoseDiagnoseIfAttrsWith( *this, Function, /*ArgDependent=*/true, Loc, [&](const DiagnoseIfAttr *DIA) { APValue Result; @@ -7918,11 +7916,10 @@ bool Sema::diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function, }); } -bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND, +void Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND, SourceLocation Loc) { - return diagnoseDiagnoseIfAttrsWith( - *this, ND, /*ArgDependent=*/false, Loc, - [&](const DiagnoseIfAttr *DIA) { + diagnoseDiagnoseIfAttrsWith( + *this, ND, /*ArgDependent=*/false, Loc, [&](const DiagnoseIfAttr *DIA) { bool Result; return DIA->getCond()->EvaluateAsBooleanCondition(Result, Context) && Result; diff --git a/clang/test/SemaCXX/diagnose_if.cpp b/clang/test/SemaCXX/diagnose_if.cpp index 0af8bb76496ea6..a8a8217aaead26 100644 --- a/clang/test/SemaCXX/diagnose_if.cpp +++ b/clang/test/SemaCXX/diagnose_if.cpp @@ -692,3 +692,36 @@ void run() { } } + +namespace GH229664 { +template <bool, class = void> +struct enable_if {}; + +template <class T> +struct enable_if<true, T> { + using type = T; +}; + +template <class T, class = void> +struct S { + static constexpr bool value = false; +}; + +template <class T> +struct S<T, typename enable_if<sizeof(T::foo(-1)) == 1>::type> { + static constexpr bool value = true; +}; + +struct ArgDependent { + static constexpr char foo(int x) _diagnose_if(sizeof(x) != 0, "", "error"); + static constexpr char (&foo(long x))[2] _diagnose_if(sizeof(x) != 0, "", "warning"); +}; + +struct ArgIndependent { + static constexpr char foo(int) _diagnose_if(true, "", "error"); + static constexpr char (&foo(long))[2] _diagnose_if(true, "", "warning"); +}; + +static_assert(S<ArgDependent>::value, ""); +static_assert(S<ArgIndependent>::value, ""); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
