https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/124920
>From bd731e4be65fc9c1746aa6a8f63d206eb54bb2be Mon Sep 17 00:00:00 2001 From: Oleksandr T <oleksandr.taras...@outlook.com> Date: Wed, 29 Jan 2025 15:17:06 +0200 Subject: [PATCH 1/4] [Clang] disallow attributes on void parameters --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Parse/ParseDecl.cpp | 7 +++++++ clang/test/Parser/cxx0x-attributes.cpp | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7fafe2807bd3883..0c87e52007d5463 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -100,6 +100,8 @@ Removed Compiler Flags Attribute Changes in Clang -------------------------- +- Clang now disallows the use of attributes on void parameters. (#GH108819) + Improvements to Clang's diagnostics ----------------------------------- diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f136d5007e8a5f0..0b88dd4449b1e28 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -7986,6 +7986,13 @@ void Parser::ParseParameterDeclarationClause( if (getLangOpts().HLSL) MaybeParseHLSLAnnotations(DS.getAttributes()); + if (ParmDeclarator.getIdentifier() == nullptr && + ParmDeclarator.getDeclarationAttributes().size() && + ParmDeclarator.getDeclSpec().getTypeSpecType() == DeclSpec::TST_void) { + SourceRange AttrRange = ParmDeclarator.getDeclarationAttributes().Range; + Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed) << AttrRange; + } + if (Tok.is(tok::kw_requires)) { // User tried to define a requires clause in a parameter declaration, // which is surely not a function declaration. diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index fad3010c98b9c28..13fcdd142fa841f 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -453,3 +453,12 @@ namespace P2361 { } alignas(int) struct AlignAsAttribute {}; // expected-error {{misplaced attributes; expected attributes here}} + +namespace GH108819 { +void a([[maybe_unused]] void) {} // expected-error {{an attribute list cannot appear here}} \ + // expected-warning {{use of the 'maybe_unused' attribute is a C++17 extension}} +void b([[deprecated]] void) {} // expected-error {{an attribute list cannot appear here}} \ + // expected-warning {{use of the 'deprecated' attribute is a C++14 extension}} +void c([[clang::lifetimebound]] void) {} // expected-error {{an attribute list cannot appear here}} +void d([[clang::annotate("a", "b", 1)]] void) {} // expected-error {{an attribute list cannot appear here}} +} >From 063f76730ebfd289f5340d0d8477a43a5ea965c2 Mon Sep 17 00:00:00 2001 From: Oleksandr T <oleksandr.taras...@outlook.com> Date: Wed, 29 Jan 2025 15:54:48 +0200 Subject: [PATCH 2/4] remove unnecessary name check --- clang/lib/Parse/ParseDecl.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 0b88dd4449b1e28..934c16c95915203 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -7986,8 +7986,7 @@ void Parser::ParseParameterDeclarationClause( if (getLangOpts().HLSL) MaybeParseHLSLAnnotations(DS.getAttributes()); - if (ParmDeclarator.getIdentifier() == nullptr && - ParmDeclarator.getDeclarationAttributes().size() && + if (ParmDeclarator.getDeclarationAttributes().size() && ParmDeclarator.getDeclSpec().getTypeSpecType() == DeclSpec::TST_void) { SourceRange AttrRange = ParmDeclarator.getDeclarationAttributes().Range; Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed) << AttrRange; >From 3f3431513ad59111794953d27e64608b3ce2e6e1 Mon Sep 17 00:00:00 2001 From: Oleksandr T <oleksandr.taras...@outlook.com> Date: Wed, 29 Jan 2025 16:07:18 +0200 Subject: [PATCH 3/4] use empty instead of size --- clang/lib/Parse/ParseDecl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 934c16c95915203..963b59565953d45 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -7986,7 +7986,7 @@ void Parser::ParseParameterDeclarationClause( if (getLangOpts().HLSL) MaybeParseHLSLAnnotations(DS.getAttributes()); - if (ParmDeclarator.getDeclarationAttributes().size() && + if (!ParmDeclarator.getDeclarationAttributes().empty() && ParmDeclarator.getDeclSpec().getTypeSpecType() == DeclSpec::TST_void) { SourceRange AttrRange = ParmDeclarator.getDeclarationAttributes().Range; Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed) << AttrRange; >From 9919006df9ec32023b2bf179b72f9ebaf977bd08 Mon Sep 17 00:00:00 2001 From: Oleksandr T <oleksandr.taras...@outlook.com> Date: Thu, 30 Jan 2025 22:35:16 +0200 Subject: [PATCH 4/4] move handling of void parameter attributes to sema decl --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Parse/ParseDecl.cpp | 6 ------ clang/lib/Sema/SemaDecl.cpp | 9 +++++++++ .../test/Misc/pragma-attribute-strict-subjects.c | 16 ++++++++-------- clang/test/Parser/cxx0x-attributes.cpp | 9 --------- clang/test/SemaCXX/attr-cxx0x.cpp | 11 +++++++++++ 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index db911ed121e9514..59bc932e9f22039 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3830,6 +3830,8 @@ def warn_type_attribute_wrong_type : Warning< "'%0' only applies to %select{function|pointer|" "Objective-C object or block pointer}1 types; type here is %2">, InGroup<IgnoredAttributes>; +def warn_attribute_on_void_param: Warning< + "attribute %0 cannot be applied to a 'void' parameter">, InGroup<IgnoredAttributes>; def err_type_attribute_wrong_type : Error< warn_type_attribute_wrong_type.Summary>; def warn_incomplete_encoded_type : Warning< diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 963b59565953d45..f136d5007e8a5f0 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -7986,12 +7986,6 @@ void Parser::ParseParameterDeclarationClause( if (getLangOpts().HLSL) MaybeParseHLSLAnnotations(DS.getAttributes()); - if (!ParmDeclarator.getDeclarationAttributes().empty() && - ParmDeclarator.getDeclSpec().getTypeSpecType() == DeclSpec::TST_void) { - SourceRange AttrRange = ParmDeclarator.getDeclarationAttributes().Range; - Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed) << AttrRange; - } - if (Tok.is(tok::kw_requires)) { // User tried to define a requires clause in a parameter declaration, // which is surely not a function declaration. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 3cad9827fdab694..ac5aab92b03ae2f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10326,6 +10326,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + if (FTIHasSingleVoidParameter(FTI)) { + ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[0].Param); + if (Param->hasAttrs()) { + for (const auto *A : Param->attrs()) + Diag(A->getLoc(), diag::warn_attribute_on_void_param) + << A << A->getRange(); + } + } + if (!getLangOpts().CPlusPlus) { // In C, find all the tag declarations from the prototype and move them // into the function DeclContext. Remove them from the surrounding tag diff --git a/clang/test/Misc/pragma-attribute-strict-subjects.c b/clang/test/Misc/pragma-attribute-strict-subjects.c index 807977fb252aa6c..3f8b553fb5011f5 100644 --- a/clang/test/Misc/pragma-attribute-strict-subjects.c +++ b/clang/test/Misc/pragma-attribute-strict-subjects.c @@ -50,8 +50,8 @@ struct testRecoverStrictnessStruct { }; #pragma clang attribute pop -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), variable, enum)) -// expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum'}} +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), variable, enum)) // expected-warning {{attribute 'abi_tag' cannot be applied to a 'void' parameter}} + // expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum'}} int testRecoverExtraVar = 0; // CHECK-LABEL: VarDecl{{.*}} testRecoverExtraVar @@ -90,7 +90,7 @@ struct testSubset1Struct { }; #pragma clang attribute pop -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = variable) +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = variable) // expected-warning {{attribute 'abi_tag' cannot be applied to a 'void' parameter}} int testSubset2Var; // CHECK-LABEL: VarDecl{{.*}} testSubset2Var @@ -122,7 +122,7 @@ struct testSubset3Struct { }; #pragma clang attribute pop -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, variable)) +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, variable)) // expected-warning {{attribute 'abi_tag' cannot be applied to a 'void' parameter}} int testSubset4Var; // CHECK-LABEL: VarDecl{{.*}} testSubset4Var @@ -138,7 +138,7 @@ struct testSubset4Struct { }; #pragma clang attribute pop -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(variable, record(unless(is_union)))) +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(variable, record(unless(is_union)))) // expected-warning {{attribute 'abi_tag' cannot be applied to a 'void' parameter}} int testSubset5Var; // CHECK-LABEL: VarDecl{{.*}} testSubset5Var @@ -170,7 +170,7 @@ struct testSubset6Struct { }; #pragma clang attribute pop -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable)) +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable)) // expected-warning {{attribute 'abi_tag' cannot be applied to a 'void' parameter}} int testSubset7Var; // CHECK-LABEL: VarDecl{{.*}} testSubset7Var @@ -187,8 +187,8 @@ struct testSubset7Struct { }; #pragma clang attribute pop -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable, enum, enum_constant)) -// expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum_constant', and 'enum'}} +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable, enum, enum_constant)) // expected-warning {{attribute 'abi_tag' cannot be applied to a 'void' parameter}} + // expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum_constant', and 'enum'}} int testSubsetRecoverVar; // CHECK-LABEL: VarDecl{{.*}} testSubsetRecoverVar diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index 13fcdd142fa841f..fad3010c98b9c28 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -453,12 +453,3 @@ namespace P2361 { } alignas(int) struct AlignAsAttribute {}; // expected-error {{misplaced attributes; expected attributes here}} - -namespace GH108819 { -void a([[maybe_unused]] void) {} // expected-error {{an attribute list cannot appear here}} \ - // expected-warning {{use of the 'maybe_unused' attribute is a C++17 extension}} -void b([[deprecated]] void) {} // expected-error {{an attribute list cannot appear here}} \ - // expected-warning {{use of the 'deprecated' attribute is a C++14 extension}} -void c([[clang::lifetimebound]] void) {} // expected-error {{an attribute list cannot appear here}} -void d([[clang::annotate("a", "b", 1)]] void) {} // expected-error {{an attribute list cannot appear here}} -} diff --git a/clang/test/SemaCXX/attr-cxx0x.cpp b/clang/test/SemaCXX/attr-cxx0x.cpp index 4d64d2b0cd8c63c..5c2e9f7553389ef 100644 --- a/clang/test/SemaCXX/attr-cxx0x.cpp +++ b/clang/test/SemaCXX/attr-cxx0x.cpp @@ -53,3 +53,14 @@ alignas(4) auto PR19252 = 0; // Check the diagnostic message class alignas(void) AlignasVoid {}; // expected-error {{invalid application of 'alignas' to an incomplete type 'void'}} + +namespace GH108819 { +void a([[maybe_unused]] void) {} // expected-warning {{attribute 'maybe_unused' cannot be applied to a 'void' parameter}}\ + // expected-warning {{use of the 'maybe_unused' attribute is a C++17 extension}} +void b([[deprecated, maybe_unused]] void) {} // expected-warning {{attribute 'deprecated' cannot be applied to a 'void' parameter}} \ + // expected-warning {{attribute 'maybe_unused' cannot be applied to a 'void' parameter}} \ + // expected-warning {{use of the 'deprecated' attribute is a C++14 extension}} \ + // expected-warning {{use of the 'maybe_unused' attribute is a C++17 extension}} +void c([[clang::lifetimebound]] void) {} // expected-warning {{attribute 'lifetimebound' cannot be applied to a 'void' parameter}} +void d([[clang::annotate("a", "b", 1)]] void) {} // expected-warning {{attribute 'annotate' cannot be applied to a 'void' parameter}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits