Skip to content

Conversation

@AmrDeveloper
Copy link
Member

Add support for the SourceLocExpr

@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Dec 9, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 9, 2025

@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: Amr Hesham (AmrDeveloper)

Changes

Add support for the SourceLocExpr


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

3 Files Affected:

  • (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+9-2)
  • (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+5-1)
  • (added) clang/test/CIR/CodeGen/source-loc.cpp (+58)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 6820e2a403288..1ed73b6d4b8ef 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "CIRGenConstantEmitter.h"
 #include "CIRGenFunction.h"
 #include "CIRGenValue.h"
 
@@ -813,8 +814,14 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
     return {};
   }
   mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
-    cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: source loc");
-    return {};
+    ASTContext &ctx = cgf.getContext();
+    APValue evaluated =
+        e->EvaluateInContext(ctx, cgf.curSourceLocExprScope.getDefaultExpr());
+    mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
+        e->getExprLoc(), evaluated, e->getType());
+    mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
+    return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
+                                   typedAttr);
   }
   mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
     CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index e1894c040dd53..7c11b2129f2f5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1412,7 +1412,11 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
     // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
     // we need to do that explicitly.
     std::string uniqueName = getUniqueGlobalName(name.str());
-    mlir::Location loc = getLoc(s->getSourceRange());
+    // Synthetic string literals (e.g., from SourceLocExpr) may not have valid
+    // source locations. Use unknown location in those cases.
+    mlir::Location loc = s->getBeginLoc().isValid()
+                             ? getLoc(s->getSourceRange())
+                             : builder.getUnknownLoc();
     auto typedC = llvm::cast<mlir::TypedAttr>(c);
     gv = generateStringLiteral(loc, typedC,
                                cir::GlobalLinkageKind::PrivateLinkage, *this,
diff --git a/clang/test/CIR/CodeGen/source-loc.cpp b/clang/test/CIR/CodeGen/source-loc.cpp
new file mode 100644
index 0000000000000..fc8ab76a9bbb8
--- /dev/null
+++ b/clang/test/CIR/CodeGen/source-loc.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+void line_column() {
+  unsigned int a = __builtin_LINE();
+  unsigned int b = __builtin_COLUMN();
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["b", init]
+// CIR: %[[CONST_9:.*]] = cir.const #cir.int<9> : !u32i
+// CIR: cir.store {{.*}} %[[CONST_9]], %[[A_ADDR]] : !u32i, !cir.ptr<!u32i>
+// CIR: %[[CONST_20:.*]] = cir.const #cir.int<20> : !u32i
+// CIR: cir.store {{.*}} %[[CONST_20]], %[[B_ADDR]] : !u32i, !cir.ptr<!u32i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[B_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: store i32 9, ptr %[[A_ADDR]], align 4
+// LLVM: store i32 20, ptr %[[B_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[B_ADDR:.*]] = alloca i32, align 4
+// OGCG: store i32 9, ptr %[[A_ADDR]], align 4
+// OGCG: store i32 20, ptr %[[B_ADDR]], align 4
+
+void function_file() {
+  const char *a = __builtin_FUNCTION();
+  const char *b = __builtin_FILE();
+  const char *c = __builtin_FILE_NAME();
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>, ["c", init]
+// CIR: %[[FUNC__GV:.*]] = cir.const #cir.global_view<@".str"> : !cir.ptr<!s8i>
+// CIR: cir.store {{.*}} %[[FUNC__GV]], %[[A_ADDR]] : !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>
+// CIR: %[[FILE_PATH_GV:.*]] = cir.const #cir.global_view<@".str.1"> : !cir.ptr<!s8i>
+// CIR: cir.store {{.*}} %[[FILE_PATH_GV]], %[[B_ADDR]] : !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>
+// CIR: %[[FILE_GV:.*]] = cir.const #cir.global_view<@".str.2"> : !cir.ptr<!s8i>
+// CIR: cir.store {{.*}} %[[FILE_GV]], %[[C_ADDR]] : !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: store ptr @.str, ptr %[[A_ADDR]], align 8
+// LLVM: store ptr @.str.1, ptr %[[B_ADDR]], align 8
+// LLVM: store ptr @.str.2, ptr %[[C_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca ptr, align 8
+// OGCG: store ptr @.str, ptr %[[A_ADDR]], align 8
+// OGCG: store ptr @.str.1, ptr %[[B_ADDR]], align 8
+// OGCG: store ptr @.str.2, ptr %[[C_ADDR]], align 8

@AmrDeveloper AmrDeveloper force-pushed the cir_scalar_source_loc_expr branch from c050eeb to 04fcc40 Compare December 9, 2025 19:42
Copy link
Contributor

@andykaylor andykaylor left a comment

Choose a reason for hiding this comment

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

lgtm

@AmrDeveloper AmrDeveloper merged commit 2acefcd into llvm:main Dec 10, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants