https://github.com/AV01DANC3 updated 
https://github.com/llvm/llvm-project/pull/183933

>From ddc8d6f2e483d75ae3a270ae6701fa97180e26d0 Mon Sep 17 00:00:00 2001
From: Nikita Miroshnichenko <[email protected]>
Date: Sat, 28 Feb 2026 18:12:48 +0100
Subject: [PATCH 1/2] [clang][CodeGen] Fix crash for VLA alias in local class
 constructor

When a VLA type is hidden behind a type alias and used as a local
variable inside a local class or struct constructor, CodeGen could fail to emit
VLA size information, leading to an assertion failure in getVLASize().

Desugar the variable type before emitting variably-modified type
information.

Add a regression test.
---
 clang/lib/CodeGen/CGDecl.cpp                     |  6 ++++--
 clang/test/CodeGenCXX/vla-alias-local-struct.cpp | 15 +++++++++++++++
 2 files changed, 19 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/vla-alias-local-struct.cpp

diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 8b5ffde1b73f3..a08e0a79671d1 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1493,8 +1493,10 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
   CharUnits alignment = getContext().getDeclAlign(&D);
 
   // If the type is variably-modified, emit all the VLA sizes for it.
-  if (Ty->isVariablyModifiedType())
-    EmitVariablyModifiedType(Ty);
+  if (Ty->isVariablyModifiedType()) {
+    QualType DesugaredTy = Ty.getDesugaredType(getContext());
+    EmitVariablyModifiedType(DesugaredTy);
+  }
 
   auto *DI = getDebugInfo();
   bool EmitDebugInfo = DI && CGM.getCodeGenOpts().hasReducedDebugInfo();
diff --git a/clang/test/CodeGenCXX/vla-alias-local-struct.cpp 
b/clang/test/CodeGenCXX/vla-alias-local-struct.cpp
new file mode 100644
index 0000000000000..bb33bdbcccb87
--- /dev/null
+++ b/clang/test/CodeGenCXX/vla-alias-local-struct.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -std=gnu++20 -emit-llvm %s -o - >/dev/null
+
+int f() { return 1; }
+
+int test0() {
+  using X = int[f()];
+
+  struct S {
+    S() {
+      X x;
+    }
+  } s;
+
+  return 0;
+}

>From 02619b6f36e816fe9ba1015605d243d61c428a6d Mon Sep 17 00:00:00 2001
From: Nikita Miroshnichenko <[email protected]>
Date: Sun, 22 Mar 2026 13:22:06 +0100
Subject: [PATCH 2/2] [clang][Sema] Diagnose use of variably modified type
 alias from enclosing scope in local class

Using a variably modified type declared in an enclosing function scope inside a 
local class method is not valid.
Previously, this would silently compile until hitting a crash in CodeGen.

This change adds Sema diagnostics via a new `DiagnoseVLAInLocalClass` helper 
that is called:
  - In `HandleDeclarator`, to catch variable declarations using such types.
  - In `ActOnUnaryExprOrTypeTraitExpr`, to catch sizeof expressions using such 
types.
---
 .../clang/Basic/DiagnosticSemaKinds.td        |  5 ++
 clang/include/clang/Sema/Sema.h               |  9 +++
 clang/lib/Sema/Sema.cpp                       | 25 +++++++
 clang/lib/Sema/SemaDecl.cpp                   |  3 +
 clang/lib/Sema/SemaExpr.cpp                   |  2 +
 clang/test/SemaCXX/vla-alias-local-class.cpp  | 70 +++++++++++++++++++
 6 files changed, 114 insertions(+)
 create mode 100644 clang/test/SemaCXX/vla-alias-local-class.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a0a74f52f8aa9..ba3c03d394cc3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -14038,4 +14038,9 @@ def err_cuda_device_kernel_launch_not_supported
 def err_cuda_device_kernel_launch_require_rdc
     : Error<"kernel launch from __device__ or __global__ function requires "
             "relocatable device code (i.e. requires -fgpu-rdc)">;
+
+def err_vmt_declared_outside_of_local_class : Error<
+  "variably modified type %0 from enclosing scope cannot be used in local 
class %1">;
+def note_vmt_type_declared_here : Note<
+  "type declared here">;
 } // end of sema component.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 13a412914f5ce..d443935580f2d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14608,6 +14608,15 @@ class Sema final : public SemaBase {
   bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
                                        UnexpandedParameterPackContext UPPC);
 
+  /// If the given type is a variably modified type from an enclosing scope
+  /// used inside a local class method, diagnose the error.
+  ///
+  /// \param T The type of the declaration or expression being checked.
+  /// \param Loc The source location, used for diagnostics.
+  ///
+  /// \returns true if an error was diagnosed, false otherwise.
+  bool DiagnoseVLAInLocalClass(QualType T, SourceLocation Loc);
+
   /// Collect the set of unexpanded parameter packs within the given
   /// template argument.
   ///
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 3065b5e1e66d3..c6b62338aab6a 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -2978,3 +2978,28 @@ Attr *Sema::CreateAnnotationAttr(const ParsedAttr &AL) {
 
   return CreateAnnotationAttr(AL, Str, Args);
 }
+
+bool Sema::DiagnoseVLAInLocalClass(QualType T, SourceLocation Loc) {
+  if (T.isNull() || !T->isVariablyModifiedType())
+    return false;
+
+  const auto *TT = dyn_cast<TypedefType>(T.getTypePtr());
+  if (!TT)
+    return false;
+
+  const auto *MD = dyn_cast<CXXMethodDecl>(CurContext);
+  if (!MD)
+    return false;
+
+  const CXXRecordDecl *RD = MD->getParent();
+  if (!RD->isLocalClass())
+    return false;
+
+  const TypedefNameDecl *TD = TT->getDecl();
+  if (TD->getDeclContext()->getRedeclContext()->Equals(RD))
+    return false;
+
+  Diag(Loc, diag::err_vmt_declared_outside_of_local_class) << T << RD;
+  Diag(TD->getLocation(), diag::note_vmt_type_declared_here);
+  return true;
+}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3db91b00f9d80..b2476ef5d7da2 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6513,6 +6513,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
   TypeSourceInfo *TInfo = GetTypeForDeclarator(D);
   QualType R = TInfo->getType();
 
+  if (DiagnoseVLAInLocalClass(R, D.getIdentifierLoc()))
+    D.setInvalidType();
+
   if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
                                       UPPC_DeclarationType))
     D.setInvalidType();
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c24601673af36..fb52e7acfa812 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4865,6 +4865,8 @@ Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
   if (IsType) {
     TypeSourceInfo *TInfo;
     (void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo);
+    if (TInfo)
+      DiagnoseVLAInLocalClass(TInfo->getType(), OpLoc);
     return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange);
   }
 
diff --git a/clang/test/SemaCXX/vla-alias-local-class.cpp 
b/clang/test/SemaCXX/vla-alias-local-class.cpp
new file mode 100644
index 0000000000000..60646b4f0e557
--- /dev/null
+++ b/clang/test/SemaCXX/vla-alias-local-class.cpp
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -std=gnu++20 -verify %s
+
+int foo();
+
+// VLA alias used in normal function scope — no error.
+int test0() {
+  using X = int[foo()];
+  X x;
+  return 0;
+}
+
+// VLA alias declared inside the local class itself — no error.
+int test1() {
+  struct S {
+    using X = int[foo()];
+    S() { X x; }
+  };
+  return 0;
+}
+
+// VLA alias from enclosing scope used as a variable in a local class
+int test3() {
+  using X = int[foo()]; // expected-note {{type declared here}}
+  struct S {
+    S() {
+      X x; // expected-error {{variably modified type 'X' (aka 'int[f()]') 
from enclosing scope cannot be used in local class 'S'}}
+    }
+  };
+  return 0;
+}
+
+// VLA typedef alias from enclosing scope used as a variable in a local class
+int test4() {
+  typedef int X[foo()]; // expected-note {{type declared here}}
+  struct S {
+    S() {
+      X x; // expected-error {{variably modified type 'X' (aka 'int[f()]') 
from enclosing scope cannot be used in local class 'S'}}
+    }
+  };
+  return 0;
+}
+
+// VLA alias from enclosing scope used in sizeof inside a local class method
+int test5() {
+  using X = int[foo()]; // expected-note {{type declared here}}
+  struct S {
+    int method() {
+      return sizeof(X); // expected-error {{variably modified type 'X' (aka 
'int[f()]') from enclosing scope cannot be used in local class 'S'}}
+    }
+  };
+  return 0;
+}
+
+// VLA alias from enclosing scope used in sizeof in an overriding method
+int bar(int&);
+struct IFace {
+  virtual int a() = 0;
+  virtual ~IFace();
+};
+
+IFace *bad_sizeof_override() {
+  int z = 10;
+  using X = int[bar(z)]; // expected-note {{type declared here}}
+  struct S : public IFace {
+    int a() override {
+      return sizeof(X); // expected-error {{variably modified type 'X' (aka 
'int[f_param(z)]') from enclosing scope cannot be used in local class 'S'}}
+    }
+  };
+  return new S;
+}

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

Reply via email to