diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index b348a385d863..15e81143062c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -411,6 +411,33 @@ LValue CIRGenFunction::buildLValueForFieldInitialization( return makeAddrLValue(V, FieldType, FieldBaseInfo); } +LValue +CIRGenFunction::buildCompoundLiteralLValue(const CompoundLiteralExpr *E) { + if (E->isFileScope()) { + llvm_unreachable("NYI"); + } + + if (E->getType()->isVariablyModifiedType()) { + llvm_unreachable("NYI"); + } + + Address DeclPtr = CreateMemTemp(E->getType(), getLoc(E->getSourceRange()), + ".compoundliteral"); + const Expr *InitExpr = E->getInitializer(); + LValue Result = makeAddrLValue(DeclPtr, E->getType(), AlignmentSource::Decl); + + buildAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(), + /*Init*/ true); + + // Block-scope compound literals are destroyed at the end of the enclosing + // scope in C. + if (!getLangOpts().CPlusPlus) + if (QualType::DestructionKind DtorKind = E->getType().isDestructedType()) + llvm_unreachable("NYI"); + + return Result; +} + // Detect the unusual situation where an inline version is shadowed by a // non-inline version. In that case we should pick the external one // everywhere. That's GCC behavior too. @@ -2241,6 +2268,8 @@ LValue CIRGenFunction::buildLValue(const Expr *E) { return buildStringLiteralLValue(cast(E)); case Expr::MemberExprClass: return buildMemberExpr(cast(E)); + case Expr::CompoundLiteralExprClass: + return buildCompoundLiteralLValue(cast(E)); case Expr::PredefinedExprClass: return buildPredefinedLValue(cast(E)); case Expr::CXXFunctionalCastExprClass: diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 222a7162b3f3..72a8ab60b69b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1529,6 +1529,7 @@ class CIRGenFunction : public CIRGenTypeCache { LValue buildCheckedLValue(const Expr *E, TypeCheckKind TCK); LValue buildMemberExpr(const MemberExpr *E); + LValue buildCompoundLiteralLValue(const CompoundLiteralExpr *E); /// Specifies which type of sanitizer check to apply when handling a /// particular builtin. diff --git a/clang/test/CIR/CodeGen/compound-literal.c b/clang/test/CIR/CodeGen/compound-literal.c index 327774c74f9f..ab493fd87bee 100644 --- a/clang/test/CIR/CodeGen/compound-literal.c +++ b/clang/test/CIR/CodeGen/compound-literal.c @@ -27,3 +27,21 @@ S b = { // LLVM: @.compoundLiteral.1 = internal global [1 x i32] [i32 1] // LLVM: @b = global %struct.S { ptr @.compoundLiteral.1 } + +int foo() { + return (struct { + int i; + }){1} + .i; +} + +// CIR: cir.func no_proto @foo() -> !s32i +// CIR: [[RET_MEM:%.*]] = cir.alloca !s32i, cir.ptr , ["__retval"] {alignment = 4 : i64} +// CIR: [[COMPLITERAL_MEM:%.*]] = cir.alloca !ty_22anon2E122, cir.ptr , [".compoundliteral"] {alignment = 4 : i64} +// CIR: [[FIELD:%.*]] = cir.get_member [[COMPLITERAL_MEM]][0] {name = "i"} : !cir.ptr -> !cir.ptr +// CIR: [[ONE:%.*]] = cir.const(#cir.int<1> : !s32i) : !s32i +// CIR: cir.store [[ONE]], [[FIELD]] : !s32i, cir.ptr +// CIR: [[ONE:%.*]] = cir.const(#cir.int<1> : !s32i) : !s32i +// CIR: cir.store [[ONE]], [[RET_MEM]] : !s32i, cir.ptr +// CIR: [[RET:%.*]] = cir.load [[RET_MEM]] : cir.ptr , !s32i +// CIR: cir.return [[RET]] : !s32i