[clang] [clang] Prevent recursive copy initialization during variadic argument promotion (PR #196744)

Vineet Agarwal via cfe-commits cfe-commits at lists.llvm.org
Sat May 9 21:31:10 PDT 2026


https://github.com/PlutoDog95 updated https://github.com/llvm/llvm-project/pull/196744

>From e397cefef2aee11ac795fc31494c804b5fab7ebb Mon Sep 17 00:00:00 2001
From: Vineet Agarwal <agarwal.vineet2006 at gmail.com>
Date: Sat, 9 May 2026 23:34:40 +0530
Subject: [PATCH] [clang] Prevent recursion during variadic argument promotion

Avoid recursive copy initialization during variadic argument promotion
for volatile class types.

Previously Clang could recurse indefinitely and crash with stack
exhaustion while handling variadic constructor calls involving
volatile objects.

This change prevents the recursive initialization path and updates
existing test expectations to match the resulting diagnostics.

Add a regression test for the crash.
---
 clang/docs/ReleaseNotes.rst                      |  3 +++
 clang/lib/Sema/SemaExpr.cpp                      |  3 ++-
 clang/test/CXX/drs/cwg6xx.cpp                    |  4 +---
 clang/test/SemaCXX/volatile-vararg-recursion.cpp | 15 +++++++++++++++
 4 files changed, 21 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/SemaCXX/volatile-vararg-recursion.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fa19d4b576575..3cba99777511d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -470,6 +470,9 @@ Improvements to Clang's diagnostics
 
 - Clang now emits an error when implicitly casting a complex type to a built-in vector type. (#GH186805)
 
+- Fixed a frontend crash caused by recursive variadic argument promotion
+  involving volatile class types (#GH196713).
+
 - Added ``-Wnonportable-include-path-separator`` (off by default) to catch
   #include directives that use backslashes as a path separator. The warning
   includes a FixIt to change all the backslashes to forward slashes, so that the
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 98062afae4577..557e1ec96190b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -935,7 +935,8 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
   //     is a prvalue for the temporary.
   // FIXME: add some way to gate this entire thing for correctness in
   // potentially potentially evaluated contexts.
-  if (getLangOpts().CPlusPlus && E->isGLValue() && !isUnevaluatedContext()) {
+  if (getLangOpts().CPlusPlus && E->isGLValue() && !isUnevaluatedContext() &&
+      !E->getType().isVolatileQualified()) {
     ExprResult Temp = PerformCopyInitialization(
                        InitializedEntity::InitializeTemporary(E->getType()),
                                                 E->getExprLoc(), E);
diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp
index b7b2ebf700375..37b613a646fda 100644
--- a/clang/test/CXX/drs/cwg6xx.cpp
+++ b/clang/test/CXX/drs/cwg6xx.cpp
@@ -757,9 +757,7 @@ namespace cwg656 { // cwg656: 2.8
     // expected-error at -1 {{call to deleted function 'accept'}}
     //   expected-note@#cwg656-accept-var {{candidate function [with T = const cwg656::A &] has been explicitly deleted}}
     //   expected-note@#cwg656-accept-T {{candidate function template not viable: no known conversion from 'volatile Y' to 'const A &' for 1st argument}}
-    // expected-error@#cwg656-vy {{no matching constructor for initialization of 'volatile Y'}}
-    //   expected-note@#cwg656-Y {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('volatile Y') would lose volatile qualifier}}
-    //   expected-note@#cwg656-Y {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
+    // cxx98-error@#cwg656-vy {{cannot pass object of non-POD type 'volatile Y' through variadic function; call will abort at runtime}}
     accept<const D&>(c);
   }
 } // namespace cwg656
diff --git a/clang/test/SemaCXX/volatile-vararg-recursion.cpp b/clang/test/SemaCXX/volatile-vararg-recursion.cpp
new file mode 100644
index 0000000000000..cf3490baccdd4
--- /dev/null
+++ b/clang/test/SemaCXX/volatile-vararg-recursion.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace cwg535 {
+class X {
+  X(const X &);
+};
+
+struct B {
+  X y;
+  B(...);
+};
+
+extern volatile B b1;
+B b2(b1); // expected-error {{cannot pass object of non-trivial type 'volatile B' through variadic constructor; call will abort at runtime}}
+}



More information about the cfe-commits mailing list