[clang] [Clang][Parse] Diagnose member template declarations with multiple declarators (PR #78243)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 16 01:29:33 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Krystian Stasiowski (sdkrystian)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/78243.diff
4 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+1)
- (modified) clang/lib/Parse/ParseDeclCXX.cpp (+9)
- (modified) clang/test/CXX/temp/p3.cpp (+6)
- (modified) clang/test/OpenMP/declare_simd_messages.cpp (+1-2)
``````````diff
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 at +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 at +1 {{single declaration is expected after 'declare simd' directive}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/78243
More information about the cfe-commits
mailing list