https://github.com/anutosh491 created
https://github.com/llvm/llvm-project/pull/165538
I added some logs to see the difference between C++ mode and C mode and I see
this
In C++ mode
```
clang-repl> struct S1{} s1; s1
[convertExprToValue] original Expr: DeclRefExpr | type: struct S1
[convertExprToValue] Ty: struct S1
[convertExprToValue] DesugaredTy: struct S1
[convertExprToValue] Treating lvalue record as reference (enters block 540)
[convertExprToValue] Ty: struct S1 & (after block 540)
[convertExprToValue] DesugaredTy: struct S1 & (after block 540)
[computeInterfaceKind] Expr class: DeclRefExpr | isLValue: 1
(S1 &) @0x10c9ac058
```
in C mode
```
(base) anutosh491@Anutoshs-MacBook-Air bin % ./clang-repl --Xcc=-xc
--Xcc=-std=c23
clang-repl> struct S1{} s1; s1
[convertExprToValue] original Expr: ImplicitCastExpr | type: struct S1
[convertExprToValue] Ty: struct S1
[convertExprToValue] DesugaredTy: struct S1
[convertExprToValue] Ty: struct S1 (after block 540)
[convertExprToValue] DesugaredTy: struct S1 (after block 540)
[computeInterfaceKind] Expr class: ImplicitCastExpr | isLValue: 0
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH
or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
s0 clang-repl 0x0000000103cca03c
llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 88
1 clang-repl 0x0000000103cca61c
PrintStackTraceSignalHandler(void*) + 28
2 clang-repl 0x0000000103cc7ee8 llvm::sys::RunSignalHandlers() +
152
3 clang-repl 0x0000000103ccbb54 SignalHandler(int, __siginfo*,
void*) + 284
4 libsystem_platform.dylib 0x00000001887f4624 _sigtramp + 56
5 clang-repl 0x00000001079bee18
clang::Sema::CheckArgsForPlaceholders(llvm::MutableArrayRef<clang::Expr*>) + 120
6 clang-repl 0x00000001079bee18
clang::Sema::CheckArgsForPlaceholders(llvm::MutableArrayRef<clang::Expr*>) + 120
7 clang-repl 0x0000000107b823dc
clang::Sema::BuildCXXNew(clang::SourceRange, bool, clang::SourceLocation,
llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::SourceRange,
clang::QualType, clang::TypeSourceInfo*, std::__1::optional<clang::Expr*>,
clang::SourceRange, clang::Expr*) + 5672
8 clang-repl 0x000000010538c560
clang::Interpreter::convertExprToValue(clang::Expr*) + 2580
9 clang-repl 0x0000000105360774
clang::InProcessPrintingASTConsumer::HandleTopLevelDecl(clang::DeclGroupRef) +
252
10 clang-repl 0x000000010536a82c
clang::IncrementalParser::ParseOrWrapTopLevelDecl() + 676
11 clang-repl 0x000000010536b554
clang::IncrementalParser::Parse(llvm::StringRef) + 712
12 clang-repl 0x000000010537e6b4
clang::Interpreter::Parse(llvm::StringRef) + 588
13 clang-repl 0x000000010537d73c
clang::Interpreter::ParseAndExecute(llvm::StringRef, clang::Value*) + 72
14 clang-repl 0x000000010022db38 main + 3660
15 dyld 0x000000018841ab98 start + 6076
```
So basically C mode wasn't entering block 540 as expressions like `s1` (where
`s1` is a struct variable) are wrapped in an `ImplicitCastExpr`, which masks
the underlying `DeclRefExpr` that is actually an `lvalue`.This patch unwraps
the implicit cast with E->IgnoreImpCasts() before checking isLValue(),
restoring correct detection of lvalue structs.
>From 7f5e7ff8d808792a82a094c00b065df5a849a460 Mon Sep 17 00:00:00 2001
From: anutosh491 <[email protected]>
Date: Wed, 29 Oct 2025 15:48:46 +0530
Subject: [PATCH] Fix struct value printing for clang-repl in C mode
---
.../lib/Interpreter/InterpreterValuePrinter.cpp | 4 ++--
clang/test/Interpreter/pretty-print.c | 16 +++++++++-------
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp
b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
index 0ed02f3bfabe8..1e9777f3485c6 100644
--- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp
+++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
@@ -411,7 +411,7 @@ class InterfaceKindVisitor
}
InterfaceKind VisitReferenceType(const ReferenceType *Ty) {
- ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf,
E);
+ ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf,
E->IgnoreImpCasts());
assert(!AddrOfE.isInvalid() && "Can not create unary expression");
Args.push_back(AddrOfE.get());
return InterfaceKind::NoAlloc;
@@ -537,7 +537,7 @@ llvm::Expected<Expr *> Interpreter::convertExprToValue(Expr
*E) {
QualType DesugaredTy = Ty.getDesugaredType(Ctx);
// For lvalue struct, we treat it as a reference.
- if (DesugaredTy->isRecordType() && E->isLValue()) {
+ if (DesugaredTy->isRecordType() && E->IgnoreImpCasts()->isLValue()) {
DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy);
Ty = Ctx.getLValueReferenceType(Ty);
}
diff --git a/clang/test/Interpreter/pretty-print.c
b/clang/test/Interpreter/pretty-print.c
index d0712fb152107..c752b53b5264a 100644
--- a/clang/test/Interpreter/pretty-print.c
+++ b/clang/test/Interpreter/pretty-print.c
@@ -78,14 +78,16 @@ int * null_ptr = (int*)0; null_ptr
union U { int I; float F; } u; u.I = 12; u.I
// CHECK-NEXT: (int) 12
-// TODO: _Bool, _Complex, _Atomic, and _BitInt
-// struct S1{} s1; s1
-// TODO-CHECK-NEXT: (S1 &) @0x{{[0-9a-f]+}}
+struct S1{} s1; s1
+// CHECK-NEXT: (S1 &) @0x{{[0-9a-f]+}}
+
+struct S2 {int d;} E = {22}; E
+// CHECK-NEXT: (struct S2 &) @0x{{[0-9a-f]+}}
-// struct S2 {int d;} E = {22}; E
-// TODO-CHECK-NEXT: (struct S2 &) @0x{{[0-9a-f]+}}
-// E.d
-// TODO-CHECK-NEXT: (int) 22
+E.d
+// CHECK-NEXT: (int) 22
+
+// TODO: _Bool, _Complex, _Atomic, and _BitInt
//
-----------------------------------------------------------------------------
// Tentative definition handling (C99 6.9.2)
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits