diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-14 00:03:17 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-14 00:03:17 +0000 |
commit | 993e3aa6b96adce7b48000b9ba4ff27266c87104 (patch) | |
tree | ed30c61c2b9049285621eba3e33ac172ac5b787e /lib/CodeGen | |
parent | 6503e97e0f2d8032e9daeb4c8cfef00c409bd9f3 (diff) |
Remove custom handling of array copies in lambda by-value array capture and
copy constructors of classes with array members, instead using
ArrayInitLoopExpr to represent the initialization loop.
This exposed a bug in the static analyzer where it was unable to differentiate
between zero-initialized and unknown array values, which has also been fixed
here.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289618 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 172 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 37 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 3 |
5 files changed, 29 insertions, 190 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 709c4afbc2..05d0567395 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -562,140 +562,6 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, isBaseVirtual); } -/// Initialize a member of aggregate type using the given expression -/// as an initializer. -/// -/// The member may be an array. If so: -/// - the destination l-value will be a pointer of the *base* element type, -/// - ArrayIndexVar will be a pointer to a variable containing the current -/// index within the destination array, and -/// - ArrayIndexes will be an array of index variables, one for each level -/// of array nesting, which will need to be updated as appropriate for the -/// array structure. -/// -/// On an array, this function will invoke itself recursively. Each time, -/// it drills into one nesting level of the member type and sets up a -/// loop updating the appropriate array index variable. -static void EmitAggMemberInitializer(CodeGenFunction &CGF, - LValue LHS, - Expr *Init, - Address ArrayIndexVar, - QualType T, - ArrayRef<VarDecl *> ArrayIndexes, - unsigned Index) { - assert(ArrayIndexVar.isValid() == (ArrayIndexes.size() != 0)); - - if (Index == ArrayIndexes.size()) { - LValue LV = LHS; - - Optional<CodeGenFunction::RunCleanupsScope> Scope; - - if (ArrayIndexVar.isValid()) { - // When we're processing an array, the temporaries from each - // element's construction are destroyed immediately. - Scope.emplace(CGF); - - // If we have an array index variable, load it and use it as an offset. - // Then, increment the value. - llvm::Value *Dest = LHS.getPointer(); - llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar); - Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress"); - llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1); - Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc"); - CGF.Builder.CreateStore(Next, ArrayIndexVar); - - // Update the LValue. - CharUnits EltSize = CGF.getContext().getTypeSizeInChars(T); - CharUnits Align = LV.getAlignment().alignmentOfArrayElement(EltSize); - LV.setAddress(Address(Dest, Align)); - - // Enter a partial-array EH cleanup to destroy previous members - // of the array if this initialization throws. - if (CGF.CGM.getLangOpts().Exceptions) { - if (auto DtorKind = T.isDestructedType()) { - if (CGF.needsEHCleanup(DtorKind)) { - CGF.pushRegularPartialArrayCleanup(LHS.getPointer(), - LV.getPointer(), T, - LV.getAlignment(), - CGF.getDestroyer(DtorKind)); - } - } - } - } - - switch (CGF.getEvaluationKind(T)) { - case TEK_Scalar: - CGF.EmitScalarInit(Init, /*decl*/ nullptr, LV, false); - break; - case TEK_Complex: - CGF.EmitComplexExprIntoLValue(Init, LV, /*isInit*/ true); - break; - case TEK_Aggregate: { - AggValueSlot Slot = - AggValueSlot::forLValue(LV, - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased); - - CGF.EmitAggExpr(Init, Slot); - break; - } - } - - return; - } - - const ConstantArrayType *Array = CGF.getContext().getAsConstantArrayType(T); - assert(Array && "Array initialization without the array type?"); - Address IndexVar = CGF.GetAddrOfLocalVar(ArrayIndexes[Index]); - - // Initialize this index variable to zero. - llvm::Value* Zero - = llvm::Constant::getNullValue(IndexVar.getElementType()); - CGF.Builder.CreateStore(Zero, IndexVar); - - // Start the loop with a block that tests the condition. - llvm::BasicBlock *CondBlock = CGF.createBasicBlock("for.cond"); - llvm::BasicBlock *AfterFor = CGF.createBasicBlock("for.end"); - - CGF.EmitBlock(CondBlock); - - llvm::BasicBlock *ForBody = CGF.createBasicBlock("for.body"); - // Generate: if (loop-index < number-of-elements) fall to the loop body, - // otherwise, go to the block after the for-loop. - uint64_t NumElements = Array->getSize().getZExtValue(); - llvm::Value *Counter = CGF.Builder.CreateLoad(IndexVar); - llvm::Value *NumElementsPtr = - llvm::ConstantInt::get(Counter->getType(), NumElements); - llvm::Value *IsLess = CGF.Builder.CreateICmpULT(Counter, NumElementsPtr, - "isless"); - - // If the condition is true, execute the body. - CGF.Builder.CreateCondBr(IsLess, ForBody, AfterFor); - - CGF.EmitBlock(ForBody); - llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc"); - - // Inside the loop body recurse to emit the inner loop or, eventually, the - // constructor call. - EmitAggMemberInitializer(CGF, LHS, Init, ArrayIndexVar, - Array->getElementType(), ArrayIndexes, Index + 1); - - CGF.EmitBlock(ContinueBlock); - - // Emit the increment of the loop counter. - llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); - Counter = CGF.Builder.CreateLoad(IndexVar); - NextVal = CGF.Builder.CreateAdd(Counter, NextVal, "inc"); - CGF.Builder.CreateStore(NextVal, IndexVar); - - // Finally, branch back up to the condition for the next iteration. - CGF.EmitBranch(CondBlock); - - // Emit the fall-through block. - CGF.EmitBlock(AfterFor, true); -} - static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) { auto *CD = dyn_cast<CXXConstructorDecl>(D); if (!(CD && CD->isCopyOrMoveConstructor()) && @@ -779,14 +645,11 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, } } - ArrayRef<VarDecl *> ArrayIndexes; - if (MemberInit->getNumArrayIndices()) - ArrayIndexes = MemberInit->getArrayIndices(); - CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes); + CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit()); } void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS, - Expr *Init, ArrayRef<VarDecl *> ArrayIndexes) { + Expr *Init) { QualType FieldType = Field->getType(); switch (getEvaluationKind(FieldType)) { case TEK_Scalar: @@ -801,30 +664,13 @@ void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS, EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true); break; case TEK_Aggregate: { - Address ArrayIndexVar = Address::invalid(); - if (ArrayIndexes.size()) { - // The LHS is a pointer to the first object we'll be constructing, as - // a flat array. - QualType BaseElementTy = getContext().getBaseElementType(FieldType); - llvm::Type *BasePtr = ConvertType(BaseElementTy); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - Address BaseAddrPtr = Builder.CreateBitCast(LHS.getAddress(), BasePtr); - LHS = MakeAddrLValue(BaseAddrPtr, BaseElementTy); - - // Create an array index that will be used to walk over all of the - // objects we're constructing. - ArrayIndexVar = CreateMemTemp(getContext().getSizeType(), "object.index"); - llvm::Value *Zero = - llvm::Constant::getNullValue(ArrayIndexVar.getElementType()); - Builder.CreateStore(Zero, ArrayIndexVar); - - // Emit the block variables for the array indices, if any. - for (unsigned I = 0, N = ArrayIndexes.size(); I != N; ++I) - EmitAutoVarDecl(*ArrayIndexes[I]); - } - - EmitAggMemberInitializer(*this, LHS, Init, ArrayIndexVar, FieldType, - ArrayIndexes, 0); + AggValueSlot Slot = + AggValueSlot::forLValue(LHS, + AggValueSlot::IsDestructed, + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased); + EmitAggExpr(Init, Slot); + break; } } diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index d756eca64f..9ead6b86b0 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -1328,27 +1328,12 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getPointer(), indices, "arrayinit.begin"); - QualType elementType = E->getSubExpr()->getType(); + QualType elementType = + CGF.getContext().getAsArrayType(E->getType())->getElementType(); CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); CharUnits elementAlign = destPtr.getAlignment().alignmentOfArrayElement(elementSize); - // Prepare for a cleanup. - QualType::DestructionKind dtorKind = elementType.isDestructedType(); - Address endOfInit = Address::invalid(); - EHScopeStack::stable_iterator cleanup; - llvm::Instruction *cleanupDominator = nullptr; - if (CGF.needsEHCleanup(dtorKind)) { - endOfInit = CGF.CreateTempAlloca(begin->getType(), CGF.getPointerAlign(), - "arrayinit.endOfInit"); - CGF.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType, - elementAlign, - CGF.getDestroyer(dtorKind)); - cleanup = CGF.EHStack.stable_begin(); - } else { - dtorKind = QualType::DK_none; - } - llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body"); @@ -1359,11 +1344,22 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { index->addIncoming(zero, entryBB); llvm::Value *element = Builder.CreateInBoundsGEP(begin, index); - // Tell the EH cleanup that we finished with the last element. - if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit); + // Prepare for a cleanup. + QualType::DestructionKind dtorKind = elementType.isDestructedType(); + EHScopeStack::stable_iterator cleanup; + if (CGF.needsEHCleanup(dtorKind)) { + CGF.pushRegularPartialArrayCleanup( + begin, element, elementType, elementAlign, CGF.getDestroyer(dtorKind)); + cleanup = CGF.EHStack.stable_begin(); + } else { + dtorKind = QualType::DK_none; + } // Emit the actual filler expression. { + // Temporaries created in an array initialization loop are destroyed + // at the end of each iteration. + CodeGenFunction::RunCleanupsScope CleanupsScope(CGF); CodeGenFunction::ArrayInitLoopExprScope Scope(CGF, index); LValue elementLV = CGF.MakeAddrLValue(Address(element, elementAlign), elementType); @@ -1385,7 +1381,8 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { CGF.EmitBlock(endBB); // Leave the partial-array cleanup if we entered one. - if (dtorKind) CGF.DeactivateCleanupBlock(cleanup, cleanupDominator); + if (dtorKind) + CGF.DeactivateCleanupBlock(cleanup, index); } void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) { diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index ab2468ef61..71c8fb8b7a 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -2140,10 +2140,7 @@ void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) { auto VAT = CurField->getCapturedVLAType(); EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); } else { - ArrayRef<VarDecl *> ArrayIndexes; - if (CurField->getType()->isArrayType()) - ArrayIndexes = E->getCaptureInitIndexVars(i); - EmitInitializerForField(*CurField, LV, *i, ArrayIndexes); + EmitInitializerForField(*CurField, LV, *i); } } } diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index ba0064ff5c..e4b158178b 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -2206,7 +2206,7 @@ LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) { auto VAT = CurField->getCapturedVLAType(); EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); } else { - EmitInitializerForField(*CurField, LV, *I, None); + EmitInitializerForField(*CurField, LV, *I); } } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index eddaf65bf8..bc4efd3e9c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1601,8 +1601,7 @@ public: void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type, FunctionArgList &Args); - void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init, - ArrayRef<VarDecl *> ArrayIndexes); + void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init); /// Struct with all informations about dynamic [sub]class needed to set vptr. struct VPtr { |