diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index b40ca28ceffaae290fa0845264e30e2cc1534513..46434c4c7bb5ee79115fa2d449be5151b2a2a0e9 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1928,8 +1928,7 @@ public: /// B(A& a) : A(a), f(3.14159) { } /// }; /// \endcode -class CXXCtorInitializer final - : private llvm::TrailingObjects<CXXCtorInitializer, VarDecl *> { +class CXXCtorInitializer final { /// \brief Either the base class name/delegating constructor type (stored as /// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field /// (IndirectFieldDecl*) being initialized. @@ -1967,14 +1966,8 @@ class CXXCtorInitializer final unsigned IsWritten : 1; /// If IsWritten is true, then this number keeps track of the textual order - /// of this initializer in the original sources, counting from 0; otherwise, - /// it stores the number of array index variables stored after this object - /// in memory. - unsigned SourceOrderOrNumArrayIndices : 13; - - CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, - SourceLocation MemberLoc, SourceLocation L, Expr *Init, - SourceLocation R, VarDecl **Indices, unsigned NumIndices); + /// of this initializer in the original sources, counting from 0. + unsigned SourceOrder : 13; public: /// \brief Creates a new base-class initializer. @@ -2000,13 +1993,6 @@ public: CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, SourceLocation L, Expr *Init, SourceLocation R); - /// \brief Creates a new member initializer that optionally contains - /// array indices used to describe an elementwise initialization. - static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member, - SourceLocation MemberLoc, SourceLocation L, - Expr *Init, SourceLocation R, - VarDecl **Indices, unsigned NumIndices); - /// \brief Determine whether this initializer is initializing a base class. bool isBaseInitializer() const { return Initializee.is<TypeSourceInfo*>() && !IsDelegating; @@ -2111,7 +2097,7 @@ public: /// \brief Return the source position of the initializer, counting from 0. /// If the initializer was implicit, -1 is returned. int getSourceOrder() const { - return IsWritten ? static_cast<int>(SourceOrderOrNumArrayIndices) : -1; + return IsWritten ? static_cast<int>(SourceOrder) : -1; } /// \brief Set the source order of this initializer. @@ -2121,49 +2107,22 @@ public: /// /// This assumes that the initializer was written in the source code, and /// ensures that isWritten() returns true. - void setSourceOrder(int pos) { + void setSourceOrder(int Pos) { assert(!IsWritten && + "setSourceOrder() used on implicit initializer"); + assert(SourceOrder == 0 && "calling twice setSourceOrder() on the same initializer"); - assert(SourceOrderOrNumArrayIndices == 0 && - "setSourceOrder() used when there are implicit array indices"); - assert(pos >= 0 && + assert(Pos >= 0 && "setSourceOrder() used to make an initializer implicit"); IsWritten = true; - SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos); + SourceOrder = static_cast<unsigned>(Pos); } SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - /// \brief Determine the number of implicit array indices used while - /// described an array member initialization. - unsigned getNumArrayIndices() const { - return IsWritten ? 0 : SourceOrderOrNumArrayIndices; - } - - /// \brief Retrieve a particular array index variable used to - /// describe an array member initialization. - VarDecl *getArrayIndex(unsigned I) { - assert(I < getNumArrayIndices() && "Out of bounds member array index"); - return getTrailingObjects<VarDecl *>()[I]; - } - const VarDecl *getArrayIndex(unsigned I) const { - assert(I < getNumArrayIndices() && "Out of bounds member array index"); - return getTrailingObjects<VarDecl *>()[I]; - } - void setArrayIndex(unsigned I, VarDecl *Index) { - assert(I < getNumArrayIndices() && "Out of bounds member array index"); - getTrailingObjects<VarDecl *>()[I] = Index; - } - ArrayRef<VarDecl *> getArrayIndices() { - return llvm::makeArrayRef(getTrailingObjects<VarDecl *>(), - getNumArrayIndices()); - } - /// \brief Get the initializer. Expr *getInit() const { return static_cast<Expr*>(Init); } - - friend TrailingObjects; }; /// Description of a constructor that was inherited from a base class. diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 4778b6cc69678dce6e5589996ab8e20f29656f51..37e59771a723d2ac9666d3167d0f7859c10c42fa 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1513,9 +1513,8 @@ public: /// C++1y introduces a new form of "capture" called an init-capture that /// includes an initializing expression (rather than capturing a variable), /// and which can never occur implicitly. -class LambdaExpr final - : public Expr, - private llvm::TrailingObjects<LambdaExpr, Stmt *, unsigned, VarDecl *> { +class LambdaExpr final : public Expr, + private llvm::TrailingObjects<LambdaExpr, Stmt *> { /// \brief The source range that covers the lambda introducer ([...]). SourceRange IntroducerRange; @@ -1536,10 +1535,6 @@ class LambdaExpr final /// \brief Whether this lambda had the result type explicitly specified. unsigned ExplicitResultType : 1; - /// \brief Whether there are any array index variables stored at the end of - /// this lambda expression. - unsigned HasArrayIndexVars : 1; - /// \brief The location of the closing brace ('}') that completes /// the lambda. /// @@ -1550,28 +1545,19 @@ class LambdaExpr final /// module file just to determine the source range. SourceLocation ClosingBrace; - size_t numTrailingObjects(OverloadToken<Stmt *>) const { - return NumCaptures + 1; - } - - size_t numTrailingObjects(OverloadToken<unsigned>) const { - return HasArrayIndexVars ? NumCaptures + 1 : 0; - } - /// \brief Construct a lambda expression. LambdaExpr(QualType T, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, bool ExplicitParams, bool ExplicitResultType, - ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars, - ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, + ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack); /// \brief Construct an empty lambda expression. - LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars) + LambdaExpr(EmptyShell Empty, unsigned NumCaptures) : Expr(LambdaExprClass, Empty), NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false), - ExplicitResultType(false), HasArrayIndexVars(true) { + ExplicitResultType(false) { getStoredStmts()[NumCaptures] = nullptr; } @@ -1579,21 +1565,6 @@ class LambdaExpr final Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } - /// \brief Retrieve the mapping from captures to the first array index - /// variable. - unsigned *getArrayIndexStarts() { return getTrailingObjects<unsigned>(); } - - const unsigned *getArrayIndexStarts() const { - return getTrailingObjects<unsigned>(); - } - - /// \brief Retrieve the complete set of array-index variables. - VarDecl **getArrayIndexVars() { return getTrailingObjects<VarDecl *>(); } - - VarDecl *const *getArrayIndexVars() const { - return getTrailingObjects<VarDecl *>(); - } - public: /// \brief Construct a new lambda expression. static LambdaExpr * @@ -1601,15 +1572,12 @@ public: LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, - ArrayRef<VarDecl *> ArrayIndexVars, - ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, - bool ContainsUnexpandedParameterPack); + SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack); /// \brief Construct a new lambda expression that will be deserialized from /// an external source. static LambdaExpr *CreateDeserialized(const ASTContext &C, - unsigned NumCaptures, - unsigned NumArrayIndexVars); + unsigned NumCaptures); /// \brief Determine the default capture kind for this lambda. LambdaCaptureDefault getCaptureDefault() const { @@ -1708,14 +1676,6 @@ public: return capture_init_begin() + NumCaptures; } - /// \brief Retrieve the set of index variables used in the capture - /// initializer of an array captured by copy. - /// - /// \param Iter The iterator that points at the capture initializer for - /// which we are extracting the corresponding index variables. - ArrayRef<VarDecl *> - getCaptureInitIndexVars(const_capture_init_iterator Iter) const; - /// \brief Retrieve the source range covering the lambda introducer, /// which contains the explicit capture list surrounded by square /// brackets ([...]). diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 9e79298c3bedcf31e87b5dd2d9366f3f1f4d1ba1..4a7c9f52ed25f381b40ae158fbe36977c1baf108 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -886,16 +886,6 @@ bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( if (Init->isWritten() || getDerived().shouldVisitImplicitCode()) TRY_TO(TraverseStmt(Init->getInit())); - if (getDerived().shouldVisitImplicitCode()) - // The braces for this one-line loop are required for MSVC2013. It - // refuses to compile - // for (int i : int_vec) - // do {} while(false); - // without braces on the for loop. - for (VarDecl *VD : Init->getArrayIndices()) { - TRY_TO(TraverseDecl(VD)); - } - return true; } @@ -2399,7 +2389,12 @@ DEF_TRAVERSE_STMT(ExtVectorElementExpr, {}) DEF_TRAVERSE_STMT(GNUNullExpr, {}) DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {}) DEF_TRAVERSE_STMT(NoInitExpr, {}) -DEF_TRAVERSE_STMT(ArrayInitLoopExpr, {}) +DEF_TRAVERSE_STMT(ArrayInitLoopExpr, { + // FIXME: The source expression of the OVE should be listed as + // a child of the ArrayInitLoopExpr. + if (OpaqueValueExpr *OVE = S->getCommonExpr()) + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(OVE->getSourceExpr()); +}) DEF_TRAVERSE_STMT(ArrayInitIndexExpr, {}) DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {}) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 1a7522db91ad31546e5950e1b904200ab3a4f275..67e96ea828bdf2521250d1b67e715f84b7bcef39 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -274,6 +274,8 @@ namespace clang { Expr *VisitMemberExpr(MemberExpr *E); Expr *VisitCallExpr(CallExpr *E); Expr *VisitInitListExpr(InitListExpr *E); + Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); + Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E); @@ -6564,6 +6566,30 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { return To; } +Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { + QualType ToType = Importer.Import(E->getType()); + if (ToType.isNull()) + return nullptr; + + Expr *ToCommon = Importer.Import(E->getCommonExpr()); + if (!ToCommon && E->getCommonExpr()) + return nullptr; + + Expr *ToSubExpr = Importer.Import(E->getSubExpr()); + if (!ToSubExpr && E->getSubExpr()) + return nullptr; + + return new (Importer.getToContext()) + ArrayInitLoopExpr(ToType, ToCommon, ToSubExpr); +} + +Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { + QualType ToType = Importer.Import(E->getType()); + if (ToType.isNull()) + return nullptr; + return new (Importer.getToContext()) ArrayInitIndexExpr(ToType); +} + Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>( Importer.Import(DIE->getField())); @@ -7054,25 +7080,6 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { return new (ToContext) CXXCtorInitializer(ToContext, ToTInfo, Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc())); - } else if (unsigned NumArrayIndices = From->getNumArrayIndices()) { - FieldDecl *ToField = - llvm::cast_or_null<FieldDecl>(Import(From->getMember())); - if (!ToField && From->getMember()) - return nullptr; - - SmallVector<VarDecl *, 4> ToAIs(NumArrayIndices); - - for (unsigned AII = 0; AII < NumArrayIndices; ++AII) { - VarDecl *ToArrayIndex = - dyn_cast_or_null<VarDecl>(Import(From->getArrayIndex(AII))); - if (!ToArrayIndex && From->getArrayIndex(AII)) - return nullptr; - } - - return CXXCtorInitializer::Create( - ToContext, ToField, Import(From->getMemberLocation()), - Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()), - ToAIs.data(), NumArrayIndices); } else { return nullptr; } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index f1848e8e0927f953d4c826cb179cf3cef765ee48..8563416a480a35f8c2a34d6d0b28add7b6371301 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1739,7 +1739,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation EllipsisLoc) : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } @@ -1750,7 +1750,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } @@ -1761,7 +1761,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } @@ -1771,38 +1771,10 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R) : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(0) + IsWritten(false), SourceOrder(0) { } -CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, - FieldDecl *Member, - SourceLocation MemberLoc, - SourceLocation L, Expr *Init, - SourceLocation R, - VarDecl **Indices, - unsigned NumIndices) - : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) -{ - std::uninitialized_copy(Indices, Indices + NumIndices, - getTrailingObjects<VarDecl *>()); -} - -CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context, - FieldDecl *Member, - SourceLocation MemberLoc, - SourceLocation L, Expr *Init, - SourceLocation R, - VarDecl **Indices, - unsigned NumIndices) { - void *Mem = Context.Allocate(totalSizeToAlloc<VarDecl *>(NumIndices), - alignof(CXXCtorInitializer)); - return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R, - Indices, NumIndices); -} - TypeLoc CXXCtorInitializer::getBaseClassLoc() const { if (isBaseInitializer()) return Initializee.get<TypeSourceInfo*>()->getTypeLoc(); diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 5ad014f3e0bde06a6789a8aa9818383c961770d5..ad510e0070e63f5f26b8a0037fb1a322d4768e9c 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -869,8 +869,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange, SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, - ArrayRef<VarDecl *> ArrayIndexVars, - ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(), @@ -907,17 +905,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange, // Copy the body of the lambda. *Stored++ = getCallOperator()->getBody(); - - // Copy the array index variables, if any. - HasArrayIndexVars = !ArrayIndexVars.empty(); - if (HasArrayIndexVars) { - assert(ArrayIndexStarts.size() == NumCaptures); - memcpy(getArrayIndexVars(), ArrayIndexVars.data(), - sizeof(VarDecl *) * ArrayIndexVars.size()); - memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(), - sizeof(unsigned) * Captures.size()); - getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size(); - } } LambdaExpr *LambdaExpr::Create( @@ -925,31 +912,24 @@ LambdaExpr *LambdaExpr::Create( SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, - ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) { // Determine the type of the expression (i.e., the type of the // function object we're creating). QualType T = Context.getTypeDeclType(Class); - unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>( - Captures.size() + 1, ArrayIndexVars.empty() ? 0 : Captures.size() + 1, - ArrayIndexVars.size()); + unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1); void *Mem = Context.Allocate(Size); - return new (Mem) LambdaExpr(T, IntroducerRange, - CaptureDefault, CaptureDefaultLoc, Captures, - ExplicitParams, ExplicitResultType, - CaptureInits, ArrayIndexVars, ArrayIndexStarts, - ClosingBrace, ContainsUnexpandedParameterPack); + return new (Mem) + LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc, + Captures, ExplicitParams, ExplicitResultType, CaptureInits, + ClosingBrace, ContainsUnexpandedParameterPack); } LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C, - unsigned NumCaptures, - unsigned NumArrayIndexVars) { - unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>( - NumCaptures + 1, NumArrayIndexVars ? NumCaptures + 1 : 0, - NumArrayIndexVars); + unsigned NumCaptures) { + unsigned Size = totalSizeToAlloc<Stmt *>(NumCaptures + 1); void *Mem = C.Allocate(Size); - return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0); + return new (Mem) LambdaExpr(EmptyShell(), NumCaptures); } bool LambdaExpr::isInitCapture(const LambdaCapture *C) const { @@ -995,19 +975,6 @@ LambdaExpr::capture_range LambdaExpr::implicit_captures() const { return capture_range(implicit_capture_begin(), implicit_capture_end()); } -ArrayRef<VarDecl *> -LambdaExpr::getCaptureInitIndexVars(const_capture_init_iterator Iter) const { - assert(HasArrayIndexVars && "No array index-var data?"); - - unsigned Index = Iter - capture_init_begin(); - assert(Index < getLambdaClass()->getLambdaData().NumCaptures && - "Capture index out-of-range"); - VarDecl *const *IndexVars = getArrayIndexVars(); - const unsigned *IndexStarts = getArrayIndexStarts(); - return llvm::makeArrayRef(IndexVars + IndexStarts[Index], - IndexVars + IndexStarts[Index + 1]); -} - CXXRecordDecl *LambdaExpr::getLambdaClass() const { return getType()->getAsCXXRecordDecl(); } diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 709c4afbc2ff60bf2188512b24fbf6d6953df701..05d056739524daee7e0e3795fcf001bb0c4d1ee7 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 d756eca64f1d742ee2b7085cc7d39bd2933d4c53..9ead6b86b0c3e62fab826af80ffaa32fb37b9576 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 ab2468ef61ebf1b18ee83889ee2de39aeebb9291..71c8fb8b7ae358e73e7e529a214a84123529949d 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 ba0064ff5c308e823e91d0875183028e70910592..e4b158178bc69d0522f2430f9696baa7bb351cd2 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 eddaf65bf8895c27a3d469627b2d10be9682d1a6..bc4efd3e9ccbb640d37a931e871370c05724733f 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 { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index fd33b3164b0d003621bacaacb455d63893ce04d5..ba62be2f5ff630b6ae8898191db4a199aab1fc6a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4246,98 +4246,30 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, CtorArg = CastForMoving(SemaRef, CtorArg.get()); } - // When the field we are copying is an array, create index variables for - // each dimension of the array. We use these index variables to subscript - // the source array, and other clients (e.g., CodeGen) will perform the - // necessary iteration with these index variables. - SmallVector<VarDecl *, 4> IndexVariables; - QualType BaseType = Field->getType(); - QualType SizeType = SemaRef.Context.getSizeType(); - bool InitializingArray = false; - while (const ConstantArrayType *Array - = SemaRef.Context.getAsConstantArrayType(BaseType)) { - InitializingArray = true; - // Create the iteration variable for this array index. - IdentifierInfo *IterationVarName = nullptr; - { - SmallString<8> Str; - llvm::raw_svector_ostream OS(Str); - OS << "__i" << IndexVariables.size(); - IterationVarName = &SemaRef.Context.Idents.get(OS.str()); - } - VarDecl *IterationVar - = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc, - IterationVarName, SizeType, - SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc), - SC_None); - IndexVariables.push_back(IterationVar); - - // Create a reference to the iteration variable. - ExprResult IterationVarRef - = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); - assert(!IterationVarRef.isInvalid() && - "Reference to invented variable cannot fail!"); - IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.get()); - assert(!IterationVarRef.isInvalid() && - "Conversion of invented variable cannot fail!"); - - // Subscript the array with this iteration variable. - CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.get(), Loc, - IterationVarRef.get(), - Loc); - if (CtorArg.isInvalid()) - return true; - - BaseType = Array->getElementType(); - } - - // The array subscript expression is an lvalue, which is wrong for moving. - if (Moving && InitializingArray) - CtorArg = CastForMoving(SemaRef, CtorArg.get()); + InitializedEntity Entity = + Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr, + /*Implicit*/ true) + : InitializedEntity::InitializeMember(Field, nullptr, + /*Implicit*/ true); - // Construct the entity that we will be initializing. For an array, this - // will be first element in the array, which may require several levels - // of array-subscript entities. - SmallVector<InitializedEntity, 4> Entities; - Entities.reserve(1 + IndexVariables.size()); - if (Indirect) - Entities.push_back(InitializedEntity::InitializeMember(Indirect)); - else - Entities.push_back(InitializedEntity::InitializeMember(Field)); - for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) - Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context, - 0, - Entities.back())); - // Direct-initialize to use the copy constructor. InitializationKind InitKind = InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation()); Expr *CtorArgE = CtorArg.getAs<Expr>(); - InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind, - CtorArgE); - - ExprResult MemberInit - = InitSeq.Perform(SemaRef, Entities.back(), InitKind, - MultiExprArg(&CtorArgE, 1)); + InitializationSequence InitSeq(SemaRef, Entity, InitKind, CtorArgE); + ExprResult MemberInit = + InitSeq.Perform(SemaRef, Entity, InitKind, MultiExprArg(&CtorArgE, 1)); MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); if (MemberInit.isInvalid()) return true; - if (Indirect) { - assert(IndexVariables.size() == 0 && - "Indirect field improperly initialized"); - CXXMemberInit - = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, - Loc, Loc, - MemberInit.getAs<Expr>(), - Loc); - } else - CXXMemberInit = CXXCtorInitializer::Create(SemaRef.Context, Field, Loc, - Loc, MemberInit.getAs<Expr>(), - Loc, - IndexVariables.data(), - IndexVariables.size()); + if (Indirect) + CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer( + SemaRef.Context, Indirect, Loc, Loc, MemberInit.getAs<Expr>(), Loc); + else + CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer( + SemaRef.Context, Field, Loc, Loc, MemberInit.getAs<Expr>(), Loc); return false; } @@ -4348,9 +4280,11 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, SemaRef.Context.getBaseElementType(Field->getType()); if (FieldBaseElementType->isRecordType()) { - InitializedEntity InitEntity - = Indirect? InitializedEntity::InitializeMember(Indirect) - : InitializedEntity::InitializeMember(Field); + InitializedEntity InitEntity = + Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr, + /*Implicit*/ true) + : InitializedEntity::InitializeMember(Field, nullptr, + /*Implicit*/ true); InitializationKind InitKind = InitializationKind::CreateDefault(Loc); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 34531287884a11b516b8f21e5a322ee518c6740d..291feea780b7a042b3e7847b805a956ffdbadd19 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -5227,8 +5227,9 @@ void InitializationSequence::InitializeFrom(Sema &S, InitializedEntity::InitializeElement(S.Context, 0, Entity); QualType InitEltT = Context.getAsArrayType(Initializer->getType())->getElementType(); - OpaqueValueExpr OVE(SourceLocation(), InitEltT, - Initializer->getValueKind()); + OpaqueValueExpr OVE(Initializer->getExprLoc(), InitEltT, + Initializer->getValueKind(), + Initializer->getObjectKind()); Expr *OVEAsExpr = &OVE; InitializeFrom(S, Element, Kind, OVEAsExpr, TopLevelOfInitList, TreatUnavailableAsInvalid); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 0715650b8a25c5416136a4c3ed816fc1c0f623bd..3bae69164ffd3f549c7a17b9bcfc41dad1cb1457 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1384,10 +1384,7 @@ static void addBlockPointerConversion(Sema &S, } static ExprResult performLambdaVarCaptureInitialization( - Sema &S, LambdaScopeInfo::Capture &Capture, - FieldDecl *Field, - SmallVectorImpl<VarDecl *> &ArrayIndexVars, - SmallVectorImpl<unsigned> &ArrayIndexStarts) { + Sema &S, LambdaScopeInfo::Capture &Capture, FieldDecl *Field) { assert(Capture.isVariableCapture() && "not a variable capture"); auto *Var = Capture.getVariable(); @@ -1411,69 +1408,11 @@ static ExprResult performLambdaVarCaptureInitialization( return ExprError(); Expr *Ref = RefResult.get(); - QualType FieldType = Field->getType(); - - // When the variable has array type, create index variables for each - // dimension of the array. We use these index variables to subscript - // the source array, and other clients (e.g., CodeGen) will perform - // the necessary iteration with these index variables. - // - // FIXME: This is dumb. Add a proper AST representation for array - // copy-construction and use it here. - SmallVector<VarDecl *, 4> IndexVariables; - QualType BaseType = FieldType; - QualType SizeType = S.Context.getSizeType(); - ArrayIndexStarts.push_back(ArrayIndexVars.size()); - while (const ConstantArrayType *Array - = S.Context.getAsConstantArrayType(BaseType)) { - // Create the iteration variable for this array index. - IdentifierInfo *IterationVarName = nullptr; - { - SmallString<8> Str; - llvm::raw_svector_ostream OS(Str); - OS << "__i" << IndexVariables.size(); - IterationVarName = &S.Context.Idents.get(OS.str()); - } - VarDecl *IterationVar = VarDecl::Create( - S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType, - S.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None); - IterationVar->setImplicit(); - IndexVariables.push_back(IterationVar); - ArrayIndexVars.push_back(IterationVar); - - // Create a reference to the iteration variable. - ExprResult IterationVarRef = - S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); - assert(!IterationVarRef.isInvalid() && - "Reference to invented variable cannot fail!"); - IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.get()); - assert(!IterationVarRef.isInvalid() && - "Conversion of invented variable cannot fail!"); - - // Subscript the array with this iteration variable. - ExprResult Subscript = - S.CreateBuiltinArraySubscriptExpr(Ref, Loc, IterationVarRef.get(), Loc); - if (Subscript.isInvalid()) - return ExprError(); - - Ref = Subscript.get(); - BaseType = Array->getElementType(); - } - - // Construct the entity that we will be initializing. For an array, this - // will be first element in the array, which may require several levels - // of array-subscript entities. - SmallVector<InitializedEntity, 4> Entities; - Entities.reserve(1 + IndexVariables.size()); - Entities.push_back(InitializedEntity::InitializeLambdaCapture( - Var->getIdentifier(), FieldType, Loc)); - for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) - Entities.push_back( - InitializedEntity::InitializeElement(S.Context, 0, Entities.back())); - + auto Entity = InitializedEntity::InitializeLambdaCapture( + Var->getIdentifier(), Field->getType(), Loc); InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); - InitializationSequence Init(S, Entities.back(), InitKind, Ref); - return Init.Perform(S, Entities.back(), InitKind, Ref); + InitializationSequence Init(S, Entity, InitKind, Ref); + return Init.Perform(S, Entity, InitKind, Ref); } ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, @@ -1514,8 +1453,6 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, bool ExplicitResultType; CleanupInfo LambdaCleanup; bool ContainsUnexpandedParameterPack; - SmallVector<VarDecl *, 4> ArrayIndexVars; - SmallVector<unsigned, 4> ArrayIndexStarts; { CallOperator = LSI->CallOperator; Class = LSI->Lambda; @@ -1549,14 +1486,12 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, LambdaCapture(From.getLocation(), IsImplicit, From.isCopyCapture() ? LCK_StarThis : LCK_This)); CaptureInits.push_back(From.getInitExpr()); - ArrayIndexStarts.push_back(ArrayIndexVars.size()); continue; } if (From.isVLATypeCapture()) { Captures.push_back( LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType)); CaptureInits.push_back(nullptr); - ArrayIndexStarts.push_back(ArrayIndexVars.size()); continue; } @@ -1566,13 +1501,11 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, Var, From.getEllipsisLoc())); Expr *Init = From.getInitExpr(); if (!Init) { - auto InitResult = performLambdaVarCaptureInitialization( - *this, From, *CurField, ArrayIndexVars, ArrayIndexStarts); + auto InitResult = + performLambdaVarCaptureInitialization(*this, From, *CurField); if (InitResult.isInvalid()) return ExprError(); Init = InitResult.get(); - } else { - ArrayIndexStarts.push_back(ArrayIndexVars.size()); } CaptureInits.push_back(Init); } @@ -1609,8 +1542,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, CaptureDefault, CaptureDefaultLoc, Captures, ExplicitParams, ExplicitResultType, - CaptureInits, ArrayIndexVars, - ArrayIndexStarts, EndLoc, + CaptureInits, EndLoc, ContainsUnexpandedParameterPack); // If the lambda expression's call operator is not explicitly marked constexpr // and we are not in a dependent context, analyze the call operator to infer diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4f12f86257857996ee769494bd9b5eebe29a4aba..f4b7392df260601dcad9a78fc4b42b188f9b9f15 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -8167,49 +8167,29 @@ ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, Expr *Init = ReadExpr(F); SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx); SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); - bool IsWritten = Record[Idx++]; - unsigned SourceOrderOrNumArrayIndices; - SmallVector<VarDecl *, 8> Indices; - if (IsWritten) { - SourceOrderOrNumArrayIndices = Record[Idx++]; - } else { - SourceOrderOrNumArrayIndices = Record[Idx++]; - Indices.reserve(SourceOrderOrNumArrayIndices); - for (unsigned i = 0; i != SourceOrderOrNumArrayIndices; ++i) - Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx)); - } CXXCtorInitializer *BOMInit; - if (Type == CTOR_INITIALIZER_BASE) { + if (Type == CTOR_INITIALIZER_BASE) BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init, RParenLoc, MemberOrEllipsisLoc); - } else if (Type == CTOR_INITIALIZER_DELEGATING) { + else if (Type == CTOR_INITIALIZER_DELEGATING) BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc, Init, RParenLoc); - } else if (IsWritten) { - if (Member) - BOMInit = new (Context) CXXCtorInitializer( - Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc); - else - BOMInit = new (Context) - CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc, - LParenLoc, Init, RParenLoc); - } else { - if (IndirectMember) { - assert(Indices.empty() && "Indirect field improperly initialized"); - BOMInit = new (Context) - CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc, - LParenLoc, Init, RParenLoc); - } else { - BOMInit = CXXCtorInitializer::Create( - Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc, - Indices.data(), Indices.size()); - } + else if (Member) + BOMInit = new (Context) + CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc, LParenLoc, + Init, RParenLoc); + else + BOMInit = new (Context) + CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc, + LParenLoc, Init, RParenLoc); + + if (bool IsWritten = Record[Idx++]) { + unsigned SourceOrder = Record[Idx++]; + BOMInit->setSourceOrder(SourceOrder); } - if (IsWritten) - BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices); CtorInitializers[i] = BOMInit; } diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 461bb9f8d466208262a0957393ef9f20266a0dba..dcadfdcc50374685789a01a27da3d65773670c82 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1287,7 +1287,6 @@ void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) { VisitExpr(E); unsigned NumCaptures = Record[Idx++]; assert(NumCaptures == E->NumCaptures);(void)NumCaptures; - unsigned NumArrayIndexVars = Record[Idx++]; E->IntroducerRange = ReadSourceRange(Record, Idx); E->CaptureDefault = static_cast<LambdaCaptureDefault>(Record[Idx++]); E->CaptureDefaultLoc = ReadSourceLocation(Record, Idx); @@ -1300,17 +1299,6 @@ void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) { CEnd = E->capture_init_end(); C != CEnd; ++C) *C = Reader.ReadSubExpr(); - - // Read array capture index variables. - if (NumArrayIndexVars > 0) { - unsigned *ArrayIndexStarts = E->getArrayIndexStarts(); - for (unsigned I = 0; I != NumCaptures + 1; ++I) - ArrayIndexStarts[I] = Record[Idx++]; - - VarDecl **ArrayIndexVars = E->getArrayIndexVars(); - for (unsigned I = 0; I != NumArrayIndexVars; ++I) - ArrayIndexVars[I] = ReadDeclAs<VarDecl>(Record, Idx); - } } void @@ -3875,9 +3863,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_LAMBDA: { unsigned NumCaptures = Record[ASTStmtReader::NumExprFields]; - unsigned NumArrayIndexVars = Record[ASTStmtReader::NumExprFields + 1]; - S = LambdaExpr::CreateDeserialized(Context, NumCaptures, - NumArrayIndexVars); + S = LambdaExpr::CreateDeserialized(Context, NumCaptures); break; } } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 9c906e46b5819a4dc8b92733c16e14075c1c0119..8b863bcecde10f367b471a96272aee0bacc0ef3f 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -5588,13 +5588,8 @@ EmitCXXCtorInitializers(ASTWriter &W, Writer.AddSourceLocation(Init->getLParenLoc()); Writer.AddSourceLocation(Init->getRParenLoc()); Writer.push_back(Init->isWritten()); - if (Init->isWritten()) { + if (Init->isWritten()) Writer.push_back(Init->getSourceOrder()); - } else { - Writer.push_back(Init->getNumArrayIndices()); - for (auto *VD : Init->getArrayIndices()) - Writer.AddDeclRef(VD); - } } return Writer.Emit(serialization::DECL_CXX_CTOR_INITIALIZERS); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index fbe1d843cd65ed27eca7a119f53c032118b18194..f66cc029f52acc407cbe96ca103e47a194a5e855 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1257,10 +1257,6 @@ void ASTStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) { VisitExpr(E); Record.push_back(E->NumCaptures); - unsigned NumArrayIndexVars = 0; - if (E->HasArrayIndexVars) - NumArrayIndexVars = E->getArrayIndexStarts()[E->NumCaptures]; - Record.push_back(NumArrayIndexVars); Record.AddSourceRange(E->IntroducerRange); Record.push_back(E->CaptureDefault); // FIXME: stable encoding Record.AddSourceLocation(E->CaptureDefaultLoc); @@ -1275,15 +1271,6 @@ void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) { Record.AddStmt(*C); } - // Add array index variables, if any. - if (NumArrayIndexVars) { - Record.append(E->getArrayIndexStarts(), - E->getArrayIndexStarts() + E->NumCaptures + 1); - VarDecl **ArrayIndexVars = E->getArrayIndexVars(); - for (unsigned I = 0; I != NumArrayIndexVars; ++I) - Record.AddDeclRef(ArrayIndexVars[I]); - } - Code = serialization::EXPR_LAMBDA; } diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 93f6939c2e53e06346da521f3a818c41c2d639e4..6ba3379eac88d563e2f4b18ab905082719a96e9b 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -507,7 +507,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init, } SVal InitVal; - if (BMI->getNumArrayIndices() > 0) { + if (Init->getType()->isArrayType()) { // Handle arrays of trivial type. We can represent this with a // primitive load/copy from the base array region. const ArraySubscriptExpr *ASE; diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index a19869d96e3f8688b65207ad951a269633b80508..15ca2c14f9440b6fd13c6a47ab1c0d13b5f6780b 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2073,11 +2073,10 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B, if (Init.getAs<nonloc::LazyCompoundVal>()) return bindAggregate(B, R, Init); - // Remaining case: explicit compound values. - if (Init.isUnknown()) - return setImplicitDefaultValue(B, R, ElementTy); + return bindAggregate(B, R, UnknownVal()); + // Remaining case: explicit compound values. const nonloc::CompoundVal& CV = Init.castAs<nonloc::CompoundVal>(); nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); uint64_t i = 0; diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index fe9a6834f6a047d2fcdb52639486b23f57374c9f..145b7e084b7b8523768b19942ba38a256470be61 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -36,8 +36,11 @@ DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) { if (type->isIntegralOrEnumerationType()) return makeIntVal(0, type); + if (type->isArrayType() || type->isRecordType() || type->isVectorType() || + type->isAnyComplexType()) + return makeCompoundVal(type, BasicVals.getEmptySValList()); + // FIXME: Handle floats. - // FIXME: Handle structs. return UnknownVal(); } diff --git a/test/CXX/special/class.copy/implicit-move-def.cpp b/test/CXX/special/class.copy/implicit-move-def.cpp index f344b0cc6a0f3690a324ca5c24d189671c60eaa9..7a6a1ee984e9222f1f81e4bc1dd2276d48bff802 100644 --- a/test/CXX/special/class.copy/implicit-move-def.cpp +++ b/test/CXX/special/class.copy/implicit-move-def.cpp @@ -110,8 +110,8 @@ void move_VirtualWithEmptyBase(VirtualWithEmptyBase &x, VirtualWithEmptyBase &y) // CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ // CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ // array loop -// CHECK-CTOR: br i1 // CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ +// CHECK-CTOR: br i1 // CHECK-CTOR: define linkonce_odr {{.*}} @_ZN1GC2EOS_ // CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp index c121755f649c64fab05541e5105e92e73d75468f..fe15ccf8fef5d3e66ba21c44548c4a796d65c4f8 100644 --- a/test/CodeGenCXX/constructor-init.cpp +++ b/test/CodeGenCXX/constructor-init.cpp @@ -207,20 +207,17 @@ namespace PR10720 { // CHECK-PR10720-LABEL: define linkonce_odr void @_ZN7PR107205pair2C2ERKS0_ // CHECK-PR10720-NOT: ret - // CHECK-PR10720: load - // CHECK-PR10720: icmp ult - // CHECK-PR10720-NEXT: br i1 // CHECK-PR10720: call void @_ZN7PR107201XC1ERKS0_ - // CHECK-PR10720-NEXT: br label + // CHECK-PR10720: icmp eq + // CHECK-PR10720-NEXT: br i1 // CHECK-PR10720: ret void // CHECK-PR10720-LABEL: define linkonce_odr void @_ZN7PR107205pair2C2EOS0_ // CHECK-PR10720-NOT: ret // CHECK-PR10720: load - // CHECK-PR10720: icmp ult - // CHECK-PR10720-NEXT: br i1 // CHECK-PR10720: call void @_ZN7PR107201XC1EOS0_ - // CHECK-PR10720-NEXT: br label + // CHECK-PR10720: icmp eq + // CHECK-PR10720-NEXT: br i1 // CHECK-PR10720: ret void pair2(pair2&&) = default; diff --git a/test/CodeGenCXX/implicit-copy-constructor.cpp b/test/CodeGenCXX/implicit-copy-constructor.cpp index d0224131c4da0b349c8eac972db3984feb6216a1..3f8665aa3b4d8f34441f27ac37e45760c2a22687 100644 --- a/test/CodeGenCXX/implicit-copy-constructor.cpp +++ b/test/CodeGenCXX/implicit-copy-constructor.cpp @@ -48,12 +48,14 @@ void f(D d) { // CHECK: call void @_ZN1BC2ERS_ // CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 28}} // CHECK: call void @_ZN1BC1ERS_ -// CHECK: br -// CHECK: {{icmp ult.*, 2}} -// CHECK: {{icmp ult.*, 3}} +// CHECK: br label // CHECK: call void @_ZN1AC1Ev // CHECK: call void @_ZN1CC1ERS_1A // CHECK: call void @_ZN1AD1Ev +// CHECK: {{icmp eq.*, 3}} +// CHECK: br i1 +// CHECK: {{icmp eq.*, 2}} +// CHECK: br i1 // CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 300}} // CHECK: ret void diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp index 2006f0f81efe62c9434a32d6fbbbdb856f4fb8df..cefaeb4017b991274e7a0f920f75887d2b906d19 100644 --- a/test/CodeGenCXX/lambda-expressions.cpp +++ b/test/CodeGenCXX/lambda-expressions.cpp @@ -54,12 +54,14 @@ int c(int x) { return [&x]{return x;}(); } // CHECK: ret i32 struct D { D(); D(const D&); int x; }; -int d(int x) { D y[10]; [x,y] { return y[x].x; }(); } +int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-LABEL: define i32 @_Z1di // CHECK: call void @_ZN1DC1Ev -// CHECK: icmp ult i64 %{{.*}}, 10 +// CHECK: br label // CHECK: call void @_ZN1DC1ERKS_ +// CHECK: icmp eq i64 %{{.*}}, 10 +// CHECK: br i1 // CHECK: call i32 @"_ZZ1diENK3$_4clEv" // CHECK-LABEL: define internal i32 @"_ZZ1diENK3$_4clEv" // CHECK: load i32, i32* @@ -67,7 +69,7 @@ int d(int x) { D y[10]; [x,y] { return y[x].x; }(); } // CHECK: ret i32 struct E { E(); E(const E&); ~E(); int x; }; -int e(E a, E b, bool cond) { [a,b,cond](){ return (cond ? a : b).x; }(); } +int e(E a, E b, bool cond) { return [a,b,cond](){ return (cond ? a : b).x; }(); } // CHECK-LABEL: define i32 @_Z1e1ES_b // CHECK: call void @_ZN1EC1ERKS_ // CHECK: invoke void @_ZN1EC1ERKS_ @@ -127,42 +129,66 @@ namespace pr28595 { ~A(); }; + void after_init() noexcept; + // CHECK-LABEL: define void @_ZN7pr285954testEv() void test() { - // CHECK: [[ARRAY:%.*]] = alloca [3 x [5 x [[A:%.*]]]], align 1 - // CHECK: [[DESTIDX:%.*]] = alloca i64, align 8 - // CHECK: [[I0:%.*]] = alloca i64, align 8 - // CHECK: [[I1:%.*]] = alloca i64, align 8 + // CHECK: %[[SRC:.*]] = alloca [3 x [5 x %[[A:.*]]]], align 1 A array[3][5]; - // CHECK: [[DESTBASE:%.*]] = bitcast [3 x [5 x [[A]]]]* {{.*}} to [[A]]* - // CHECK: store i64 0, i64* [[DESTIDX]], align 8 - // CHECK: store i64 0, i64* [[I0]], align 8 + // Skip over the initialization loop. + // CHECK: call {{.*}}after_init + after_init(); + + // CHECK: %[[DST_0:.*]] = getelementptr inbounds [3 x [5 x %[[A]]]], {{.*}}, i64 0, i64 0 // CHECK: br label - // CHECK: icmp ult - // CHECK: store i64 0, i64* [[I1]], align 8 + // CHECK: %[[I:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[I_NEXT:.*]], {{.*}} ] + // CHECK: %[[DST_I:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[DST_0]], i64 %[[I]] + // CHECK: %[[SRC_I:.*]] = getelementptr {{.*}} [3 x [5 x %[[A]]]]* %[[SRC]], i64 0, i64 %[[I]] + // + // CHECK: %[[DST_I_0:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[DST_I]], i64 0, i64 0 // CHECK: br label - // CHECK: icmp ult - // CHECK: [[T0:%.*]] = load i64, i64* [[DESTIDX]], align 8 - // CHECK: [[DEST:%.*]] = getelementptr inbounds [[A]], [[A]]* [[DESTBASE]], i64 [[T0]] + // CHECK: %[[J:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[J_NEXT:.*]], {{.*}} ] + // CHECK: %[[DST_I_J:.*]] = getelementptr {{.*}} %[[A]]* %[[DST_I_0]], i64 %[[J]] + // CHECK: %[[SRC_I_J:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[SRC_I]], i64 0, i64 %[[J]] + // // CHECK: invoke void @_ZN7pr285954TempC1Ev // CHECK: invoke void @_ZN7pr285951AC1ERKS0_RKNS_4TempE // CHECK: invoke void @_ZN7pr285954TempD1Ev + // + // CHECK: add nuw i64 %[[J]], 1 + // CHECK: icmp eq + // CHECK: br i1 + // + // CHECK: add nuw i64 %[[I]], 1 + // CHECK: icmp eq + // CHECK: br i1 + // + // CHECK: ret void + // // CHECK: landingpad // CHECK: landingpad - // CHECK: br label [[CLEANUP:%.*]]{{$}} + // CHECK: br label %[[CLEANUP:.*]]{{$}} // CHECK: landingpad // CHECK: invoke void @_ZN7pr285954TempD1Ev - // CHECK: br label [[CLEANUP]] - // CHECK: icmp eq [[A]]* [[DESTBASE]], [[DEST]] - // CHECK: [[T0:%.*]] = phi [[A]]* - // CHECK: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[T0]], i64 -1 - // CHECK: call void @_ZN7pr285951AD1Ev([[A]]* [[T1]]) - // CHECK: icmp eq [[A]]* [[T1]], [[DESTBASE]] + // CHECK: br label %[[CLEANUP]] + // + // FIXME: only emit a single cleanup loop here + // CHECK: [[CLEANUP]]: + // CHECK: icmp eq %[[A]]* %[[DST_I_0]], %[[DST_I_J]] + // CHECK: %[[T0:.*]] = phi %[[A]]* + // CHECK: %[[T1:.*]] = getelementptr inbounds %[[A]], %[[A]]* %[[T0]], i64 -1 + // CHECK: call void @_ZN7pr285951AD1Ev(%[[A]]* %[[T1]]) + // CHECK: icmp eq %[[A]]* %[[T1]], %[[DST_I_0]] + // + // CHECK: %[[BEGIN:.*]] = getelementptr {{.*}} %[[DST_0]], i64 0, i64 0 + // CHECK: %[[END:.*]] = getelementptr {{.*}} %[[DST_I]], i64 0, i64 0 + // CHECK: icmp eq %[[A]]* %[[BEGIN]], %[[END]] + // CHECK: %[[T0:.*]] = phi %[[A]]* + // CHECK: %[[T1:.*]] = getelementptr inbounds %[[A]], %[[A]]* %[[T0]], i64 -1 + // CHECK: call void @_ZN7pr285951AD1Ev(%[[A]]* %[[T1]]) + // CHECK: icmp eq %[[A]]* %[[T1]], %[[BEGIN]] (void) [array]{}; - - // Skip over the initialization loop. - // CHECK: [[BEGIN:%.*]] = getelementptr inbounds [3 x [5 x [[A]]]], [3 x [5 x [[A]]]]* [[ARRAY]], i32 0, i32 0, i32 0 } } diff --git a/test/CodeGenObjCXX/arc-special-member-functions.mm b/test/CodeGenObjCXX/arc-special-member-functions.mm index df3c22916f572c07fbb57e1b80ac284565b85969..af161ddc5ad53e74fd9c7bbb149c96a11337c569 100644 --- a/test/CodeGenObjCXX/arc-special-member-functions.mm +++ b/test/CodeGenObjCXX/arc-special-member-functions.mm @@ -141,10 +141,9 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) { // Implicitly-generated copy constructor for ObjCArrayMember // CHECK-LABEL: define linkonce_odr void @_ZN15ObjCArrayMemberC2ERKS_ -// CHECK: br i1 // CHECK: call i8* @objc_retain // CHECK-NEXT: store i8* -// CHECK-NEXT: br label +// CHECK: br i1 // CHECK: ret // Implicitly-generated default constructor for ObjCBlockMember diff --git a/test/CodeGenObjCXX/implicit-copy-constructor.mm b/test/CodeGenObjCXX/implicit-copy-constructor.mm index 6c56616f04cf2d1d8856b551e1d3c821207ffb22..e1c7b8ded0e6f8324afbe572efb42037b6fea330 100644 --- a/test/CodeGenObjCXX/implicit-copy-constructor.mm +++ b/test/CodeGenObjCXX/implicit-copy-constructor.mm @@ -49,12 +49,14 @@ void f(D d) { // CHECK: call void @_ZN1BC2ERS_ // CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}} // CHECK: call void @_ZN1BC1ERS_ -// CHECK: br -// CHECK: {{icmp ult.*, 2}} -// CHECK: {{icmp ult.*, 3}} +// CHECK: br label // CHECK: call void @_ZN1AC1Ev // CHECK: call void @_ZN1CC1ERS_1A // CHECK: call void @_ZN1AD1Ev +// CHECK: {{icmp eq.*, 3}} +// CHECK: br i1 +// CHECK: {{icmp eq.*, 2}} +// CHECK: br i1 // CHECK: {{call.*@objc_memmove_collectable}} // CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 12}} // CHECK: ret void diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index a441405939e12c608bf20cfb8694477b0dc36e93..0b7528281acad38aee09cf1f1950240c2136f124 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -566,6 +566,21 @@ struct ArrayRVal { }; static_assert(ArrayRVal().elems[3].f() == 0, ""); +namespace CopyCtor { + struct A { + constexpr A() {} + constexpr A(const A &) {} + }; + struct B { + A a; + int arr[10]; + }; + constexpr B b{{}, {1, 2, 3, 4, 5}}; + constexpr B c = b; + static_assert(c.arr[2] == 3, ""); + static_assert(c.arr[7] == 0, ""); +} + constexpr int selfref[2][2][2] = { selfref[1][1][1] + 1, selfref[0][0][0] + 1, selfref[1][0][1] + 1, selfref[0][1][0] + 1, diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp index a2aedb64859882b346f24633b92ad006574f07d3..7e08f9619c1c60a3f80cd62267ad6acaf3f38af7 100644 --- a/unittests/Tooling/RecursiveASTVisitorTest.cpp +++ b/unittests/Tooling/RecursiveASTVisitorTest.cpp @@ -133,25 +133,6 @@ TEST(RecursiveASTVisitor, AttributesAreVisited) { "};\n")); } -// Check to ensure that VarDecls are visited. -class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> { -public: - bool VisitVarDecl(VarDecl *VD) { - Match(VD->getNameAsString(), VD->getLocStart()); - return true; - } -}; - -TEST(RecursiveASTVisitor, ArrayInitializersAreVisited) { - VarDeclVisitor Visitor; - Visitor.ExpectMatch("__i0", 1, 8); - EXPECT_TRUE( - Visitor.runOver("struct MyClass {\n" - " int c[1];\n" - " static MyClass Create() { return MyClass(); }\n" - "};\n")); -} - // Check to ensure that implicit default argument expressions are visited. class IntegerLiteralVisitor : public ExpectedLocationVisitor<IntegerLiteralVisitor> {