Author: Erich Keane
Date: 2026-05-20T06:24:05-07:00
New Revision: f9585141ff3bc78ae7830c9f39ce562d660c5065

URL: 
https://github.com/llvm/llvm-project/commit/f9585141ff3bc78ae7830c9f39ce562d660c5065
DIFF: 
https://github.com/llvm/llvm-project/commit/f9585141ff3bc78ae7830c9f39ce562d660c5065.diff

LOG: [CIR] Lower calling through a variable (#198672)

We managed to miss a condition when lowering emitCallee, where a
DeclRefExpr referenced a function object. This patch adds that
condition, which will result in these being lowered properly as an
indirect call.

Added: 
    

Modified: 
    clang/lib/CIR/CodeGen/CIRGenExpr.cpp
    clang/test/CIR/CodeGen/call.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 43f68e0bc6172..6a01513b3e25f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -2360,8 +2360,8 @@ CIRGenCallee CIRGenFunction::emitCallee(const clang::Expr 
*e) {
            "unexpected implicit cast on function pointers");
   } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {
     // Resolve direct calls.
-    const auto *funcDecl = cast<FunctionDecl>(declRef->getDecl());
-    return emitDirectCallee(funcDecl);
+    if (const auto *funcDecl = dyn_cast<FunctionDecl>(declRef->getDecl()))
+      return emitDirectCallee(funcDecl);
   } else if (auto me = dyn_cast<MemberExpr>(e)) {
     if (const auto *fd = dyn_cast<FunctionDecl>(me->getMemberDecl())) {
       emitIgnoredExpr(me->getBase());

diff  --git a/clang/test/CIR/CodeGen/call.cpp b/clang/test/CIR/CodeGen/call.cpp
index 70d45b9099d87..28b0479321131 100644
--- a/clang/test/CIR/CodeGen/call.cpp
+++ b/clang/test/CIR/CodeGen/call.cpp
@@ -130,4 +130,25 @@ void f16() {
 // LLVM-NEXT:    %{{.+}} = call{{.*}} i32 @_Z3f15v()
 // LLVM:       }
 
+template<typename Func>
+inline decltype(auto) TakesFunc(const Func &f) {
+  return f();
+}
+
+int Passed();
+
+void use_TakesFunc() {
+  TakesFunc(Passed);
+}
+
+// CIR-LABEL: _Z9TakesFuncIFivEEDcRKT_
+// CIR-NEXT: %[[FUNC_ALLOCA:.*]] = cir.alloca !cir.ptr<!cir.func<() -> 
!s32i>>, !cir.ptr<!cir.ptr<!cir.func<() -> !s32i>>>, ["f", init, const]
+// CIR: %[[FUNC_LOAD:.*]] = cir.load %[[FUNC_ALLOCA]] : 
!cir.ptr<!cir.ptr<!cir.func<() -> !s32i>>>, !cir.ptr<!cir.func<() -> !s32i>>
+// CIR-NEXT: %[[CALL:.*]] = cir.call %[[FUNC_LOAD]]() : (!cir.ptr<!cir.func<() 
-> !s32i>>) -> (!s32i {llvm.noundef})
+
+// LLVM-LABEL: _Z9TakesFuncIFivEEDcRKT_
+// LLVM-NEXT: %[[FUNC_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[FUNC_LOAD:.*]] = load ptr, ptr %[[FUNC_ALLOCA]]
+// LLVM-NEXT: %[[CALL:.*]] = call noundef i32 %[[FUNC_LOAD]]()
+
 // LLVM: attributes #[[LLVM_ATTR_0]] = { nounwind }


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

Reply via email to