https://github.com/keinflue created 
https://github.com/llvm/llvm-project/pull/155064

ParseMisplacedBracketDeclarator assumed that declarators without associated 
identifier are ill-formed and already diagnosed previously. This didn't 
consider declarators using template-ids, constructors, destructors, conversion 
functions, etc.

Fixes #147333.

>From b8f51c5dbad044fdbaf90e3db84f3bbbfaee337a Mon Sep 17 00:00:00 2001
From: keinflue <keinf...@posteo.de>
Date: Sat, 23 Aug 2025 04:50:28 +0200
Subject: [PATCH] [clang] Diagnose misplaced array bounds with non-identifier
 declarators.

ParseMisplacedBracketDeclarator assumed that declarators without associated
identifier are ill-formed and already diagnosed previously. This didn't
consider declarators using template-ids, constructors, destructors, conversion
functions, etc.

Fixes #147333.
---
 clang/docs/ReleaseNotes.rst    |  4 +++
 clang/lib/Parse/ParseDecl.cpp  |  4 +--
 clang/test/Parser/brackets.cpp | 51 +++++++++++++++++++++++++++++++++-
 3 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 465c50784f27f..2b91c622c2b33 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -234,6 +234,10 @@ Improvements to Clang's diagnostics
   however, non-preprocessor use of tokens now triggers a pedantic warning in 
C++.
   Compilation in C mode is unchanged, and still permits these tokens to be 
used. (#GH147217)
 
+- Clang now diagnoses misplaced array bounds on declarators for template
+  specializations in th same way as it already did for other declarators.
+  (#GH147333)
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 65504ff7f6728..10355bb874762 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -7878,9 +7878,9 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator 
&D) {
     D.AddTypeInfo(Chunk, TempDeclarator.getAttributePool(), SourceLocation());
   }
 
-  // The missing identifier would have been diagnosed in ParseDirectDeclarator.
+  // The missing name would have been diagnosed in ParseDirectDeclarator.
   // If parentheses are required, always suggest them.
-  if (!D.getIdentifier() && !NeedParens)
+  if (!D.hasName() && !NeedParens)
     return;
 
   SourceLocation EndBracketLoc = TempDeclarator.getEndLoc();
diff --git a/clang/test/Parser/brackets.cpp b/clang/test/Parser/brackets.cpp
index 927b66a7ebcb8..91d4f9b507c8f 100644
--- a/clang/test/Parser/brackets.cpp
+++ b/clang/test/Parser/brackets.cpp
@@ -158,4 +158,53 @@ struct A {
 const char[] A::f = "f";
 // expected-error@-1{{brackets are not allowed here; to declare an array, 
place the brackets after the name}}
 }
-// CHECK: 15 errors generated.
+
+namespace gh147333 {
+    template<class T, char fmt>
+    constexpr inline auto& to_print_fmt = "";
+    template<> constexpr inline char[] to_print_fmt<unsigned, 'x'> = "0x%x";
+    // expected-error@-1{{brackets are not allowed here; to declare an array, 
place the brackets after the name}}
+
+#ifndef FIXIT
+    // Further related test cases.
+
+    int[1] operator+();
+    // expected-error@-1{{brackets are not allowed here; to declare an array, 
place the brackets after the name}}
+    // expected-error@-2{{function cannot return array type}}
+    
+    int[1] operator ""_x(unsigned long long);
+    // expected-error@-1{{brackets are not allowed here; to declare an array, 
place the brackets after the name}}
+    // expected-error@-2{{function cannot return array type}}
+       
+    struct A {
+        int[1] operator int();
+        // expected-error@-1{{brackets are not allowed here; to declare an 
array, place the brackets after the name}}
+        // TODO: The following is too noisy and redundant.
+        // expected-error@-3{{conversion function cannot have a return type}}
+        // expected-error@-4{{cannot specify any part of a return type in the 
declaration of a conversion function}}
+        // expected-error@-5{{conversion function cannot convert to an array 
type}}
+
+        int[1] A();
+        // expected-error@-1{{brackets are not allowed here; to declare an 
array, place the brackets after the name}}
+        // TODO: The following is too noisy and redundant.
+        // expected-error@-3{{function cannot return array type}}
+        // expected-error@-4{{constructor cannot have a return type}}
+        
+        int[1] ~A();
+        // expected-error@-1{{brackets are not allowed here; to declare an 
array, place the brackets after the name}}
+        // TODO: This isn't helpful.
+        // expected-error@-3{{array has incomplete element type 'void'}}
+    };
+    
+    template<typename T>
+    struct B {
+        int[1] B<T>();
+        // expected-error@-1{{brackets are not allowed here; to declare an 
array, place the brackets after the name}}
+        // TODO: The following is too noisy and redundant.
+        // expected-error@-3{{function cannot return array type}}
+        // expected-error@-4{{constructor cannot have a return type}}
+    };
+#endif
+}
+
+// CHECK: 32 errors generated.

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to