diff options
Diffstat (limited to 'clang/lib/CodeGen/CGExprConstant.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index ac4b4d1308ab..b83a87443250 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -439,22 +439,33 @@ llvm::Constant *ConstantAggregateBuilder::buildFrom( // Can't emit as an array, carry on to emit as a struct. } + // The size of the constant we plan to generate. This is usually just + // the size of the initialized type, but in AllowOversized mode (i.e. + // flexible array init), it can be larger. CharUnits DesiredSize = Utils.getSize(DesiredTy); + if (Size > DesiredSize) { + assert(AllowOversized && "Elems are oversized"); + DesiredSize = Size; + } + + // The natural alignment of an unpacked LLVM struct with the given elements. CharUnits Align = CharUnits::One(); for (llvm::Constant *C : Elems) Align = std::max(Align, Utils.getAlignment(C)); + + // The natural size of an unpacked LLVM struct with the given elements. CharUnits AlignedSize = Size.alignTo(Align); bool Packed = false; ArrayRef<llvm::Constant*> UnpackedElems = Elems; llvm::SmallVector<llvm::Constant*, 32> UnpackedElemStorage; - if ((DesiredSize < AlignedSize && !AllowOversized) || - DesiredSize.alignTo(Align) != DesiredSize) { - // The natural layout would be the wrong size; force use of a packed layout. + if (DesiredSize < AlignedSize || DesiredSize.alignTo(Align) != DesiredSize) { + // The natural layout would be too big; force use of a packed layout. NaturalLayout = false; Packed = true; } else if (DesiredSize > AlignedSize) { - // The constant would be too small. Add padding to fix it. + // The natural layout would be too small. Add padding to fix it. (This + // is ignored if we choose a packed layout.) UnpackedElemStorage.assign(Elems.begin(), Elems.end()); UnpackedElemStorage.push_back(Utils.getPadding(DesiredSize - Size)); UnpackedElems = UnpackedElemStorage; @@ -482,7 +493,7 @@ llvm::Constant *ConstantAggregateBuilder::buildFrom( // If we're using the packed layout, pad it out to the desired size if // necessary. if (Packed) { - assert((SizeSoFar <= DesiredSize || AllowOversized) && + assert(SizeSoFar <= DesiredSize && "requested size is too small for contents"); if (SizeSoFar < DesiredSize) PackedElems.push_back(Utils.getPadding(DesiredSize - SizeSoFar)); @@ -692,8 +703,8 @@ bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) { !declaresSameEntity(ILE->getInitializedFieldInUnion(), Field)) continue; - // Don't emit anonymous bitfields or zero-sized fields. - if (Field->isUnnamedBitfield() || Field->isZeroSize(CGM.getContext())) + // Don't emit anonymous bitfields. + if (Field->isUnnamedBitfield()) continue; // Get the initializer. A struct can include fields without initializers, @@ -704,6 +715,14 @@ bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) { if (Init && isa<NoInitExpr>(Init)) continue; + // Zero-sized fields are not emitted, but their initializers may still + // prevent emission of this struct as a constant. + if (Field->isZeroSize(CGM.getContext())) { + if (Init->HasSideEffects(CGM.getContext())) + return false; + continue; + } + // When emitting a DesignatedInitUpdateExpr, a nested InitListExpr // represents additional overwriting of our current constant value, and not // a new constant to emit independently. @@ -1092,7 +1111,16 @@ public: destAS, destTy); } - case CK_LValueToRValue: + case CK_LValueToRValue: { + // We don't really support doing lvalue-to-rvalue conversions here; any + // interesting conversions should be done in Evaluate(). But as a + // special case, allow compound literals to support the gcc extension + // allowing "struct x {int x;} x = (struct x) {};". + if (auto *E = dyn_cast<CompoundLiteralExpr>(subExpr->IgnoreParens())) + return Visit(E->getInitializer(), destType); + return nullptr; + } + case CK_AtomicToNonAtomic: case CK_NonAtomicToAtomic: case CK_NoOp: @@ -1909,6 +1937,9 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { if (auto *GD = dyn_cast<MSGuidDecl>(D)) return CGM.GetAddrOfMSGuidDecl(GD); + if (auto *GCD = dyn_cast<UnnamedGlobalConstantDecl>(D)) + return CGM.GetAddrOfUnnamedGlobalConstantDecl(GCD); + if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) return CGM.GetAddrOfTemplateParamObject(TPO); |
