Author: Tony Guillot
Date: 2026-07-13T15:15:05+02:00
New Revision: 9e014de2d3cc674b548e321013bfe42e6f5485ab

URL: 
https://github.com/llvm/llvm-project/commit/9e014de2d3cc674b548e321013bfe42e6f5485ab
DIFF: 
https://github.com/llvm/llvm-project/commit/9e014de2d3cc674b548e321013bfe42e6f5485ab.diff

LOG: [Clang] Fixed missing sentinel attribute diagnostic discrepancy with 
explicit object parameters (#208842)

When using the sentinel attribute on a variadic function with an
explicit object parameter, the missing sentinel attribute diagnostic
takes into account the explicit object parameter as an argument. It was
diagnosing `missing sentinel in function call` instead of `not enough
variable arguments in '%0' declaration to fit a sentinel`, compared to
other similar variadic functions.

Fixes #200007

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/Sema/SemaExpr.cpp
    clang/test/SemaCXX/attr-sentinel.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index bbd42848a98c2..69f86294d4377 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -741,6 +741,9 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 
 - Added a clearer diagnostic for uninitialized decomposition declarations. 
(#GH90107)
 
+- Fixed missing sentinel attribute diagnostic discrepancy with explicit object
+  parameters in variadic functions. (#GH200007)
+
 ### Improvements to Clang's time-trace
 
 ### Improvements to Coverage Mapping

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3afca1a202062..6d7cdf9f60dea 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -433,6 +433,8 @@ void Sema::DiagnoseSentinelCalls(const NamedDecl *D, 
SourceLocation Loc,
   } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
     NumFormalParams = FD->param_size();
     CalleeKind = CK_Function;
+    if (FD->hasCXXExplicitFunctionObjectParameter())
+      NumFormalParams++;
   } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
     QualType Ty = VD->getType();
     const FunctionType *Fn = nullptr;

diff  --git a/clang/test/SemaCXX/attr-sentinel.cpp 
b/clang/test/SemaCXX/attr-sentinel.cpp
index 92c6e21444fa3..e11ac16fe6bcf 100644
--- a/clang/test/SemaCXX/attr-sentinel.cpp
+++ b/clang/test/SemaCXX/attr-sentinel.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17 -std=c++17 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx23 -std=c++23 %s
 
 void f(int, ...) __attribute__((sentinel));
 
@@ -21,3 +22,88 @@ void class_test() {
   s2->a(1,2,3); // expected-warning {{missing sentinel in function call}}
   s(1,2,3); // expected-warning {{missing sentinel in function call}}
 }
+
+namespace consistent_diganostic_test {
+struct Ty {
+    void baseline0(int, ...) __attribute__((sentinel));     // #BASELINE0_NOTE
+    void baseline1(int, ...) __attribute__((sentinel(1)));  // #BASELINE1_NOTE
+    void baseline2(int, ...) __attribute__((sentinel(2)));  // #BASELINE2_NOTE
+
+    template<typename T>
+    int&& foo(T&& val, ...) __attribute__((sentinel(1))); // #FOO_NOTE
+
+    template<class Self>
+    int&& bar(this Self&& self, ...) __attribute__((sentinel(1))); // #BAR_NOTE
+    // cxx17-error@-1 {{explicit object parameters are incompatible with C++ 
standards before C++2b}}
+};
+
+void test_baseline0() {
+    auto sty = Ty{};
+
+    sty.baseline0(1);
+    // expected-warning@-1 {{not enough variable arguments in 'baseline0' 
declaration to fit a sentinel}}
+    // expected-note@#BASELINE0_NOTE {{function has been explicitly marked 
sentinel here}}
+
+    sty.baseline0(1, 2);
+    // expected-warning@-1 {{missing sentinel in function call}}
+    // expected-note@#BASELINE0_NOTE {{function has been explicitly marked 
sentinel here}}
+
+    sty.baseline0(1, 2, nullptr);
+}
+
+void test_baseline1() {
+    auto sty = Ty{};
+
+    sty.baseline1(1, 3);
+    // expected-warning@-1 {{not enough variable arguments in 'baseline1' 
declaration to fit a sentinel}}
+    // expected-note@#BASELINE1_NOTE {{function has been explicitly marked 
sentinel here}}
+
+    sty.baseline1(1, 2, 3);
+    // expected-warning@-1 {{missing sentinel in function call}}
+    // expected-note@#BASELINE1_NOTE {{function has been explicitly marked 
sentinel here}}
+
+    sty.baseline1(1, 2, nullptr, 3);
+}
+
+void test_baseline2() {
+    auto sty = Ty{};
+
+    sty.baseline2(1, 2, 3);
+    // expected-warning@-1 {{not enough variable arguments in 'baseline2' 
declaration to fit a sentinel}}
+    // expected-note@#BASELINE2_NOTE {{function has been explicitly marked 
sentinel here}}
+
+    sty.baseline2(1, 2, 3, 4);
+    // expected-warning@-1 {{missing sentinel in function call}}
+    // expected-note@#BASELINE2_NOTE {{function has been explicitly marked 
sentinel here}}
+
+    sty.baseline2(1, 2, nullptr, 3, 4);
+}
+
+void test_foo() {
+    auto sty = Ty{};
+
+    sty.foo(1, 2);
+    // expected-warning@-1 {{not enough variable arguments in 'foo' 
declaration to fit a sentinel}}
+    // expected-note@#FOO_NOTE {{function has been explicitly marked sentinel 
here}}
+
+    sty.foo(1, 2, 3);
+    // expected-warning@-1 {{missing sentinel in function call}}
+    // expected-note@#FOO_NOTE {{function has been explicitly marked sentinel 
here}}
+
+    sty.foo(1, nullptr, 3);
+}
+
+void test_bar() {
+    auto sty = Ty{};
+
+    sty.bar(1, 2);
+    // expected-warning@-1 {{not enough variable arguments in 'bar' 
declaration to fit a sentinel}}
+    // expected-note@#BAR_NOTE {{function has been explicitly marked sentinel 
here}}
+
+    sty.bar(1, 2, 3);
+    // expected-warning@-1 {{missing sentinel in function call}}
+    // expected-note@#BAR_NOTE {{function has been explicitly marked sentinel 
here}}
+
+    sty.bar(1, nullptr, 3);
+}
+} // namespace consistent_diganostic_test


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to