Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

#include "Address.h"
#include "CIRGenCstEmitter.h"
#include "CIRGenFunction.h"
#include "CIRGenModule.h"
#include "CIRGenOpenMPRuntime.h"
Expand Down Expand Up @@ -705,7 +706,17 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
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<mlir::TypedAttr>(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());
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<mlir::TypedAttr>(c);
if (!typedC)
llvm_unreachable("this should never be untyped at this point");
Expand Down
73 changes: 73 additions & 0 deletions clang/test/CIR/CodeGen/source-loc-expr.cpp
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member

Choose a reason for hiding this comment

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

Please add LLVM and OGCG checks too!


// 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<!s8i>
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<!s8i>
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
}
Loading