diff options
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 131 |
1 files changed, 2 insertions, 129 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d49fc0b0315..f6218cddfb5 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1628,125 +1628,6 @@ CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const { TheDataLayout.getTypeStoreSizeInBits(Ty)); } -llvm::Constant * -CodeGenModule::MaybeEmitGlobalStdInitializerListInitializer(const VarDecl *D, - const Expr *rawInit) { - ArrayRef<ExprWithCleanups::CleanupObject> cleanups; - if (const ExprWithCleanups *withCleanups = - dyn_cast<ExprWithCleanups>(rawInit)) { - cleanups = withCleanups->getObjects(); - rawInit = withCleanups->getSubExpr(); - } - - const InitListExpr *init = dyn_cast<InitListExpr>(rawInit); - if (!init || !init->initializesStdInitializerList() || - init->getNumInits() == 0) - return 0; - - ASTContext &ctx = getContext(); - unsigned numInits = init->getNumInits(); - // FIXME: This check is here because we would otherwise silently miscompile - // nested global std::initializer_lists. Better would be to have a real - // implementation. - for (unsigned i = 0; i < numInits; ++i) { - const InitListExpr *inner = dyn_cast<InitListExpr>(init->getInit(i)); - if (inner && inner->initializesStdInitializerList()) { - ErrorUnsupported(inner, "nested global std::initializer_list"); - return 0; - } - } - - // Synthesize a fake VarDecl for the array and initialize that. - QualType elementType = init->getInit(0)->getType(); - llvm::APInt numElements(ctx.getTypeSize(ctx.getSizeType()), numInits); - QualType arrayType = ctx.getConstantArrayType(elementType, numElements, - ArrayType::Normal, 0); - - IdentifierInfo *name = &ctx.Idents.get(D->getNameAsString() + "__initlist"); - TypeSourceInfo *sourceInfo = ctx.getTrivialTypeSourceInfo( - arrayType, D->getLocation()); - VarDecl *backingArray = VarDecl::Create(ctx, const_cast<DeclContext*>( - D->getDeclContext()), - D->getLocStart(), D->getLocation(), - name, arrayType, sourceInfo, - SC_Static); - backingArray->setTSCSpec(D->getTSCSpec()); - - // Now clone the InitListExpr to initialize the array instead. - // Incredible hack: we want to use the existing InitListExpr here, so we need - // to tell it that it no longer initializes a std::initializer_list. - ArrayRef<Expr*> Inits(const_cast<InitListExpr*>(init)->getInits(), - init->getNumInits()); - Expr *arrayInit = new (ctx) InitListExpr(ctx, init->getLBraceLoc(), Inits, - init->getRBraceLoc()); - arrayInit->setType(arrayType); - - if (!cleanups.empty()) - arrayInit = ExprWithCleanups::Create(ctx, arrayInit, cleanups); - - backingArray->setInit(arrayInit); - - // Emit the definition of the array. - EmitGlobalVarDefinition(backingArray); - - // Inspect the initializer list to validate it and determine its type. - // FIXME: doing this every time is probably inefficient; caching would be nice - RecordDecl *record = init->getType()->castAs<RecordType>()->getDecl(); - RecordDecl::field_iterator field = record->field_begin(); - if (field == record->field_end()) { - ErrorUnsupported(D, "weird std::initializer_list"); - return 0; - } - QualType elementPtr = ctx.getPointerType(elementType.withConst()); - // Start pointer. - if (!ctx.hasSameType(field->getType(), elementPtr)) { - ErrorUnsupported(D, "weird std::initializer_list"); - return 0; - } - ++field; - if (field == record->field_end()) { - ErrorUnsupported(D, "weird std::initializer_list"); - return 0; - } - bool isStartEnd = false; - if (ctx.hasSameType(field->getType(), elementPtr)) { - // End pointer. - isStartEnd = true; - } else if(!ctx.hasSameType(field->getType(), ctx.getSizeType())) { - ErrorUnsupported(D, "weird std::initializer_list"); - return 0; - } - - // Now build an APValue representing the std::initializer_list. - APValue initListValue(APValue::UninitStruct(), 0, 2); - APValue &startField = initListValue.getStructField(0); - APValue::LValuePathEntry startOffsetPathEntry; - startOffsetPathEntry.ArrayIndex = 0; - startField = APValue(APValue::LValueBase(backingArray), - CharUnits::fromQuantity(0), - llvm::makeArrayRef(startOffsetPathEntry), - /*IsOnePastTheEnd=*/false, 0); - - if (isStartEnd) { - APValue &endField = initListValue.getStructField(1); - APValue::LValuePathEntry endOffsetPathEntry; - endOffsetPathEntry.ArrayIndex = numInits; - endField = APValue(APValue::LValueBase(backingArray), - ctx.getTypeSizeInChars(elementType) * numInits, - llvm::makeArrayRef(endOffsetPathEntry), - /*IsOnePastTheEnd=*/true, 0); - } else { - APValue &sizeField = initListValue.getStructField(1); - sizeField = APValue(llvm::APSInt(numElements)); - } - - // Emit the constant for the initializer_list. - llvm::Constant *llvmInit = - EmitConstantValueForMemory(initListValue, D->getType()); - assert(llvmInit && "failed to initialize as constant"); - return llvmInit; -} - unsigned CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D, unsigned AddrSpace) { if (LangOpts.CUDA && CodeGenOpts.CUDAIsDevice) { @@ -1817,18 +1698,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type"); Init = EmitNullConstant(D->getType()); } else { - // If this is a std::initializer_list, emit the special initializer. - Init = MaybeEmitGlobalStdInitializerListInitializer(D, InitExpr); - // An empty init list will perform zero-initialization, which happens - // to be exactly what we want. - // FIXME: It does so in a global constructor, which is *not* what we - // want. + initializedGlobalDecl = GlobalDecl(D); + Init = EmitConstantInit(*InitDecl); if (!Init) { - initializedGlobalDecl = GlobalDecl(D); - Init = EmitConstantInit(*InitDecl); - } - if (!Init) { QualType T = InitExpr->getType(); if (D->getType()->isReferenceType()) T = D->getType(); |