https://github.com/SharmaRithik updated 
https://github.com/llvm/llvm-project/pull/207261

>From 2a327307f1d32b905525dd906951c0052b6611a3 Mon Sep 17 00:00:00 2001
From: SharmaRithik <[email protected]>
Date: Wed, 1 Jul 2026 23:56:31 +0000
Subject: [PATCH 1/2] [CIR] Add support for AST call expressions on cir.call

Before this change the AST node of a call was thrown away right after
CIRGen. Passes that want to know what the source code called had nothing
to look at. The ClangIR incubator fixes this by keeping a link to the
call expression as an attribute on the call op.

This patch adds that attribute. CIRGen now keeps the call expression that
each cir.call came from, for calls that appear in the source code. Calls
that the compiler makes on its own have no call expression, so they are
skipped. These include constructors, thunks, and the CUDA device stub
launcher. The attribute works the same way as the existing ASTVarDeclAttr.
It is optional and stays hidden in the normal printed IR, so the output
does not change from before. It shows up only in the generic op form,
which is what the tests check.

The ASTCallExprInterface has no methods yet. They will come later with the
pass that uses them, the IdiomRecognizer pass.
---
 clang/include/clang/CIR/Dialect/IR/CIRAttrs.td    |  4 ++++
 clang/include/clang/CIR/Dialect/IR/CIRDialect.td  |  1 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td      |  3 ++-
 .../clang/CIR/Interfaces/ASTAttrInterfaces.h      |  1 +
 .../clang/CIR/Interfaces/ASTAttrInterfaces.td     |  4 ++++
 clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp            |  2 ++
 clang/lib/CIR/CodeGen/CIRGenCall.cpp              |  9 ++++++++-
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp              |  2 +-
 clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp           |  4 ++--
 clang/lib/CIR/CodeGen/CIRGenFunction.h            |  3 ++-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp           |  3 ++-
 clang/test/CIR/CodeGen/call-ast-attr.c            | 13 +++++++++++++
 clang/test/CIR/CodeGen/call-ast-attr.cpp          | 15 +++++++++++++++
 13 files changed, 57 insertions(+), 7 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/call-ast-attr.c
 create mode 100644 clang/test/CIR/CodeGen/call-ast-attr.cpp

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index ec99899355b17..cf00f9022c952 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1684,6 +1684,10 @@ def CIR_ASTVarDeclAttr : CIR_AST<"VarDecl", "var.decl", [
   ASTVarDeclInterface
 ]>;
 
+def CIR_ASTCallExprAttr : CIR_AST<"CallExpr", "call.expr", [
+  ASTCallExprInterface
+]>;
+
 
//===----------------------------------------------------------------------===//
 // AnnotationAttr
 
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index c20af04f97a1a..7700ba4aec693 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -37,6 +37,7 @@ def CIR_Dialect : Dialect {
     static llvm::StringRef getSourceLanguageAttrName() { return "cir.lang"; }
     static llvm::StringRef getTripleAttrName() { return "cir.triple"; }
     static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; }
+    static llvm::StringRef getAstAttrName() { return "ast"; }
     static llvm::StringRef getCalleeAttrName() { return "callee"; }
     static llvm::StringRef getNoThrowAttrName() { return "nothrow"; }
     static llvm::StringRef getNoReturnAttrName() { return "noreturn"; }
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index e83fb81291007..24e1d0e9dbf3f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4312,7 +4312,8 @@ class CIR_CallOpBase<string mnemonic, list<Trait> 
extra_traits = []>
       UnitAttr:$musttail,
       DefaultValuedAttr<CIR_SideEffect, "SideEffect::All">:$side_effect,
       OptionalAttr<DictArrayAttr>:$arg_attrs,
-      OptionalAttr<DictArrayAttr>:$res_attrs
+      OptionalAttr<DictArrayAttr>:$res_attrs,
+      OptionalAttr<ASTCallExprInterface>:$ast
       );
 }
 
diff --git a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h 
b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h
index 2fb633ee9221a..e886808f8e21a 100644
--- a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h
+++ b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h
@@ -14,6 +14,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
 
 /// Include the generated interface declarations.
 #include "clang/CIR/Interfaces/ASTAttrInterfaces.h.inc"
diff --git a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td 
b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td
index 53909063abbab..5bf778afeb0f8 100644
--- a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td
@@ -34,6 +34,10 @@ let cppNamespace = "::cir" in {
       }]>
     ];
   }
+
+  // Query methods are added together with their consumers in the
+  // IdiomRecognizer pass.
+  def ASTCallExprInterface : AttrInterface<"ASTCallExprInterface"> {}
 } // namespace cir
 
 #endif // MLIR_CIR_INTERFACES_ASTATTRINTERFACES_TD
diff --git a/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp
index 65a3c2a7468e9..403deeb849578 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp
@@ -292,6 +292,8 @@ void 
CIRGenNVCUDARuntime::emitDeviceStubBodyNew(CIRGenFunction &cgf,
       cast<cir::FuncType>(launchTy), launchKernelName);
   const CIRGenFunctionInfo &callInfo =
       cgm.getTypes().arrangeFunctionDeclaration(cudaLaunchKernelFD);
+  // The emitted call targets the runtime launcher rather than the function
+  // named in the source call, so no AST call expression is attached.
   cgf.emitCall(callInfo, CIRGenCallee::forDirect(cudaKernelLauncherFn),
                ReturnValueSlot(), launchArgs);
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index c3065c8917924..ece07b79ca158 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -1173,7 +1173,8 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo 
&funcInfo,
                                 ReturnValueSlot returnValue,
                                 const CallArgList &args,
                                 cir::CIRCallOpInterface *callOp,
-                                mlir::Location loc) {
+                                mlir::Location loc,
+                                const clang::CallExpr *astCallExpr) {
   QualType retTy = funcInfo.getReturnType();
   cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
 
@@ -1347,6 +1348,12 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo 
&funcInfo,
       emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
                      cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
 
+  // Attach the AST call expression so later passes can reason about the
+  // original source call.
+  if (astCallExpr)
+    theCall->setAttr(cir::CIRDialect::getAstAttrName(),
+                     cir::ASTCallExprAttr::get(&getMLIRContext(), 
astCallExpr));
+
   if (callOp)
     *callOp = theCall;
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 9b9811f7c4cb1..8ab6e1dbce938 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -2423,7 +2423,7 @@ RValue CIRGenFunction::emitCall(clang::QualType calleeTy,
 
   cir::CIRCallOpInterface callOp;
   RValue callResult = emitCall(funcInfo, callee, returnValue, args, &callOp,
-                               getLoc(e->getExprLoc()));
+                               getLoc(e->getExprLoc()), e);
 
   assert(!cir::MissingFeatures::generateDebugInfo());
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index df60005d77259..17cbb1d483a6e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -121,7 +121,7 @@ CIRGenFunction::emitCXXMemberPointerCallExpr(const 
CXXMemberCallExpr *ce,
   assert(!cir::MissingFeatures::opCallMustTail());
   return emitCall(cgm.getTypes().arrangeCXXMethodCall(argsList, fpt, required,
                                                       /*PrefixSize=*/0),
-                  callee, returnValue, argsList, nullptr, loc);
+                  callee, returnValue, argsList, nullptr, loc, ce);
 }
 
 RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
@@ -323,7 +323,7 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorCall(
   assert((ce || currSrcLoc) && "expected source location");
   mlir::Location loc = ce ? getLoc(ce->getExprLoc()) : *currSrcLoc;
   assert(!cir::MissingFeatures::opCallMustTail());
-  return emitCall(fnInfo, callee, returnValue, args, nullptr, loc);
+  return emitCall(fnInfo, callee, returnValue, args, nullptr, loc, ce);
 }
 
 static void emitNullBaseClassInitialization(CIRGenFunction &cgf,
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 322355fde3957..a23763990c162 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1737,7 +1737,8 @@ class CIRGenFunction : public CIRGenTypeCache {
   RValue emitCall(const CIRGenFunctionInfo &funcInfo,
                   const CIRGenCallee &callee, ReturnValueSlot returnValue,
                   const CallArgList &args, cir::CIRCallOpInterface *callOp,
-                  mlir::Location loc);
+                  mlir::Location loc,
+                  const clang::CallExpr *astCallExpr = nullptr);
   RValue emitCall(const CIRGenFunctionInfo &funcInfo,
                   const CIRGenCallee &callee, ReturnValueSlot returnValue,
                   const CallArgList &args,
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 67cc5e09f26d0..71dda584e9fcc 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1228,7 +1228,8 @@ printCallCommon(mlir::Operation *op, 
mlir::FlatSymbolRefAttr calleeSym,
       CIRDialect::getSideEffectAttrName(),
       CIRDialect::getOperandSegmentSizesAttrName(),
       llvm::StringRef("res_attrs"),
-      llvm::StringRef("arg_attrs")};
+      llvm::StringRef("arg_attrs"),
+      CIRDialect::getAstAttrName()};
   printer.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
   printer << " : ";
   if (calleeSym || !argAttrs) {
diff --git a/clang/test/CIR/CodeGen/call-ast-attr.c 
b/clang/test/CIR/CodeGen/call-ast-attr.c
new file mode 100644
index 0000000000000..4037b86f0b566
--- /dev/null
+++ b/clang/test/CIR/CodeGen/call-ast-attr.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir 
-mlir-print-op-generic %s -o - | FileCheck %s --check-prefix=GENERIC
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
- | FileCheck %s --check-prefix=DEFAULT
+
+void callee(void);
+
+void caller(void) { callee(); }
+
+// Calls carry the AST call expression, visible in the generic form.
+// GENERIC: "cir.call"(){{.*}}ast = #cir.call.expr.ast
+
+// The attribute is elided from the pretty form.
+// DEFAULT: cir.call @callee()
+// DEFAULT-NOT: #cir.call.expr.ast
diff --git a/clang/test/CIR/CodeGen/call-ast-attr.cpp 
b/clang/test/CIR/CodeGen/call-ast-attr.cpp
new file mode 100644
index 0000000000000..402c7c1fff689
--- /dev/null
+++ b/clang/test/CIR/CodeGen/call-ast-attr.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-cir -mmlir -mlir-print-op-generic %s -o - | FileCheck %s
+
+struct S {
+  void method();
+};
+
+// Member calls carry the AST call expression as well.
+void member_call(S &s) { s.method(); }
+// CHECK: "cir.call"
+// CHECK-SAME: ast = #cir.call.expr.ast
+
+// Calls through pointers to member functions carry it too.
+void member_ptr_call(S &s, void (S::*fn)()) { (s.*fn)(); }
+// CHECK: "cir.call"
+// CHECK-SAME: ast = #cir.call.expr.ast

>From 52017132c9e5446285f83d1c105d37c86e0fbf7b Mon Sep 17 00:00:00 2001
From: SharmaRithik <[email protected]>
Date: Fri, 3 Jul 2026 00:10:55 +0000
Subject: [PATCH 2/2] [CIR] Record the source level identity of functions on
 cir.func

CIRGen throws the AST away once it finishes, so passes cannot tell what
the source code calls, and the mangled callee symbol would need a
demangler to read.

The IdiomRecognizer pass from the ClangIR incubator needs three facts
about a call. The plain callee name, whether the callee lives in the
std namespace, and whether it is an instance method. Those recognize
calls like std find as well as the begin and end calls used for
iterator raising. Everything else, like argument counts and types,
comes from the operations, and C library functions like strlen are
matched through their symbol, since C names have no mangling.

This patch provides those three facts as a cir.func_info attribute on
cir.func, set when the function is created, following the
CXXSpecialMemberAttr pattern. A pass answers its questions about a call
by looking up the callee function, the same way LoweringPrepare reads
the special member attribute today. Only functions in the std namespace
carry the attribute for now. It is plain data with a textual form, so
it survives a round trip through a CIR file, and existing test output
does not change. The IdiomRecognizer and LibOpt passes arrive in follow
up PRs.
---
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  | 46 +++++++++++++++++--
 .../clang/CIR/Dialect/IR/CIRDialect.td        |  1 -
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  4 +-
 .../clang/CIR/Interfaces/ASTAttrInterfaces.h  |  1 -
 .../clang/CIR/Interfaces/ASTAttrInterfaces.td |  4 --
 clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp        |  2 -
 clang/lib/CIR/CodeGen/CIRGenCall.cpp          |  9 +---
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp          |  2 +-
 clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp       |  4 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.h        |  3 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        | 32 +++++++++++++
 clang/lib/CIR/CodeGen/CIRGenModule.h          |  4 ++
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 26 ++++++++++-
 clang/test/CIR/CodeGen/call-ast-attr.c        | 13 ------
 clang/test/CIR/CodeGen/call-ast-attr.cpp      | 15 ------
 clang/test/CIR/CodeGen/func-info-attr.c       | 10 ++++
 clang/test/CIR/CodeGen/func-info-attr.cpp     | 45 ++++++++++++++++++
 clang/test/CIR/IR/func-info-attr.cir          | 11 +++++
 18 files changed, 175 insertions(+), 57 deletions(-)
 delete mode 100644 clang/test/CIR/CodeGen/call-ast-attr.c
 delete mode 100644 clang/test/CIR/CodeGen/call-ast-attr.cpp
 create mode 100644 clang/test/CIR/CodeGen/func-info-attr.c
 create mode 100644 clang/test/CIR/CodeGen/func-info-attr.cpp
 create mode 100644 clang/test/CIR/IR/func-info-attr.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index cf00f9022c952..2a67053ca3a8c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1298,6 +1298,48 @@ def CIR_CXXSpecialMemberAttr : AnyAttrOf<[
   CIR_CXXAssignAttr
 ]>;
 
+//===----------------------------------------------------------------------===//
+// FuncInfoAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_FuncInfoAttr : CIR_Attr<"FuncInfo", "func_info"> {
+  let summary = "Holds the source level identity of a function";
+  let description = [{
+    Carries facts about the source declaration a function was emitted from,
+    precomputed during CIRGen while the AST is available. Passes that want
+    to reason about what the source calls read this attribute instead of
+    the AST.
+
+    The `name` parameter holds the plain function name as written in the
+    source, without mangling, qualification, or template arguments.
+    Functions without a plain identifier, for example overloaded operators
+    and constructors, carry no attribute, and neither do static member
+    functions, so a free function and a static member with the same name
+    stay apart. The `in_std_namespace` parameter is true when the function
+    is declared directly in the `std` namespace, looking through inline
+    namespaces. For a member function the enclosing record decides. The
+    `instance_method` parameter is true for a member function that is not
+    static.
+
+    Example:
+    ```
+    #cir.func_info<name = "find", in_std_namespace = true>
+    ```
+  }];
+
+  let parameters = (ins
+    "mlir::StringAttr":$name,
+    DefaultValuedParameter<"bool", "false">:$in_std_namespace,
+    DefaultValuedParameter<"bool", "false">:$instance_method
+  );
+
+  let assemblyFormat = [{
+    `<` struct($name, $in_std_namespace, $instance_method) `>`
+  }];
+
+  let canHaveIllegalCXXABIType = 0;
+}
+
 
//===----------------------------------------------------------------------===//
 // BitfieldInfoAttr
 
//===----------------------------------------------------------------------===//
@@ -1684,10 +1726,6 @@ def CIR_ASTVarDeclAttr : CIR_AST<"VarDecl", "var.decl", [
   ASTVarDeclInterface
 ]>;
 
-def CIR_ASTCallExprAttr : CIR_AST<"CallExpr", "call.expr", [
-  ASTCallExprInterface
-]>;
-
 
//===----------------------------------------------------------------------===//
 // AnnotationAttr
 
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 7700ba4aec693..c20af04f97a1a 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -37,7 +37,6 @@ def CIR_Dialect : Dialect {
     static llvm::StringRef getSourceLanguageAttrName() { return "cir.lang"; }
     static llvm::StringRef getTripleAttrName() { return "cir.triple"; }
     static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; }
-    static llvm::StringRef getAstAttrName() { return "ast"; }
     static llvm::StringRef getCalleeAttrName() { return "callee"; }
     static llvm::StringRef getNoThrowAttrName() { return "nothrow"; }
     static llvm::StringRef getNoReturnAttrName() { return "noreturn"; }
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 24e1d0e9dbf3f..6d6b46b45b8be 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4025,6 +4025,7 @@ def CIR_FuncOp : CIR_Op<"func", [
     CIR_OptionalPriorityAttr:$global_ctor_priority,
     CIR_OptionalPriorityAttr:$global_dtor_priority,
     OptionalAttr<CIR_CXXSpecialMemberAttr>:$cxx_special_member,
+    OptionalAttr<CIR_FuncInfoAttr>:$func_info,
     OptionalAttr<CIR_AnnotationArrayAttr>:$annotations
   );
 
@@ -4312,8 +4313,7 @@ class CIR_CallOpBase<string mnemonic, list<Trait> 
extra_traits = []>
       UnitAttr:$musttail,
       DefaultValuedAttr<CIR_SideEffect, "SideEffect::All">:$side_effect,
       OptionalAttr<DictArrayAttr>:$arg_attrs,
-      OptionalAttr<DictArrayAttr>:$res_attrs,
-      OptionalAttr<ASTCallExprInterface>:$ast
+      OptionalAttr<DictArrayAttr>:$res_attrs
       );
 }
 
diff --git a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h 
b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h
index e886808f8e21a..2fb633ee9221a 100644
--- a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h
+++ b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h
@@ -14,7 +14,6 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
 
 /// Include the generated interface declarations.
 #include "clang/CIR/Interfaces/ASTAttrInterfaces.h.inc"
diff --git a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td 
b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td
index 5bf778afeb0f8..53909063abbab 100644
--- a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td
@@ -34,10 +34,6 @@ let cppNamespace = "::cir" in {
       }]>
     ];
   }
-
-  // Query methods are added together with their consumers in the
-  // IdiomRecognizer pass.
-  def ASTCallExprInterface : AttrInterface<"ASTCallExprInterface"> {}
 } // namespace cir
 
 #endif // MLIR_CIR_INTERFACES_ASTATTRINTERFACES_TD
diff --git a/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp
index 403deeb849578..65a3c2a7468e9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp
@@ -292,8 +292,6 @@ void 
CIRGenNVCUDARuntime::emitDeviceStubBodyNew(CIRGenFunction &cgf,
       cast<cir::FuncType>(launchTy), launchKernelName);
   const CIRGenFunctionInfo &callInfo =
       cgm.getTypes().arrangeFunctionDeclaration(cudaLaunchKernelFD);
-  // The emitted call targets the runtime launcher rather than the function
-  // named in the source call, so no AST call expression is attached.
   cgf.emitCall(callInfo, CIRGenCallee::forDirect(cudaKernelLauncherFn),
                ReturnValueSlot(), launchArgs);
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index ece07b79ca158..c3065c8917924 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -1173,8 +1173,7 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo 
&funcInfo,
                                 ReturnValueSlot returnValue,
                                 const CallArgList &args,
                                 cir::CIRCallOpInterface *callOp,
-                                mlir::Location loc,
-                                const clang::CallExpr *astCallExpr) {
+                                mlir::Location loc) {
   QualType retTy = funcInfo.getReturnType();
   cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
 
@@ -1348,12 +1347,6 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo 
&funcInfo,
       emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
                      cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
 
-  // Attach the AST call expression so later passes can reason about the
-  // original source call.
-  if (astCallExpr)
-    theCall->setAttr(cir::CIRDialect::getAstAttrName(),
-                     cir::ASTCallExprAttr::get(&getMLIRContext(), 
astCallExpr));
-
   if (callOp)
     *callOp = theCall;
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 8ab6e1dbce938..9b9811f7c4cb1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -2423,7 +2423,7 @@ RValue CIRGenFunction::emitCall(clang::QualType calleeTy,
 
   cir::CIRCallOpInterface callOp;
   RValue callResult = emitCall(funcInfo, callee, returnValue, args, &callOp,
-                               getLoc(e->getExprLoc()), e);
+                               getLoc(e->getExprLoc()));
 
   assert(!cir::MissingFeatures::generateDebugInfo());
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index 17cbb1d483a6e..df60005d77259 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -121,7 +121,7 @@ CIRGenFunction::emitCXXMemberPointerCallExpr(const 
CXXMemberCallExpr *ce,
   assert(!cir::MissingFeatures::opCallMustTail());
   return emitCall(cgm.getTypes().arrangeCXXMethodCall(argsList, fpt, required,
                                                       /*PrefixSize=*/0),
-                  callee, returnValue, argsList, nullptr, loc, ce);
+                  callee, returnValue, argsList, nullptr, loc);
 }
 
 RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
@@ -323,7 +323,7 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorCall(
   assert((ce || currSrcLoc) && "expected source location");
   mlir::Location loc = ce ? getLoc(ce->getExprLoc()) : *currSrcLoc;
   assert(!cir::MissingFeatures::opCallMustTail());
-  return emitCall(fnInfo, callee, returnValue, args, nullptr, loc, ce);
+  return emitCall(fnInfo, callee, returnValue, args, nullptr, loc);
 }
 
 static void emitNullBaseClassInitialization(CIRGenFunction &cgf,
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index a23763990c162..322355fde3957 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1737,8 +1737,7 @@ class CIRGenFunction : public CIRGenTypeCache {
   RValue emitCall(const CIRGenFunctionInfo &funcInfo,
                   const CIRGenCallee &callee, ReturnValueSlot returnValue,
                   const CallArgList &args, cir::CIRCallOpInterface *callOp,
-                  mlir::Location loc,
-                  const clang::CallExpr *astCallExpr = nullptr);
+                  mlir::Location loc);
   RValue emitCall(const CIRGenFunctionInfo &funcInfo,
                   const CIRGenCallee &callee, ReturnValueSlot returnValue,
                   const CallArgList &args,
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 7a05aed4c33e0..5e0ad33173468 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -3446,6 +3446,9 @@ CIRGenModule::createCIRFunction(mlir::Location loc, 
StringRef name,
     // Mark C++ special member functions (Constructor, Destructor etc.)
     setCXXSpecialMemberAttr(func, funcDecl);
 
+    // Record the source level identity of the function.
+    setFuncInfoAttr(func, funcDecl);
+
     if (!cgf)
       theModule.push_back(func);
 
@@ -3522,6 +3525,35 @@ void CIRGenModule::setCXXSpecialMemberAttr(
   }
 }
 
+void CIRGenModule::setFuncInfoAttr(cir::FuncOp funcOp,
+                                   const clang::FunctionDecl *funcDecl) {
+  // Functions without a plain identifier, for example overloaded operators
+  // and constructors, carry no information, since no pass can match a
+  // function it cannot name.
+  if (!funcDecl || !funcDecl->getIdentifier())
+    return;
+
+  // A member function lives inside its record, so the record decides
+  // whether the function belongs to the std namespace. Static member
+  // functions carry no attribute, so that a static member like
+  // char_traits::find can never be mistaken for the free std::find.
+  const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
+  if (method && method->isStatic())
+    return;
+  bool inStdNamespace = method ? method->getParent()->isInStdNamespace()
+                               : funcDecl->isInStdNamespace();
+
+  // Only functions in the std namespace carry the attribute for now. Those
+  // are the ones upcoming passes look for, and plain C library functions
+  // can be matched through their symbol, since C names have no mangling.
+  if (!inStdNamespace)
+    return;
+
+  funcOp.setFuncInfoAttr(cir::FuncInfoAttr::get(
+      &getMLIRContext(), builder.getStringAttr(funcDecl->getName()),
+      inStdNamespace, method && method->isInstance()));
+}
+
 static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
                                        cir::FuncOp funcOp, StringRef name) {
   // In Windows Itanium environments, try to mark runtime functions
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h 
b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 144f8c7b9f3e7..8d5f955cbb261 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -802,6 +802,10 @@ class CIRGenModule : public CIRGenTypeCache {
   void setCXXSpecialMemberAttr(cir::FuncOp funcOp,
                                const clang::FunctionDecl *funcDecl);
 
+  /// Record the source level identity of the function (plain name, std
+  /// namespace membership) so passes can reason about it without the AST.
+  void setFuncInfoAttr(cir::FuncOp funcOp, const clang::FunctionDecl 
*funcDecl);
+
   cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name,
                                     mlir::NamedAttrList extraAttrs = {},
                                     bool isLocal = false,
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 71dda584e9fcc..4ee19634f5822 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1228,8 +1228,7 @@ printCallCommon(mlir::Operation *op, 
mlir::FlatSymbolRefAttr calleeSym,
       CIRDialect::getSideEffectAttrName(),
       CIRDialect::getOperandSegmentSizesAttrName(),
       llvm::StringRef("res_attrs"),
-      llvm::StringRef("arg_attrs"),
-      CIRDialect::getAstAttrName()};
+      llvm::StringRef("arg_attrs")};
   printer.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
   printer << " : ";
   if (calleeSym || !argAttrs) {
@@ -2560,6 +2559,23 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, 
OperationState &state) {
       return failure();
   }
 
+  // Parse FuncInfo attribute
+  if (parser.parseOptionalKeyword("func_info").succeeded()) {
+    if (parser.parseLess().failed())
+      return failure();
+
+    mlir::Attribute attr;
+    if (parser.parseAttribute(attr).failed())
+      return failure();
+    if (!mlir::isa<cir::FuncInfoAttr>(attr))
+      return parser.emitError(parser.getCurrentLocation(),
+                              "expected a function information attribute");
+    state.addAttribute(getFuncInfoAttrName(state.name), attr);
+
+    if (parser.parseGreater().failed())
+      return failure();
+  }
+
   if (parseGlobalDtorCtor("global_ctor", [&](std::optional<int> priority) {
         mlir::IntegerAttr globalCtorPriorityAttr =
             builder.getI32IntegerAttr(priority.value_or(65535));
@@ -2757,6 +2773,12 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
     p << '>';
   }
 
+  if (cir::FuncInfoAttr funcInfo = getFuncInfoAttr()) {
+    p << " func_info<";
+    p.printAttribute(funcInfo);
+    p << '>';
+  }
+
   if (auto globalCtorPriority = getGlobalCtorPriority()) {
     p << " global_ctor";
     if (globalCtorPriority.value() != 65535)
diff --git a/clang/test/CIR/CodeGen/call-ast-attr.c 
b/clang/test/CIR/CodeGen/call-ast-attr.c
deleted file mode 100644
index 4037b86f0b566..0000000000000
--- a/clang/test/CIR/CodeGen/call-ast-attr.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir 
-mlir-print-op-generic %s -o - | FileCheck %s --check-prefix=GENERIC
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
- | FileCheck %s --check-prefix=DEFAULT
-
-void callee(void);
-
-void caller(void) { callee(); }
-
-// Calls carry the AST call expression, visible in the generic form.
-// GENERIC: "cir.call"(){{.*}}ast = #cir.call.expr.ast
-
-// The attribute is elided from the pretty form.
-// DEFAULT: cir.call @callee()
-// DEFAULT-NOT: #cir.call.expr.ast
diff --git a/clang/test/CIR/CodeGen/call-ast-attr.cpp 
b/clang/test/CIR/CodeGen/call-ast-attr.cpp
deleted file mode 100644
index 402c7c1fff689..0000000000000
--- a/clang/test/CIR/CodeGen/call-ast-attr.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-cir -mmlir -mlir-print-op-generic %s -o - | FileCheck %s
-
-struct S {
-  void method();
-};
-
-// Member calls carry the AST call expression as well.
-void member_call(S &s) { s.method(); }
-// CHECK: "cir.call"
-// CHECK-SAME: ast = #cir.call.expr.ast
-
-// Calls through pointers to member functions carry it too.
-void member_ptr_call(S &s, void (S::*fn)()) { (s.*fn)(); }
-// CHECK: "cir.call"
-// CHECK-SAME: ast = #cir.call.expr.ast
diff --git a/clang/test/CIR/CodeGen/func-info-attr.c 
b/clang/test/CIR/CodeGen/func-info-attr.c
new file mode 100644
index 0000000000000..41b7e0f846086
--- /dev/null
+++ b/clang/test/CIR/CodeGen/func-info-attr.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
- | FileCheck %s
+
+void callee(void);
+
+void caller(void) { callee(); }
+
+// Plain C functions carry no identity attribute. Their symbol already is
+// the plain name, since C names have no mangling.
+// CHECK: cir.func{{.*}} @caller
+// CHECK-NOT: func_info
diff --git a/clang/test/CIR/CodeGen/func-info-attr.cpp 
b/clang/test/CIR/CodeGen/func-info-attr.cpp
new file mode 100644
index 0000000000000..736f980789b0a
--- /dev/null
+++ b/clang/test/CIR/CodeGen/func-info-attr.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-cir %s -o %t.cir
+// RUN: FileCheck %s --input-file=%t.cir
+// RUN: FileCheck %s --input-file=%t.cir --check-prefix=NEG
+
+namespace std {
+int *find(int *first, int *last, int value);
+inline namespace __1 {
+void sort(int *first, int *last);
+}
+struct container {
+  int *begin();
+};
+struct traits {
+  static int *locate(int *first);
+};
+}
+
+int *std_call(int *first, int *last) { return std::find(first, last, 42); }
+// Functions declared in the std namespace carry their source identity.
+// CHECK-DAG: cir.func{{.*}} @_ZSt4find{{.*}} func_info<#cir.func_info<name = 
"find", in_std_namespace = true>>
+
+void inline_ns_call(int *first, int *last) { std::sort(first, last); }
+// Inline namespaces, like the one in libc++, are looked through.
+// CHECK-DAG: cir.func{{.*}} @_ZNSt3__14sort{{.*}} 
func_info<#cir.func_info<name = "sort", in_std_namespace = true>>
+
+int *member_call(std::container &c) { return c.begin(); }
+// Member functions of std records are marked as instance methods.
+// CHECK-DAG: cir.func{{.*}} @_ZNSt9container5begin{{.*}} 
func_info<#cir.func_info<name = "begin", in_std_namespace = true, 
instance_method = true>>
+
+struct S {
+  void method();
+  void operator()();
+};
+
+void plain_calls(S &s) {
+  s.method();
+  s();
+}
+int *static_member_call(int *first) { return std::traits::locate(first); }
+// Functions outside the std namespace carry nothing, and neither do
+// functions without a plain name, such as operators, nor static member
+// functions, even inside std.
+// NEG-NOT: name = "method"
+// NEG-NOT: name = "operator
+// NEG-NOT: name = "locate"
diff --git a/clang/test/CIR/IR/func-info-attr.cir 
b/clang/test/CIR/IR/func-info-attr.cir
new file mode 100644
index 0000000000000..902616014bd9b
--- /dev/null
+++ b/clang/test/CIR/IR/func-info-attr.cir
@@ -0,0 +1,11 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+module {
+
+cir.func private @_ZSt4findv() func_info<#cir.func_info<name = "find", 
in_std_namespace = true>>
+// CHECK: cir.func private @_ZSt4findv() func_info<#cir.func_info<name = 
"find", in_std_namespace = true>>
+
+cir.func private @_ZNSt9container5beginEv() func_info<#cir.func_info<name = 
"begin", in_std_namespace = true, instance_method = true>>
+// CHECK: cir.func private @_ZNSt9container5beginEv() 
func_info<#cir.func_info<name = "begin", in_std_namespace = true, 
instance_method = true>>
+
+}

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

Reply via email to