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

Reply via email to