[clang] [clang][CodeGen] Set `dead_on_return` on indirect pointer arguments (PR #148159)

John McCall via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 14 09:24:46 PDT 2025


================
@@ -2852,8 +2852,17 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
       if (AI.getInReg())
         Attrs.addAttribute(llvm::Attribute::InReg);
 
-      if (AI.getIndirectByVal())
+      // Depending on the ABI, this may be either a byval or a dead_on_return
+      // argument.
+      if (AI.getIndirectByVal()) {
         Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType));
+      } else {
+        // If the argument type has a non-trivial destructor that the caller has
+        // to invoke, this cannot be a dead_on_return argument.
+        const auto *RD = ParamType->getAsCXXRecordDecl();
+        if (!RD || (RD && RD->hasTrivialDestructor()))
+          Attrs.addAttribute(llvm::Attribute::DeadOnReturn);
+      }
----------------
rjmccall wrote:

Please use:

```
  if (!ParamType.isDestructedType() || !ParamType->isRecordType() ||
      ParamType->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee())
```

We do destroy parameters in the callee in several situations. The most important example is the MSVC C++ ABI, but I believe that coincidentally never uses indirect argument passing, so it wouldn't be testable. The testable example would be something like this in Objective-C++:

```
struct HasWeakReference {
  __weak id ref;
};
void test(HasWeakReference) {} // should still be dead_on_return because the caller is not responsible to destroy it
```

`__weak` helpfully forces the struct to be passed indirectly, but you could also just use a `__strong id ref;` in a struct that's big enough to be passed indirectly on the target.

https://github.com/llvm/llvm-project/pull/148159


More information about the cfe-commits mailing list