stuij created this revision. Herald added a project: All. stuij requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
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 should 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 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D131555 Files: clang/lib/CodeGen/CGExprConstant.cpp clang/lib/CodeGen/ConstantEmitter.h clang/test/CodeGen/const-init.c Index: clang/test/CodeGen/const-init.c =================================================================== --- clang/test/CodeGen/const-init.c +++ clang/test/CodeGen/const-init.c @@ -1,4 +1,4 @@ -// 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 +// 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 <stdint.h> @@ -181,3 +181,7 @@ #pragma pack() // CHECK: @g31.a = internal global %struct.anon.2 { i16 23122, i32 -12312731, i16 -312 }, align 4 } + +struct { const float *floats; } compoundliteral = { + (float[1]) { 0.1, }, +}; Index: clang/lib/CodeGen/ConstantEmitter.h =================================================================== --- clang/lib/CodeGen/ConstantEmitter.h +++ clang/lib/CodeGen/ConstantEmitter.h @@ -67,6 +67,9 @@ 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); Index: clang/lib/CodeGen/CGExprConstant.cpp =================================================================== --- clang/lib/CodeGen/CGExprConstant.cpp +++ clang/lib/CodeGen/CGExprConstant.cpp @@ -913,17 +913,15 @@ // ConstExprEmitter //===----------------------------------------------------------------------===// -static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM, - CodeGenFunction *CGF, +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) { @@ -1970,7 +1968,9 @@ 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 @@ -2214,7 +2214,8 @@ ConstantAddress CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) { assert(E->isFileScope() && "not a file-scope compound literal expr"); - return tryEmitGlobalCompoundLiteral(*this, nullptr, E); + ConstantEmitter emitter(*this, nullptr); + return tryEmitGlobalCompoundLiteral(emitter, E); } llvm::Constant *
Index: clang/test/CodeGen/const-init.c =================================================================== --- clang/test/CodeGen/const-init.c +++ clang/test/CodeGen/const-init.c @@ -1,4 +1,4 @@ -// 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 +// 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 <stdint.h> @@ -181,3 +181,7 @@ #pragma pack() // CHECK: @g31.a = internal global %struct.anon.2 { i16 23122, i32 -12312731, i16 -312 }, align 4 } + +struct { const float *floats; } compoundliteral = { + (float[1]) { 0.1, }, +}; Index: clang/lib/CodeGen/ConstantEmitter.h =================================================================== --- clang/lib/CodeGen/ConstantEmitter.h +++ clang/lib/CodeGen/ConstantEmitter.h @@ -67,6 +67,9 @@ 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); Index: clang/lib/CodeGen/CGExprConstant.cpp =================================================================== --- clang/lib/CodeGen/CGExprConstant.cpp +++ clang/lib/CodeGen/CGExprConstant.cpp @@ -913,17 +913,15 @@ // ConstExprEmitter //===----------------------------------------------------------------------===// -static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM, - CodeGenFunction *CGF, +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) { @@ -1970,7 +1968,9 @@ 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 @@ -2214,7 +2214,8 @@ ConstantAddress CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) { assert(E->isFileScope() && "not a file-scope compound literal expr"); - return tryEmitGlobalCompoundLiteral(*this, nullptr, E); + ConstantEmitter emitter(*this, nullptr); + return tryEmitGlobalCompoundLiteral(emitter, E); } llvm::Constant *
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits