[clang] Move const qualification of array to its elements (PR #131366)

Serge Pavlov via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 14 10:42:13 PDT 2025


https://github.com/spavloff created https://github.com/llvm/llvm-project/pull/131366

Const-qualification of an array caused by constexpr specifier can produce QualType, where the const qualifier is set both as fast qualifier and as a qualifier of the array element type. It can result in a compiler crash, because such QualType does not compare equal to the same type but without extra qualification.

As a fix, the const qualifier is moved to the array element type when setting the implicit const.

It fixes https://github.com/llvm/llvm-project/issues/97005 (Clang crashed in ASTContext::getCommonSugaredType).

>From 22e4fa0d003679135000cdf0d0bb48fd1b3ee7fe Mon Sep 17 00:00:00 2001
From: Serge Pavlov <sepavloff at gmail.com>
Date: Thu, 13 Mar 2025 12:35:59 +0700
Subject: [PATCH] Move const qualification of array to its elements

Const-qualification of an array caused by constexpr specifier can
produce QualType, where the const qualifier is set both as fast
qualifier and as a qualifier of the array element type. It can result in
a compiler crash, because such QualType does not compare equal to the
same type but without extra qualification.

As a fix, the const qualifier is moved to the array element type when
setting the implicit const.

It fixes https://github.com/llvm/llvm-project/issues/97005 (Clang
crashed in ASTContext::getCommonSugaredType).
---
 clang/lib/Sema/SemaType.cpp                           | 7 ++++++-
 clang/test/AST/ByteCode/constexpr.c                   | 2 +-
 clang/test/Sema/constexpr.c                           | 2 +-
 clang/test/SemaCXX/constexpr-implicit-const-97005.cpp | 8 ++++++++
 4 files changed, 16 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/SemaCXX/constexpr-implicit-const-97005.cpp

diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 11943c0b53591..dee678aa69e83 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -5613,8 +5613,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
   //  A constexpr specifier used in an object declaration declares the object
   //  as const.
   if (D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr &&
-      T->isObjectType())
+      T->isObjectType()) {
     T.addConst();
+    // C++ 9.3.3.4p3: Any type of the form "cv-qualifier-seq array of N U" is
+    // adjusted to "array of N cv-qualifier-seq U".
+    if (const ArrayType *AType = Context.getAsArrayType(T))
+      T = QualType(AType, 0);
+  }
 
   // C++2a [dcl.fct]p4:
   //   A parameter with volatile-qualified type is deprecated
diff --git a/clang/test/AST/ByteCode/constexpr.c b/clang/test/AST/ByteCode/constexpr.c
index af96bf3a06f37..a4a8bde266e76 100644
--- a/clang/test/AST/ByteCode/constexpr.c
+++ b/clang/test/AST/ByteCode/constexpr.c
@@ -82,7 +82,7 @@ constexpr TheA V19[3] = {};
 constexpr TheV V20[3] = {};
 // both-error at -1 {{constexpr variable cannot have type 'const TheV[3]' (aka 'const volatile short[3]')}}
 constexpr TheR V21[3] = {};
-// both-error at -1 {{constexpr variable cannot have type 'const TheR[3]' (aka 'float *restrict const[3]')}}
+// both-error at -1 {{constexpr variable cannot have type 'const TheR[3]' (aka 'float *const restrict[3]')}}
 
 struct HasA {
   TheA f;
diff --git a/clang/test/Sema/constexpr.c b/clang/test/Sema/constexpr.c
index 3dcb0b3a7d95f..005e980563cc7 100644
--- a/clang/test/Sema/constexpr.c
+++ b/clang/test/Sema/constexpr.c
@@ -81,7 +81,7 @@ constexpr TheA V19[3] = {};
 constexpr TheV V20[3] = {};
 // expected-error at -1 {{constexpr variable cannot have type 'const TheV[3]' (aka 'const volatile short[3]')}}
 constexpr TheR V21[3] = {};
-// expected-error at -1 {{constexpr variable cannot have type 'const TheR[3]' (aka 'float *restrict const[3]')}}
+// expected-error at -1 {{constexpr variable cannot have type 'const TheR[3]' (aka 'float *const restrict[3]')}}
 
 struct HasA {
   TheA f;
diff --git a/clang/test/SemaCXX/constexpr-implicit-const-97005.cpp b/clang/test/SemaCXX/constexpr-implicit-const-97005.cpp
new file mode 100644
index 0000000000000..78e9b11f4d61c
--- /dev/null
+++ b/clang/test/SemaCXX/constexpr-implicit-const-97005.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -ast-dump %s | FileCheck %s
+
+bool aaa;
+constexpr const unsigned char ccc[] = { 5 };
+constexpr const unsigned char ddd[1] = { 0 };
+auto bbb = (aaa ? ddd : ccc);
+
+// CHECK: DeclRefExpr {{.*}} 'const unsigned char[1]' {{.*}} 'ddd' 'const unsigned char[1]'



More information about the cfe-commits mailing list