https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/78243
According to [[temp.pre] p5](http://eel.is/c++draft/temp.pre#5): > In a > [template-declaration](http://eel.is/c++draft/temp.pre#nt:template-declaration), > explicit specialization, or explicit instantiation the > [init-declarator-list](http://eel.is/c++draft/dcl.decl.general#nt:init-declarator-list) > in the declaration shall contain at most one declarator. A [member-declaration](http://eel.is/c++draft/class.mem.general#nt:member-declaration) that is a [template-declaration](http://eel.is/c++draft/temp.pre#nt:template-declaration) or [explicit-specialization](http://eel.is/c++draft/temp.expl.spec#nt:explicit-specialization) contains a [declaration](http://eel.is/c++draft/dcl.pre#nt:declaration), even though it declares a member. This means it _will_ contain an [init-declarator-list](http://eel.is/c++draft/dcl.decl.general#nt:init-declarator-list) (not a [member-declarator-list](http://eel.is/c++draft/class.mem.general#nt:member-declarator-list)), so [[temp.pre] p5](http://eel.is/c++draft/temp.pre#5) applies. This diagnoses declarations such as: ```cpp struct A { template<typename T> static const int x = 0, f(); // error: a template declaration can only declare a single entity template<typename T> static const int g(), y = 0; // error: a template declaration can only declare a single entity }; ``` The diagnostic messages are the same as those of the equivalent namespace scope declarations. Note: since we currently do not diagnose declarations with multiple abbreviated function template declarators at namespace scope e.g., `void f(auto), g(auto);`, I did not add diagnostics for the equivalent member declarations. >From 44c582f0e23725b28b46c07bdb0d2991ebb7d204 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Fri, 12 Jan 2024 13:45:15 -0500 Subject: [PATCH] [Clang][Parse] Diagnose member template declarations with multiple declarators --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Parse/ParseDeclCXX.cpp | 9 +++++++++ clang/test/CXX/temp/p3.cpp | 6 ++++++ clang/test/OpenMP/declare_simd_messages.cpp | 3 +-- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ea57769a4a5795..54debc4d40e945 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -555,6 +555,7 @@ Improvements to Clang's diagnostics - Clang now diagnoses unexpanded packs within the template argument lists of function template specializations. - Clang now diagnoses attempts to bind a bitfield to an NTTP of a reference type as erroneous converted constant expression and not as a reference to subobject. +- Clang now diagnoses member template declarations with multiple declarators. Improvements to Clang's time-trace diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 5576be9e717a9b..36a9ef199a9588 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3167,6 +3167,15 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DeclaratorInfo.complete(ThisDecl); + if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { + if (Tok.is(tok::comma)) { + Diag(Tok, diag::err_multiple_template_declarators) + << (int)TemplateInfo.Kind; + SkipUntil(tok::semi, StopBeforeMatch); + } + break; + } + // If we don't have a comma, it is either the end of the list (a ';') // or an error, bail out. SourceLocation CommaLoc; diff --git a/clang/test/CXX/temp/p3.cpp b/clang/test/CXX/temp/p3.cpp index b708c613d352d2..9e561d0b9a83b2 100644 --- a/clang/test/CXX/temp/p3.cpp +++ b/clang/test/CXX/temp/p3.cpp @@ -15,3 +15,9 @@ template<typename T> struct B { } f(); // expected-error {{expected ';' after st template<typename T> struct C { } // expected-error {{expected ';' after struct}} A<int> c; + +struct D { + template<typename T> static const int x = 0, f(); // expected-error {{can only declare a single entity}} + + template<typename T> static const int g(), y = 0; // expected-error {{can only declare a single entity}} +}; diff --git a/clang/test/OpenMP/declare_simd_messages.cpp b/clang/test/OpenMP/declare_simd_messages.cpp index dd24322694b69f..fea045400e1faf 100644 --- a/clang/test/OpenMP/declare_simd_messages.cpp +++ b/clang/test/OpenMP/declare_simd_messages.cpp @@ -33,10 +33,9 @@ int main(); int main(); struct A { -// expected-error@+1 {{function declaration is expected after 'declare simd' directive}} #pragma omp declare simd template<typename T> - T infunc1(T a), infunc2(T a); + T infunc1(T a); }; // expected-error@+1 {{single declaration is expected after 'declare simd' directive}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits