https://github.com/MitraGulla created 
https://github.com/llvm/llvm-project/pull/235457

This fixes an unexpected `-Wfunction-effects` warning that occurs when Clang 
analyzes a template's dependent default argument, even though the caller 
provides the argument explicitly.

Added a regression test for the reported issue and tests covering explicit and 
implicit arguments and other template default-argument cases.

## LLM usage

LLM was used to help understand the issue, and finding relevant code part. The 
implementation and test changes were reviewed and tested locally.

>From 838ab1bb5e68a53672f2b00b30ee307bc371cf68 Mon Sep 17 00:00:00 2001
From: MitraGulla <[email protected]>
Date: Sun, 25 Oct 2026 20:02:05 +0530
Subject: [PATCH] [Clang] Fix nonblocking warning for dependent default
 arguments

---
 clang/lib/Sema/SemaFunctionEffects.cpp        |  8 +++
 .../Sema/attr-nonblocking-constraints.cpp     | 52 +++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp 
b/clang/lib/Sema/SemaFunctionEffects.cpp
index 975281175aebb4..ef92e0c8b3ec47 100644
--- a/clang/lib/Sema/SemaFunctionEffects.cpp
+++ b/clang/lib/Sema/SemaFunctionEffects.cpp
@@ -1342,6 +1342,14 @@ class Analyzer {
       return Result;
     }
 
+    bool TraverseParmVarDecl(ParmVarDecl *D) override {
+      // Uninstantiated default arguments are dependent expressions that cannot
+      // be analyzed for function effects without producing incorrect warnings.
+      if (D->hasUninstantiatedDefaultArg())
+        return true;
+      return DynamicRecursiveASTVisitor::TraverseParmVarDecl(D);
+    }
+
     bool TraverseLambdaExpr(LambdaExpr *Lambda) override {
       // We override this so as to be able to skip traversal of the lambda's
       // body. We have to explicitly traverse the captures. Why not return
diff --git a/clang/test/Sema/attr-nonblocking-constraints.cpp 
b/clang/test/Sema/attr-nonblocking-constraints.cpp
index 400057768523c5..55aa3cfde11bc3 100644
--- a/clang/test/Sema/attr-nonblocking-constraints.cpp
+++ b/clang/test/Sema/attr-nonblocking-constraints.cpp
@@ -380,6 +380,58 @@ void nb21() [[clang::nonblocking]] {
 void nb22(int param = badForDefaultArg()) [[clang::nonblocking]] { // 
expected-warning {{function with 'nonblocking' attribute must not call 
non-'nonblocking' function 'badForDefaultArg'}}
 }
 
+ // Template default arguments
+ template <typename T>
+ int tmplDefaultSafe() noexcept [[clang::nonblocking]] {
+   return 0;
+ }
+
+ template <typename T>
+ auto tmplDefault(T a = tmplDefaultSafe<T>()) noexcept [[clang::nonblocking]] {
+   return a;
+ }
+
+ void testTmplDefaultExplicit(int x) [[clang::nonblocking]] {
+   tmplDefault(x);
+ }
+
+ void testTmplDefaultImplicit() [[clang::nonblocking]] {
+   tmplDefault<int>();
+ }
+
+ int badForTmplDefaultArg(); // expected-note {{declaration cannot be inferred 
'nonblocking' because it has no definition in this translation unit}} \
+                             // expected-note {{declaration cannot be inferred 
'nonblocking' because it has no definition in this translation unit}}
+
+ template <typename T>
+ auto tmplDefaultBad(T a = badForTmplDefaultArg()) noexcept 
[[clang::nonblocking]] { // expected-warning {{function with 'nonblocking' 
attribute must not call non-'nonblocking' function 'badForTmplDefaultArg'}} \
+                                                                               
      // expected-warning {{function with 'nonblocking' attribute must not call 
non-'nonblocking' function 'badForTmplDefaultArg'}}
+   return a;
+ }
+
+ void testTmplDefaultBadExplicit(int x) [[clang::nonblocking]] {
+   tmplDefaultBad(x);
+ }
+
+ void testTmplDefaultBadImplicit() [[clang::nonblocking]] {
+   tmplDefaultBad<int>(); // expected-note {{in evaluating default argument 
here}}
+ }
+
+ // An explicit argument must not trigger analysis of an unused dependent
+ // default argument.
+ template <typename T>
+ int f1() noexcept [[clang::nonblocking]] {
+   return 0;
+ }
+
+ template <typename T>
+ auto f2(T a = f1<T>()) noexcept [[clang::nonblocking]] {
+   return a;
+ }
+
+ void testDependentDefaultExplicit(int argc) [[clang::nonblocking]] {
+   f2(argc);
+ }
+
 // Verify traversal of implicit code paths - constructors and destructors.
 struct Unsafe {
   static void problem1();   // expected-note {{declaration cannot be inferred 
'nonblocking' because it has no definition in this translation unit}}

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

Reply via email to