From 7c2bc83d67022a6509ec62a6d5e7f40ec649d9b6 Mon Sep 17 00:00:00 2001 From: Nathan Lanza Date: Mon, 17 Nov 2025 21:55:35 -0800 Subject: [PATCH] Update [ghstack-poisoned] --- clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 13 +++- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 5 +- clang/test/CIR/CodeGen/source-loc-expr.cpp | 73 ++++++++++++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 clang/test/CIR/CodeGen/source-loc-expr.cpp diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index b6b114f0e4b9..dd621a279efd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "Address.h" +#include "CIRGenCstEmitter.h" #include "CIRGenFunction.h" #include "CIRGenModule.h" #include "CIRGenOpenMPRuntime.h" @@ -705,7 +706,17 @@ class ScalarExprEmitter : public StmtVisitor { mlir::Value VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E) { return emitLoadOfLValue(E); } - mlir::Value VisitSourceLocExpr(SourceLocExpr *E) { llvm_unreachable("NYI"); } + mlir::Value VisitSourceLocExpr(SourceLocExpr *E) { + auto &Ctx = CGF.getContext(); + APValue Evaluated = + E->EvaluateInContext(Ctx, CGF.CurSourceLocExprScope.getDefaultExpr()); + auto C = ConstantEmitter(CGF).emitAbstract(E->getLocation(), Evaluated, + E->getType()); + mlir::TypedAttr typedAttr = mlir::dyn_cast_or_null(C); + assert(typedAttr && "SourceLocExpr must produce a typed constant"); + return cir::ConstantOp::create(Builder, CGF.getLoc(E->getExprLoc()), + typedAttr); + } mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { CIRGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE); return Visit(DAE->getExpr()); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 56121a721ae1..6388af3e9cae 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -1855,7 +1855,10 @@ 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(globalVariableName.str()); - auto loc = getLoc(s->getSourceRange()); + // Synthetic string literals (e.g., from SourceLocExpr) may not have valid + // source locations. Use unknown location in those cases. + auto loc = s->getBeginLoc().isValid() ? getLoc(s->getSourceRange()) + : builder.getUnknownLoc(); auto typedC = llvm::dyn_cast(c); if (!typedC) llvm_unreachable("this should never be untyped at this point"); diff --git a/clang/test/CIR/CodeGen/source-loc-expr.cpp b/clang/test/CIR/CodeGen/source-loc-expr.cpp new file mode 100644 index 000000000000..02108cba052f --- /dev/null +++ b/clang/test/CIR/CodeGen/source-loc-expr.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +// Test __builtin_LINE +int test_builtin_LINE() { + // CHECK-LABEL: cir.func {{.*}}@{{.*}}test_builtin_LINE + // CHECK: %{{.*}} = cir.const #cir.int<8> : !u32i + return __builtin_LINE(); +} + +// Test __builtin_FILE +const char* test_builtin_FILE() { + // CHECK-LABEL: cir.func {{.*}}@{{.*}}test_builtin_FILE + // CHECK: %{{.*}} = cir.const #cir.global_view<@".str{{.*}}"> : !cir.ptr + return __builtin_FILE(); +} + +// Test __builtin_FUNCTION +const char* test_builtin_FUNCTION() { + // CHECK-LABEL: cir.func {{.*}}@{{.*}}test_builtin_FUNCTION + // CHECK: %{{.*}} = cir.const #cir.global_view<@".str{{.*}}"> : !cir.ptr + return __builtin_FUNCTION(); +} + +// Test __builtin_COLUMN +int test_builtin_COLUMN() { + // CHECK-LABEL: cir.func {{.*}}@{{.*}}test_builtin_COLUMN + // The column number is the position of '__builtin_COLUMN' + // CHECK: %{{.*}} = cir.const #cir.int<10> : !u32i + return __builtin_COLUMN(); +} + +// Test in global context +#line 100 "test_file.cpp" +int global_line = __builtin_LINE(); +// CHECK: cir.global external @global_line = #cir.int<100> : !s32i + +// Test default argument +int get_line(int l = __builtin_LINE()) { + return l; +} + +void test_default_arg() { + // CHECK-LABEL: cir.func {{.*}}@{{.*}}test_default_arg + // The LINE should be from the call site, not the default argument definition + #line 111 + int x = get_line(); + // CHECK: %{{.*}} = cir.const #cir.int<111> : !u32i + // CHECK: %{{.*}} = cir.call @{{.*}}get_line{{.*}}({{.*}}) : +} + +#line 200 "lambda-test.cpp" +// Test in lambda (this tests that source location correctly captures context) +void test_in_lambda() { + // CHECK-LABEL: cir.func {{.*}}@{{.*}}test_in_lambda + auto lambda = []() { + return __builtin_LINE(); + }; + int x = lambda(); +} + +#line 214 "combined-test.cpp" +// Test multiple builtins in one expression +void test_combined() { + // CHECK-LABEL: cir.func {{.*}}@{{.*}}test_combined + const char* file = __builtin_FILE(); + int line = __builtin_LINE(); + const char* func = __builtin_FUNCTION(); + // All should produce constants + // CHECK: cir.const + // CHECK: cir.const + // CHECK: cir.const +}