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 + constexpr inline auto& to_print_fmt = ""; + template<> constexpr inline char[] to_print_fmt = "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 + struct B { + int[1] B(); + // 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.