diff options
| author | Mital Ashok <mital@mitalashok.co.uk> | 2024-06-20 18:44:06 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-20 19:44:06 +0200 |
| commit | 482c41e992c1edf8833a4577b56ff9dda49fbc83 (patch) | |
| tree | 6a606c6bb325ce7e825bdc50a07ce6e734badb7a /clang/lib/CodeGen/CGExprAgg.cpp | |
| parent | 6cea40400df542a1a4a6d35b45cbe3367f2c32b7 (diff) | |
| download | llvm-482c41e992c1edf8833a4577b56ff9dda49fbc83.zip llvm-482c41e992c1edf8833a4577b56ff9dda49fbc83.tar.gz llvm-482c41e992c1edf8833a4577b56ff9dda49fbc83.tar.bz2 | |
[Clang] [Sema] Diagnose unknown std::initializer_list layout in SemaInit (#95580)
This checks if the layout of `std::initializer_list` is something Clang
can handle much earlier and deduplicates the checks in
CodeGen/CGExprAgg.cpp and AST/ExprConstant.cpp
Also now diagnose `union initializer_list` (Fixes #95495), bit-field for
the size (Fixes a crash that would happen during codegen if it were
unnamed), base classes (that wouldn't be initialized) and polymorphic
classes (whose vtable pointer wouldn't be initialized).
Diffstat (limited to 'clang/lib/CodeGen/CGExprAgg.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 44 |
1 files changed, 18 insertions, 26 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 0c87558..c3c10e7 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -426,53 +426,45 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); assert(ArrayType && "std::initializer_list constructed from non-array"); - // FIXME: Perform the checks on the field types in SemaInit. RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl(); RecordDecl::field_iterator Field = Record->field_begin(); - if (Field == Record->field_end()) { - CGF.ErrorUnsupported(E, "weird std::initializer_list"); - return; - } + assert(Field != Record->field_end() && + Ctx.hasSameType(Field->getType()->getPointeeType(), + ArrayType->getElementType()) && + "Expected std::initializer_list first field to be const E *"); // Start pointer. - if (!Field->getType()->isPointerType() || - !Ctx.hasSameType(Field->getType()->getPointeeType(), - ArrayType->getElementType())) { - CGF.ErrorUnsupported(E, "weird std::initializer_list"); - return; - } - AggValueSlot Dest = EnsureSlot(E->getType()); LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType()); LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field); llvm::Value *ArrayStart = ArrayPtr.emitRawPointer(CGF); CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start); ++Field; - - if (Field == Record->field_end()) { - CGF.ErrorUnsupported(E, "weird std::initializer_list"); - return; - } + assert(Field != Record->field_end() && + "Expected std::initializer_list to have two fields"); llvm::Value *Size = Builder.getInt(ArrayType->getSize()); LValue EndOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *Field); - if (Field->getType()->isPointerType() && - Ctx.hasSameType(Field->getType()->getPointeeType(), - ArrayType->getElementType())) { + if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { + // Length. + CGF.EmitStoreThroughLValue(RValue::get(Size), EndOrLength); + + } else { // End pointer. + assert(Field->getType()->isPointerType() && + Ctx.hasSameType(Field->getType()->getPointeeType(), + ArrayType->getElementType()) && + "Expected std::initializer_list second field to be const E *"); llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0); llvm::Value *IdxEnd[] = { Zero, Size }; llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP( ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxEnd, "arrayend"); CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); - } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { - // Length. - CGF.EmitStoreThroughLValue(RValue::get(Size), EndOrLength); - } else { - CGF.ErrorUnsupported(E, "weird std::initializer_list"); - return; } + + assert(++Field == Record->field_end() && + "Expected std::initializer_list to only have two fields"); } /// Determine if E is a trivial array filler, that is, one that is |
