Skip to content

[Clang][CodeGen] Mark __dynamic_cast as willreturn #80409

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 4, 2024

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Feb 2, 2024

According to the C++ standard, dynamic_cast of pointers either returns a pointer (7.6.1.7) or results in undefined behavior (11.9.5). This patch marks __dynamic_cast as willreturn to remove unused calls.

Fixes #77606.

@dtcxzyw dtcxzyw added c++ clang:codegen IR generation bugs: mangling, exceptions, etc. labels Feb 2, 2024
@dtcxzyw dtcxzyw requested review from nikic, cor3ntin and shafik February 2, 2024 09:08
@llvmbot llvmbot added the clang Clang issues not falling into any other category label Feb 2, 2024
@llvmbot
Copy link
Member

llvmbot commented Feb 2, 2024

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-codegen

Author: Yingwei Zheng (dtcxzyw)

Changes

According to the C++ standard, dynamic_cast of pointers either returns a pointer (7.6.1.7) or results in undefined behavior (11.9.5). This patch marks __dynamic_cast as willreturn to remove unused calls.

Fixes #77606.


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

4 Files Affected:

  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+2-1)
  • (modified) clang/test/CodeGenCXX/dynamic-cast-address-space.cpp (+1-1)
  • (added) clang/test/CodeGenCXX/dynamic-cast-dead.cpp (+8)
  • (modified) clang/test/CodeGenCXX/dynamic-cast.cpp (+1-1)
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index d173806ec8ce5..60b45ee78d931 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -1347,9 +1347,10 @@ static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF) {
 
   llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
 
-  // Mark the function as nounwind readonly.
+  // Mark the function as nounwind willreturn readonly.
   llvm::AttrBuilder FuncAttrs(CGF.getLLVMContext());
   FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
+  FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
   FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
   llvm::AttributeList Attrs = llvm::AttributeList::get(
       CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
diff --git a/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp b/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp
index c278988c9647b..83a408984b760 100644
--- a/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp
+++ b/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp
@@ -20,5 +20,5 @@ const B& f(A *a) {
 
 // CHECK: declare ptr @__dynamic_cast(ptr, ptr addrspace(1), ptr addrspace(1), i64) [[NUW_RO:#[0-9]+]]
 
-// CHECK: attributes [[NUW_RO]] = { nounwind memory(read) }
+// CHECK: attributes [[NUW_RO]] = { nounwind willreturn memory(read) }
 // CHECK: attributes [[NR]] = { noreturn }
diff --git a/clang/test/CodeGenCXX/dynamic-cast-dead.cpp b/clang/test/CodeGenCXX/dynamic-cast-dead.cpp
new file mode 100644
index 0000000000000..8154cc1ba123a
--- /dev/null
+++ b/clang/test/CodeGenCXX/dynamic-cast-dead.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -I%S %s -O3 -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -std=c++11 -o - | FileCheck %s
+struct A { virtual ~A(); };
+struct B : A { };
+
+void foo(A* a) {
+  // CHECK-NOT: call {{.*}} @__dynamic_cast
+  B* b = dynamic_cast<B*>(a);
+}
diff --git a/clang/test/CodeGenCXX/dynamic-cast.cpp b/clang/test/CodeGenCXX/dynamic-cast.cpp
index 1d36376a55bc7..b39186c85b60a 100644
--- a/clang/test/CodeGenCXX/dynamic-cast.cpp
+++ b/clang/test/CodeGenCXX/dynamic-cast.cpp
@@ -20,5 +20,5 @@ const B& f(A *a) {
 
 // CHECK: declare ptr @__dynamic_cast(ptr, ptr, ptr, i64) [[NUW_RO:#[0-9]+]]
 
-// CHECK: attributes [[NUW_RO]] = { nounwind memory(read) }
+// CHECK: attributes [[NUW_RO]] = { nounwind willreturn memory(read) }
 // CHECK: attributes [[NR]] = { noreturn }

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, nice find!

@dtcxzyw dtcxzyw merged commit a3d8b78 into llvm:main Feb 4, 2024
@dtcxzyw dtcxzyw deleted the dyn_cast_willreturn branch February 4, 2024 03:31
agozillon pushed a commit to agozillon/llvm-project that referenced this pull request Feb 5, 2024
According to the C++ standard, `dynamic_cast` of pointers either returns
a pointer (7.6.1.7) or results in undefined behavior (11.9.5). This
patch marks `__dynamic_cast` as `willreturn` to remove unused calls.

Fixes llvm#77606.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Superfluous dynamic_cast not optimized out
3 participants