From: Ties Stuij Date: Thu, 18 Aug 2022 10:25:07 +0000 (+0100) Subject: [Clang] Propagate const context info when emitting compound literal X-Git-Tag: upstream/17.0.6~36155 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=27cbfa7cc8cdab121842adf4dd31f6811f523928;p=platform%2Fupstream%2Fllvm.git [Clang] Propagate const context info when emitting compound literal This patch fixes a crash when trying to emit a constant compound literal. For C++ Clang evaluates either casts or binary operations at translation time, but doesn't pass on the InConstantContext information that was inferred when parsing the statement. Because of this, strict FP evaluation (-ftrapping-math) which shouldn't be in effect yet, then causes checkFloatingpointResult to return false, which in tryEmitGlobalCompoundLiteral will trigger an assert that the compound literal wasn't constant. The discussion here around 'manifestly constant evaluated contexts' was very helpful to me when trying to understand what LLVM's position is on what evaluation context should be in effect, together with the explanatory text in that patch itself: https://reviews.llvm.org/D87528 Reviewed By: rjmccall, DavidSpickett Differential Revision: https://reviews.llvm.org/D131555 --- diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index f00ada9..db6341e 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -913,17 +913,16 @@ bool ConstStructBuilder::UpdateStruct(ConstantEmitter &Emitter, // ConstExprEmitter //===----------------------------------------------------------------------===// -static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM, - CodeGenFunction *CGF, - const CompoundLiteralExpr *E) { +static ConstantAddress +tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter, + const CompoundLiteralExpr *E) { + CodeGenModule &CGM = emitter.CGM; CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType()); if (llvm::GlobalVariable *Addr = CGM.getAddrOfConstantCompoundLiteralIfEmitted(E)) return ConstantAddress(Addr, Addr->getValueType(), Align); LangAS addressSpace = E->getType().getAddressSpace(); - - ConstantEmitter emitter(CGM, CGF); llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(), addressSpace, E->getType()); if (!C) { @@ -1967,7 +1966,9 @@ ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *E) { ConstantLValue ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { - return tryEmitGlobalCompoundLiteral(CGM, Emitter.CGF, E); + ConstantEmitter CompoundLiteralEmitter(CGM, Emitter.CGF); + CompoundLiteralEmitter.setInConstantContext(Emitter.isInConstantContext()); + return tryEmitGlobalCompoundLiteral(CompoundLiteralEmitter, E); } ConstantLValue @@ -2211,7 +2212,8 @@ void CodeGenModule::setAddrOfConstantCompoundLiteral( ConstantAddress CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) { assert(E->isFileScope() && "not a file-scope compound literal expr"); - return tryEmitGlobalCompoundLiteral(*this, nullptr, E); + ConstantEmitter emitter(*this); + return tryEmitGlobalCompoundLiteral(emitter, E); } llvm::Constant * diff --git a/clang/lib/CodeGen/ConstantEmitter.h b/clang/lib/CodeGen/ConstantEmitter.h index 188b82e..1a7a181 100644 --- a/clang/lib/CodeGen/ConstantEmitter.h +++ b/clang/lib/CodeGen/ConstantEmitter.h @@ -67,6 +67,9 @@ public: return Abstract; } + bool isInConstantContext() const { return InConstantContext; } + void setInConstantContext(bool var) { InConstantContext = var; } + /// Try to emit the initiaizer of the given declaration as an abstract /// constant. If this succeeds, the emission must be finalized. llvm::Constant *tryEmitForInitializer(const VarDecl &D); diff --git a/clang/test/CodeGen/const-init.c b/clang/test/CodeGen/const-init.c index 551c63e..4748d71 100644 --- a/clang/test/CodeGen/const-init.c +++ b/clang/test/CodeGen/const-init.c @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -no-opaque-pointers -triple i386-pc-linux-gnu -ffreestanding -Wno-pointer-to-int-cast -Wno-int-conversion -emit-llvm -o - %s | FileCheck %s +// setting strict FP behaviour in the run line below tests that the compiler +// does the right thing for global compound literals (compoundliteral test) +// RUN: %clang_cc1 -no-opaque-pointers -triple i386-pc-linux-gnu -ffreestanding -Wno-pointer-to-int-cast -Wno-int-conversion -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck %s #include @@ -181,3 +183,10 @@ void g31(void) { #pragma pack() // CHECK: @g31.a = internal global %struct.anon.2 { i16 23122, i32 -12312731, i16 -312 }, align 4 } + +// Clang should evaluate this in constant context, so floating point mode should +// have no effect. +// CHECK: @.compoundliteral = internal global [1 x float] [float 0x3FB99999A0000000], align 4 +struct { const float *floats; } compoundliteral = { + (float[1]) { 0.1, }, +};