llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: David Meng (davidmenggx)

<details>
<summary>Changes</summary>

In `const char (&amp;s)[N] [[clang::lifetimebound]]`, the attribute comes after 
the array brackets, so C++ attaches it to the array type rather than the 
parameter, and Clang rejected it there.

Move it to the parameter instead, which is what 
`__attribute__((lifetimebound))` in that position already did.

Fixes https://github.com/llvm/llvm-project/issues/221221

---
Full diff: https://github.com/llvm/llvm-project/pull/221627.diff


5 Files Affected:

- (modified) clang/docs/ReleaseNotes.md (+5) 
- (modified) clang/lib/Sema/SemaType.cpp (+14-1) 
- (modified) clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp 
(+6) 
- (modified) clang/test/Sema/attr-lifetimebound.c (+1) 
- (modified) clang/test/SemaCXX/attr-lifetimebound.cpp (+37) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 1686537008499..d0c357281a2e4 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -534,6 +534,11 @@ features cannot lower the translation-unit ABI level;
   written after the declarator-id, where it appertains to the declared entity
   rather than to a declarator chunk. (#GH196982, #GH111463)
 
+- `[[clang::lifetimebound]]` is no longer rejected when written after a
+  parameter's array bound (e.g. `const char (&s)[N] [[clang::lifetimebound]]`);
+  it now marks the parameter, as `__attribute__((lifetimebound))` already did.
+  (#GH221221)
+
 #### Bug Fixes to C++ Support
 
 - Fixed a false type mismatch when a typedef naming an anonymous enumeration
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 9de4f12aabf68..e54b8516438bb 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8993,12 +8993,25 @@ static void HandleAnnotateTypeAttr(TypeProcessingState 
&State,
 static void HandleLifetimeBoundAttr(TypeProcessingState &State,
                                     QualType &CurType,
                                     ParsedAttr &Attr) {
-  if (State.getDeclarator().isDeclarationOfFunction()) {
+  Declarator &D = State.getDeclarator();
+  if (D.isDeclarationOfFunction()) {
     CurType = State.getAttributedType(
         createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr),
         CurType, CurType);
     return;
   }
+  // An attribute-specifier-seq after an array bound appertains to the array
+  // type ([dcl.array]p1), so it lands on the array chunk rather than on the
+  // parameter:
+  //   int *f(const char (&s)[4] [[clang::lifetimebound]]);
+  // Apply it to the parameter, as the GNU spelling already does.
+  if (D.isPrototypeContext() &&
+      D.getTypeObject(State.getCurrentChunkIndex()).Kind ==
+          DeclaratorChunk::Array) {
+    moveAttrFromListToList(Attr, State.getCurrentAttributes(),
+                           D.getAttributes());
+    return;
+  }
   State.getSema().Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
       << Attr << Attr.isRegularKeywordAttribute()
       << ExpectedParameterOrImplicitObjectParameter;
diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp 
b/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp
index dde1c8f7e2431..839dfcc61e6c8 100644
--- a/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp
+++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp
@@ -81,6 +81,12 @@ View param_default(View a = View()) {
   return a;
 }
 
+const char *arr_ref_param(const char (&a)[2]) {
+  // CHECK: :[[@LINE-1]]:45: warning: parameter in intra-TU function should be 
marked
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:45-[[@LINE-2]]:45}:" 
{{\[\[}}clang::lifetimebound]]"
+  return a;
+}
+
 int *arr_default(int a[2] = nullptr) {
   // CHECK: :[[@LINE-1]]:23: warning: parameter in intra-TU function should be 
marked
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:23-[[@LINE-2]]:23}:" 
{{\[\[}}clang::lifetimebound]]"
diff --git a/clang/test/Sema/attr-lifetimebound.c 
b/clang/test/Sema/attr-lifetimebound.c
index 6292fe90bdf68..e7ea37f5c9081 100644
--- a/clang/test/Sema/attr-lifetimebound.c
+++ b/clang/test/Sema/attr-lifetimebound.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c2x -verify %s
 
 int *ptr_param(int *param [[clang::lifetimebound]]);
+int *array_param(int param[4] [[clang::lifetimebound]]);
 int *ptr_param_gnu(int *param __attribute__((lifetimebound)));
 int *ptr_param_redecl(int *param);
 int *ptr_param_redecl(int *param [[clang::lifetimebound]]);
diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp 
b/clang/test/SemaCXX/attr-lifetimebound.cpp
index 9e2aaff6559c4..74800202a7bb0 100644
--- a/clang/test/SemaCXX/attr-lifetimebound.cpp
+++ b/clang/test/SemaCXX/attr-lifetimebound.cpp
@@ -28,6 +28,13 @@ namespace usage_invalid {
   int (*(*func_ptr_ptr)(int) [[clang::lifetimebound]])(int); // expected-error 
{{'clang::lifetimebound' attribute only applies to parameters and implicit 
object parameters}}
   struct X {};
   int (X::*member_func_ptr)(int) [[clang::lifetimebound]]; // expected-error 
{{'clang::lifetimebound' attribute only applies to parameters and implicit 
object parameters}}
+
+  int attr_on_array_var[4] [[clang::lifetimebound]]; // expected-error 
{{'clang::lifetimebound' attribute only applies to parameters and implicit 
object parameters}}
+  void attr_on_array_param_void_return(int (&param)[4] 
[[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute cannot 
be applied to a parameter of a function that returns void; did you mean 
'lifetime_capture_by(X)'}}
+  int *attr_on_array_param_with_args(int (&param)[4] 
[[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}}
+  using attr_on_array_alias = int[4] [[clang::lifetimebound]]; // 
expected-error {{'clang::lifetimebound' attribute only applies to parameters 
and implicit object parameters}}
+  static_assert(sizeof(int[4] [[clang::lifetimebound]]) > 0); // 
expected-error {{'clang::lifetimebound' attribute only applies to parameters 
and implicit object parameters}} \
+                                                              // 
expected-warning {{'clang::lifetimebound' attribute ignored when parsing type}}
 }
 
 namespace usage_ok {
@@ -383,3 +390,33 @@ void test(StatusOr<FooView> foo1, 
StatusOr<NonAnnotatedFooView> foo2) {
   foo2 = NonAnnotatedFoo(); // expected-warning {{object backing 'foo2' will 
be destroyed at the end}}
 }
 } // namespace GH106372
+
+namespace array_params {
+  // An attribute written after an array bound is applied to the parameter.
+  const char *ref_to_array(const char (&a)[4] [[clang::lifetimebound]]) { 
return a; }
+  int *decayed_array(int a[4] [[clang::lifetimebound]]);
+  int *ptr_to_array(int (*a)[4] [[clang::lifetimebound]]);
+  template <int N> const char *dependent_ref_to_array(const char (&a)[N] 
[[clang::lifetimebound]]);
+  const char *gnu_ref_to_array(const char (&a)[4] 
__attribute__((lifetimebound)));
+
+  const char *test_ref_to_array() {
+    char a[4];
+    return ref_to_array(a); // expected-warning {{address of stack memory 
associated with local variable 'a' returned}}
+  }
+  int *test_decayed_array() {
+    int a[4];
+    return decayed_array(a); // expected-warning {{address of stack memory 
associated with local variable 'a' returned}}
+  }
+  int *test_ptr_to_array() {
+    int a[4];
+    return ptr_to_array(&a); // expected-warning {{address of stack memory 
associated with local variable 'a' returned}}
+  }
+  const char *test_dependent_ref_to_array() {
+    char a[4];
+    return dependent_ref_to_array(a); // expected-warning {{address of stack 
memory associated with local variable 'a' returned}}
+  }
+  const char *test_gnu_ref_to_array() {
+    char a[4];
+    return gnu_ref_to_array(a); // expected-warning {{address of stack memory 
associated with local variable 'a' returned}}
+  }
+} // namespace array_params

``````````

</details>


https://github.com/llvm/llvm-project/pull/221627
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to