[clang] [clang] Respect [[gnu::error]] on functions passed to [[gnu::cleanup]] (PR #152082)

via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 5 20:50:19 PDT 2025


https://github.com/Mr-Anyone updated https://github.com/llvm/llvm-project/pull/152082

>From c0fda068d6a17845593702ea6198ad458bec217d Mon Sep 17 00:00:00 2001
From: Vincent <llvm at viceroygroup.ca>
Date: Tue, 5 Aug 2025 13:39:02 +0800
Subject: [PATCH 1/3] [clang] Emit Error for Cleanup Attribute Functions Marked
 with Error Attribute

Forward SourceLocation to `EmitCall` so that clang triggers an error when
a function inside [[gnu::cleanup(func)]] is annotated with [[gnu::error("...")]].

resolves #146520
---
 clang/docs/ReleaseNotes.rst                           |  2 ++
 clang/lib/CodeGen/CGDecl.cpp                          | 11 +++++++++--
 .../backend-attribute-error-warning-optimize.c        | 10 ++++++++++
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9231f2cae9bfa..4fc354e254e38 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -152,6 +152,8 @@ Bug Fixes to Attribute Support
 
 - ``[[nodiscard]]`` is now respected on Objective-C and Objective-C++ methods.
   (#GH141504)
+- Using ``[[gnu::cleanup(some_func)]]`` where some_func is annotated with
+  ``[[gnu::error("some error")]]`` now correctly triggers an error. (#GH146520)
 
 Bug Fixes to C++ Support
 ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 04f13c7d7a6a3..8f1d1fac3f083 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -624,8 +624,15 @@ namespace {
       CallArgList Args;
       Args.add(RValue::get(Arg),
                CGF.getContext().getPointerType(Var.getType()));
-      auto Callee = CGCallee::forDirect(CleanupFn);
-      CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args);
+      bool HasCleanupAttr = Var.hasAttr<CleanupAttr>();
+      GlobalDecl GD = HasCleanupAttr
+                          ? (Var.getAttr<CleanupAttr>()->getFunctionDecl())
+                          : GlobalDecl();
+      SourceLocation Loc = HasCleanupAttr ? Var.getAttr<CleanupAttr>()->getLoc()
+                                          : SourceLocation();
+      auto Callee = CGCallee::forDirect(CleanupFn, CGCalleeInfo(GD));
+      CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args,
+                   /*callOrInvoke*/ nullptr, /*IsMustTail*/ false, Loc);
     }
   };
 } // end anonymous namespace
diff --git a/clang/test/Frontend/backend-attribute-error-warning-optimize.c b/clang/test/Frontend/backend-attribute-error-warning-optimize.c
index d3951e3b6b1f5..d5a8d57e36c96 100644
--- a/clang/test/Frontend/backend-attribute-error-warning-optimize.c
+++ b/clang/test/Frontend/backend-attribute-error-warning-optimize.c
@@ -20,3 +20,13 @@ void indirect(void) {
   quux = foo;
   quux();
 }
+
+// https://github.com/llvm/llvm-project/issues/146520
+
+[[gnu::error("error please")]]
+void cleaner_function(char*);
+
+void asdf(void){
+	[[gnu::cleanup(cleaner_function)]] // expected-error {{call to 'cleaner_function' declared with 'error' attribute: error please}}
+	char x; 
+}

>From c36e978c05a50619f9e92a3c3176d2a0c70fe0cc Mon Sep 17 00:00:00 2001
From: Vincent <llvm at viceroygroup.ca>
Date: Wed, 6 Aug 2025 11:15:20 +0800
Subject: [PATCH 2/3] Saved SourceLocation In CallCleanupFunction

---
 clang/lib/CodeGen/CGDecl.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 8f1d1fac3f083..1dc765d389b5f 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -599,10 +599,11 @@ namespace {
     llvm::Constant *CleanupFn;
     const CGFunctionInfo &FnInfo;
     const VarDecl &Var;
+    SourceLocation Loc;
 
     CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info,
-                        const VarDecl *Var)
-      : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {}
+                        const VarDecl *Var, SourceLocation Location)
+        : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var), Loc(Location) {}
 
     void Emit(CodeGenFunction &CGF, Flags flags) override {
       DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false,
@@ -628,8 +629,6 @@ namespace {
       GlobalDecl GD = HasCleanupAttr
                           ? (Var.getAttr<CleanupAttr>()->getFunctionDecl())
                           : GlobalDecl();
-      SourceLocation Loc = HasCleanupAttr ? Var.getAttr<CleanupAttr>()->getLoc()
-                                          : SourceLocation();
       auto Callee = CGCallee::forDirect(CleanupFn, CGCalleeInfo(GD));
       CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args,
                    /*callOrInvoke*/ nullptr, /*IsMustTail*/ false, Loc);
@@ -2238,7 +2237,8 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
     assert(F && "Could not find function!");
 
     const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD);
-    EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D);
+    EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D,
+                                             CA->getLoc());
   }
 
   // If this is a block variable, call _Block_object_destroy

>From 1c22a113c30b89437a2cfa1fe3ee9527b765b370 Mon Sep 17 00:00:00 2001
From: Vincent <llvm at viceroygroup.ca>
Date: Wed, 6 Aug 2025 11:36:50 +0800
Subject: [PATCH 3/3] Store Pointer to CleanupAttr Instead

---
 clang/lib/CodeGen/CGDecl.cpp | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 1dc765d389b5f..ff2dadad0d4ef 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -599,11 +599,11 @@ namespace {
     llvm::Constant *CleanupFn;
     const CGFunctionInfo &FnInfo;
     const VarDecl &Var;
-    SourceLocation Loc;
+    const CleanupAttr *Attribute;
 
     CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info,
-                        const VarDecl *Var, SourceLocation Location)
-        : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var), Loc(Location) {}
+                        const VarDecl *Var, const CleanupAttr *Attr)
+        : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var), Attribute(Attr) {}
 
     void Emit(CodeGenFunction &CGF, Flags flags) override {
       DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false,
@@ -625,13 +625,11 @@ namespace {
       CallArgList Args;
       Args.add(RValue::get(Arg),
                CGF.getContext().getPointerType(Var.getType()));
-      bool HasCleanupAttr = Var.hasAttr<CleanupAttr>();
-      GlobalDecl GD = HasCleanupAttr
-                          ? (Var.getAttr<CleanupAttr>()->getFunctionDecl())
-                          : GlobalDecl();
+      GlobalDecl GD = GlobalDecl(Attribute->getFunctionDecl());
       auto Callee = CGCallee::forDirect(CleanupFn, CGCalleeInfo(GD));
       CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args,
-                   /*callOrInvoke*/ nullptr, /*IsMustTail*/ false, Loc);
+                   /*callOrInvoke*/ nullptr, /*IsMustTail*/ false,
+                   Attribute->getLoc());
     }
   };
 } // end anonymous namespace
@@ -2238,7 +2236,7 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
 
     const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD);
     EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D,
-                                             CA->getLoc());
+                                             CA);
   }
 
   // If this is a block variable, call _Block_object_destroy



More information about the cfe-commits mailing list