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..ff2dadad0d4ef 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; + const CleanupAttr *Attribute; CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info, - const VarDecl *Var) - : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {} + 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(&Var), false, @@ -624,8 +625,11 @@ namespace { CallArgList Args; Args.add(RValue::get(Arg), CGF.getContext().getPointerType(Var.getType())); - auto Callee = CGCallee::forDirect(CleanupFn); - CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args); + GlobalDecl GD = GlobalDecl(Attribute->getFunctionDecl()); + auto Callee = CGCallee::forDirect(CleanupFn, CGCalleeInfo(GD)); + CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args, + /*callOrInvoke*/ nullptr, /*IsMustTail*/ false, + Attribute->getLoc()); } }; } // end anonymous namespace @@ -2231,7 +2235,8 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { assert(F && "Could not find function!"); const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD); - EHStack.pushCleanup(NormalAndEHCleanup, F, &Info, &D); + EHStack.pushCleanup(NormalAndEHCleanup, F, &Info, &D, + CA); } // If this is a block variable, call _Block_object_destroy 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; +}