[clang] [Clang] Fixed the behavior of C23 auto when an array type was specified for a `char *` (PR #189722)
Tony Guillot via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 31 11:04:57 PDT 2026
https://github.com/to268 created https://github.com/llvm/llvm-project/pull/189722
At the time of the implementation of [N3007](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3007.htm) in Clang, when an array type was specified, an error was emitted unless the deduced type was a `char *`.
After further inspection in the C standard, it turns out that the inferred type of an `char[]` should be deduced to a `char *`, which should emit an error if an array type is specified with `auto`.
This now invalidates the following cases:
```c
auto s1[] = "test";
auto s2[4] = "test";
auto s3[5] = "test";
```
Fixes #162694
>From 121baa9a5477c079f55d8f5cea373991c979159d Mon Sep 17 00:00:00 2001
From: Tony Guillot <tony.guillot at protonmail.com>
Date: Tue, 31 Mar 2026 19:30:33 +0200
Subject: [PATCH 1/2] Fixed C23 auto when an array type was specified for a
`char *`
---
clang/docs/ReleaseNotes.rst | 13 +++++++------
clang/lib/Sema/SemaTemplateDeduction.cpp | 10 ----------
clang/test/C/C23/n3007.c | 2 --
clang/test/CodeGen/auto.c | 1 -
clang/test/Sema/c2x-auto.c | 17 ++++++++++++-----
5 files changed, 19 insertions(+), 24 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bbbd3a34e01d6..10588c4c8df08 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -113,7 +113,7 @@ Clang Python Bindings Potentially Breaking Changes
``locations`` argument are passed. Previousy, ``locations`` took precedence.
- ``_CXUnsavedFile`` will be renamed to ``UnsavedFile`` for consistency.
``UnsavedFile`` is already available to use and existing uses should
- be adapted to refer to it instead. ``_CXUnsavedFile`` will be removed in a
+ be adapted to refer to it instead. ``_CXUnsavedFile`` will be removed in a
future release.
What's New in Clang |release|?
@@ -324,7 +324,7 @@ Improvements to Clang's diagnostics
when accessing a member function on a past-the-end array element.
(#GH179128)
-- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
+- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
made sure that only one such diagnostic and FixIt is emitted per declaration group. (#GH179354)
- Fixed the Fix-It insertion point for ``expected ';' after alias declaration``
@@ -337,7 +337,7 @@ Improvements to Clang's diagnostics
- The ``-Wloop-analysis`` warning has been extended to catch more cases of
variable modification inside lambda expressions (#GH132038).
-- Clang now emits ``-Wsizeof-pointer-memaccess`` when snprintf/vsnprintf use the sizeof
+- Clang now emits ``-Wsizeof-pointer-memaccess`` when snprintf/vsnprintf use the sizeof
the destination buffer(dynamically allocated) in the len parameter(#GH162366)
- Added ``-Wmodule-map-path-outside-directory`` (off by default) to warn on
@@ -384,6 +384,7 @@ Bug Fixes in This Version
- Correctly diagnosing and no longer crashing when ``export module foo``
(without a semicolon) are the final tokens in a module file. (#GH187771)
- Fixed a crash in duplicate attribute checking caused by comparing constant arguments with different integer signedness. (#GH188259)
+- Fixed the behavior in C23 of ``auto``, by emitting an error when an array type is specified for a ``char *``. (#GH162694)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -406,7 +407,7 @@ Bug Fixes to C++ Support
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
- Fixed a crash when instantiating an invalid out-of-line static data member definition in a local class. (#GH176152)
- Fixed a crash when pack expansions are used as arguments for non-pack parameters of built-in templates. (#GH180307)
-- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable
+- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable
when used inside decltype in the return type. (#GH180460)
- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044)
- Fixed a crash when `explicit(bool)` is used with an incomplete enumeration. (#GH183887)
@@ -414,8 +415,8 @@ Bug Fixes to C++ Support
- Fixed a crash when an immediate-invoked ``consteval`` lambda is used as an invalid initializer. (#GH185270)
- Fixed an assertion failure when using a global destructor with a target with a non-default program address space. (#GH186484)
-- Inherited constructors in ``dllexport`` classes are now exported for ABI-compatible cases, matching
- MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported
+- Inherited constructors in ``dllexport`` classes are now exported for ABI-compatible cases, matching
+ MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported
and produce a warning. (#GH162640)
- Fix initialization of GRO when GRO-return type mismatches, as part of CWG2563. (#GH98744)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index f18a34415ba43..696609d937850 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5224,16 +5224,6 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result,
return TemplateDeductionResult::Success;
}
- // Make sure that we treat 'char[]' equaly as 'char*' in C23 mode.
- auto *String = dyn_cast<StringLiteral>(Init);
- if (getLangOpts().C23 && String && Type.getType()->isArrayType()) {
- Diag(Type.getBeginLoc(), diag::ext_c23_auto_non_plain_identifier);
- TypeLoc TL = TypeLoc(Init->getType(), Type.getOpaqueData());
- Result = SubstituteDeducedTypeTransform(*this, DependentResult).Apply(TL);
- assert(!Result.isNull() && "substituting DependentTy can't fail");
- return TemplateDeductionResult::Success;
- }
-
// Emit a warning if 'auto*' is used in pedantic and in C23 mode.
if (getLangOpts().C23 && Type.getType()->isPointerType()) {
Diag(Type.getBeginLoc(), diag::ext_c23_auto_non_plain_identifier);
diff --git a/clang/test/C/C23/n3007.c b/clang/test/C/C23/n3007.c
index b8b84519fc19d..46bbfa48dda50 100644
--- a/clang/test/C/C23/n3007.c
+++ b/clang/test/C/C23/n3007.c
@@ -107,12 +107,10 @@ void test_misc(void) {
auto something; // expected-error {{declaration of variable 'something' with deduced type 'auto' requires an initializer}}
auto test_char = 'A';
auto test_char_ptr = "test";
- auto test_char_ptr2[] = "another test"; // expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}}
auto auto_size = sizeof(auto); // expected-error {{expected expression}}
_Static_assert(_Generic(test_char, int : 1));
_Static_assert(_Generic(test_char_ptr, char * : 1));
- _Static_assert(_Generic(test_char_ptr2, char * : 1));
}
void test_no_integer_promotions(void) {
diff --git a/clang/test/CodeGen/auto.c b/clang/test/CodeGen/auto.c
index e5bc1bf66138f..844fd37b309b9 100644
--- a/clang/test/CodeGen/auto.c
+++ b/clang/test/CodeGen/auto.c
@@ -7,7 +7,6 @@ void basic_types(void) {
auto bl = true; // CHECK: alloca i8
auto chr = 'A'; // CHECK: alloca i{{8|32}}
auto str = "Test"; // CHECK: alloca ptr
- auto str2[] = "Test"; // CHECK: alloca [5 x i8]
auto nptr = nullptr; // CHECK: alloca ptr
}
diff --git a/clang/test/Sema/c2x-auto.c b/clang/test/Sema/c2x-auto.c
index 7d62db9ea6c28..6b92690003645 100644
--- a/clang/test/Sema/c2x-auto.c
+++ b/clang/test/Sema/c2x-auto.c
@@ -84,16 +84,16 @@ void test_qualifiers(const int y) {
_Static_assert(_Generic(pc, int * : 1));
}
-void test_strings(void) {
+void test_parens(void) {
auto str = "this is a string";
- auto str2[] = "this is a string"; // expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}}
- auto (str3) = "this is a string";
- auto (((str4))) = "this is a string";
+ auto (str2) = "this is a string";
+ auto (((str3))) = "this is a string";
+ auto ((((x)))) = 12;
_Static_assert(_Generic(str, char * : 1));
_Static_assert(_Generic(str2, char * : 1));
_Static_assert(_Generic(str3, char * : 1));
- _Static_assert(_Generic(str4, char * : 1));
+ _Static_assert(_Generic(x, int : 1));
}
void test_pointers(void) {
@@ -137,3 +137,10 @@ void test_scopes(void) {
expected-error {{'auto' not allowed in function return type}}
return x;
}
+
+
+void test_incompatible_initializer(void) {
+ auto s1[] = "test"; // expected-error {{variable 's1' with type 'auto[]' has incompatible initializer of type 'char[5]'}}
+ auto s2[4] = "test"; // expected-error {{variable 's2' with type 'auto[4]' has incompatible initializer of type 'char[5]'}}
+ auto s3[5] = "test"; // expected-error {{variable 's3' with type 'auto[5]' has incompatible initializer of type 'char[5]'}}
+}
>From f89db10f42b0c4dcd6c4403a362625f3d4e8f35c Mon Sep 17 00:00:00 2001
From: Tony Guillot <tony.guillot at protonmail.com>
Date: Tue, 31 Mar 2026 19:39:49 +0200
Subject: [PATCH 2/2] Formatted ReleaseNotes
---
clang/docs/ReleaseNotes.rst | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 10588c4c8df08..cb69dbef3d2e5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -113,7 +113,7 @@ Clang Python Bindings Potentially Breaking Changes
``locations`` argument are passed. Previousy, ``locations`` took precedence.
- ``_CXUnsavedFile`` will be renamed to ``UnsavedFile`` for consistency.
``UnsavedFile`` is already available to use and existing uses should
- be adapted to refer to it instead. ``_CXUnsavedFile`` will be removed in a
+ be adapted to refer to it instead. ``_CXUnsavedFile`` will be removed in a
future release.
What's New in Clang |release|?
@@ -324,7 +324,7 @@ Improvements to Clang's diagnostics
when accessing a member function on a past-the-end array element.
(#GH179128)
-- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
+- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
made sure that only one such diagnostic and FixIt is emitted per declaration group. (#GH179354)
- Fixed the Fix-It insertion point for ``expected ';' after alias declaration``
@@ -337,7 +337,7 @@ Improvements to Clang's diagnostics
- The ``-Wloop-analysis`` warning has been extended to catch more cases of
variable modification inside lambda expressions (#GH132038).
-- Clang now emits ``-Wsizeof-pointer-memaccess`` when snprintf/vsnprintf use the sizeof
+- Clang now emits ``-Wsizeof-pointer-memaccess`` when snprintf/vsnprintf use the sizeof
the destination buffer(dynamically allocated) in the len parameter(#GH162366)
- Added ``-Wmodule-map-path-outside-directory`` (off by default) to warn on
@@ -407,7 +407,7 @@ Bug Fixes to C++ Support
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
- Fixed a crash when instantiating an invalid out-of-line static data member definition in a local class. (#GH176152)
- Fixed a crash when pack expansions are used as arguments for non-pack parameters of built-in templates. (#GH180307)
-- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable
+- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable
when used inside decltype in the return type. (#GH180460)
- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044)
- Fixed a crash when `explicit(bool)` is used with an incomplete enumeration. (#GH183887)
@@ -415,8 +415,8 @@ Bug Fixes to C++ Support
- Fixed a crash when an immediate-invoked ``consteval`` lambda is used as an invalid initializer. (#GH185270)
- Fixed an assertion failure when using a global destructor with a target with a non-default program address space. (#GH186484)
-- Inherited constructors in ``dllexport`` classes are now exported for ABI-compatible cases, matching
- MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported
+- Inherited constructors in ``dllexport`` classes are now exported for ABI-compatible cases, matching
+ MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported
and produce a warning. (#GH162640)
- Fix initialization of GRO when GRO-return type mismatches, as part of CWG2563. (#GH98744)
More information about the cfe-commits
mailing list