[clang] [Clang] Fix nonblocking warning for dependent default arguments (PR #235457)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 25 07:39:17 PDT 2026
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 <cs24btech11027 at iith.ac.in>
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}}
More information about the cfe-commits
mailing list