[clang] [clang] Informative error for lifetimebound in decl-spec (PR #118567)

Maksim Ivanov via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 5 03:31:55 PST 2024


https://github.com/emaxx-google updated https://github.com/llvm/llvm-project/pull/118567

>From 204069c8e11db15f0b716d09cab58398b9399598 Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Tue, 3 Dec 2024 22:49:09 +0000
Subject: [PATCH 1/2] [clang] Informative error for lifetimebound in decl-spec

Emit a bit more informative error when the `[[clang::lifetimebound]]`
attribute is wrongly appearing on a decl-spec:

  "'lifetimebound' attribute only applies to parameters and implicit
object parameters",

instead of:

  "'lifetimebound' attribute cannot be applied to types".

The new error is also consistent with the diagnostic emitted when the
attribute is misplaced in other parts of a declarator.
---
 clang/lib/Parse/ParseDecl.cpp             | 10 ++++++++--
 clang/test/SemaCXX/attr-lifetimebound.cpp |  4 ++--
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 937a94b02458c6..caa1a12297bc01 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3703,8 +3703,14 @@ void Parser::ParseDeclarationSpecifiers(
           // We reject AT_LifetimeBound and AT_AnyX86NoCfCheck, even though they
           // are type attributes, because we historically haven't allowed these
           // to be used as type attributes in C++11 / C23 syntax.
-          if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_LifetimeBound &&
-              PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck)
+          if (PA.getKind() == ParsedAttr::AT_LifetimeBound) {
+            Diag(PA.getLoc(), diag::err_attribute_wrong_decl_type_str)
+                << PA << PA.isRegularKeywordAttribute()
+                << "parameters and implicit object parameters";
+            PA.setInvalid();
+            continue;
+          }
+          if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck)
             continue;
           Diag(PA.getLoc(), diag::err_attribute_not_type_attr)
               << PA << PA.isRegularKeywordAttribute();
diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp
index c7abec61873efb..896793f9966666 100644
--- a/clang/test/SemaCXX/attr-lifetimebound.cpp
+++ b/clang/test/SemaCXX/attr-lifetimebound.cpp
@@ -10,7 +10,7 @@ namespace usage_invalid {
     static int *static_class_member() [[clang::lifetimebound]]; // expected-error {{static member function has no implicit object parameter}}
     int *explicit_object(this A&) [[clang::lifetimebound]]; // expected-error {{explicit object member function has no implicit object parameter}}
     int attr_on_var [[clang::lifetimebound]]; // expected-error {{only applies to parameters and implicit object parameters}}
-    int [[clang::lifetimebound]] attr_on_int; // expected-error {{cannot be applied to types}}
+    int [[clang::lifetimebound]] attr_on_int; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
     int * [[clang::lifetimebound]] attr_on_int_ptr; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
     int * [[clang::lifetimebound]] * attr_on_int_ptr_ptr; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
     int (* [[clang::lifetimebound]] attr_on_func_ptr)(); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
@@ -19,7 +19,7 @@ namespace usage_invalid {
   int *attr_with_param(int &param [[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}}
 
   void attr_on_ptr_arg(int * [[clang::lifetimebound]] ptr); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
-  static_assert((int [[clang::lifetimebound]]) 12); // expected-error {{cannot be applied to types}}
+  static_assert((int [[clang::lifetimebound]]) 12); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
   int* attr_on_unnamed_arg(const int& [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
   template <typename T>
   int* attr_on_template_ptr_arg(T * [[clang::lifetimebound]] ptr); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}

>From cfc20181d55d631dcbe98f0012eb37af32ff81cd Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Thu, 5 Dec 2024 11:24:26 +0000
Subject: [PATCH 2/2] refactor diag code

---
 clang/lib/Parse/ParseDecl.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index caa1a12297bc01..7f3f6d568e28cf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3703,17 +3703,17 @@ void Parser::ParseDeclarationSpecifiers(
           // We reject AT_LifetimeBound and AT_AnyX86NoCfCheck, even though they
           // are type attributes, because we historically haven't allowed these
           // to be used as type attributes in C++11 / C23 syntax.
-          if (PA.getKind() == ParsedAttr::AT_LifetimeBound) {
+          if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_LifetimeBound &&
+              PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck)
+            continue;
+
+          if (PA.getKind() == ParsedAttr::AT_LifetimeBound)
             Diag(PA.getLoc(), diag::err_attribute_wrong_decl_type_str)
                 << PA << PA.isRegularKeywordAttribute()
                 << "parameters and implicit object parameters";
-            PA.setInvalid();
-            continue;
-          }
-          if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck)
-            continue;
-          Diag(PA.getLoc(), diag::err_attribute_not_type_attr)
-              << PA << PA.isRegularKeywordAttribute();
+          else
+            Diag(PA.getLoc(), diag::err_attribute_not_type_attr)
+                << PA << PA.isRegularKeywordAttribute();
           PA.setInvalid();
         }
 



More information about the cfe-commits mailing list