From: Richard Smith Date: Wed, 19 Dec 2012 01:39:02 +0000 (+0000) Subject: PR13470: Ensure that copy-list-initialization isntantiates as X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c83c2300e1946fea78ecd3c2e93d9c2dd2638a2b;p=clang PR13470: Ensure that copy-list-initialization isntantiates as copy-list-initialization (and doesn't add an additional copy step): Fill in the ListInitialization bit when creating a CXXConstructExpr. Use it when instantiating initializers in order to correctly handle instantiation of copy-list-initialization. Teach TreeTransform that function arguments are initializations, and so need this special treatment too. Finally, remove some hacks which were working around SubstInitializer's shortcomings. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@170489 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index c737d5f8de..c8b4c0c6e9 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1092,7 +1092,8 @@ public: ArrayRef Args, SourceRange parenRange, bool HadMultipleCandidates, - bool ZeroInitialization = false); + bool ListInitialization, + bool ZeroInitialization); explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 047804ae4f..ab66c9dbb8 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3367,13 +3367,6 @@ public: UnqualifiedId &Name, TypeResult Type); - /// InitializeVarWithConstructor - Creates an CXXConstructExpr - /// and sets it as the initializer for the passed in VarDecl. - bool InitializeVarWithConstructor(VarDecl *VD, - CXXConstructorDecl *Constructor, - MultiExprArg Exprs, - bool HadMultipleCandidates); - /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. /// @@ -3381,8 +3374,9 @@ public: ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg Exprs, - bool HadMultipleCandidates, bool RequiresZeroInit, - unsigned ConstructKind, SourceRange ParenRange); + bool HadMultipleCandidates, bool IsListInitialization, + bool RequiresZeroInit, unsigned ConstructKind, + SourceRange ParenRange); // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if // the constructor can be elidable? @@ -3390,8 +3384,8 @@ public: BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, bool HadMultipleCandidates, - bool RequiresZeroInit, unsigned ConstructKind, - SourceRange ParenRange); + bool IsListInitialization, bool RequiresZeroInit, + unsigned ConstructKind, SourceRange ParenRange); /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating /// the default expr if needed. diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 6c66c90cd4..fcf34d95b5 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -717,12 +717,14 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, ArrayRef Args, SourceRange parenRange, bool HadMultipleCandidates, + bool ListInitialization, bool ZeroInitialization) : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), Cons, false, Args, - HadMultipleCandidates, /*FIXME*/false, ZeroInitialization, + HadMultipleCandidates, + ListInitialization, ZeroInitialization, CXXConstructExpr::CK_Complete, parenRange), Type(Type) { } diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index ec90674e0c..ff9039e3f3 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1487,6 +1487,9 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { } void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { + if (E->isListInitialization()) + OS << "{ "; + for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { if (isa(E->getArg(i))) { // Don't print any defaulted arguments @@ -1496,6 +1499,9 @@ void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { if (i) OS << ", "; PrintExpr(E->getArg(i)); } + + if (E->isListInitialization()) + OS << " }"; } void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 99366b6a6b..8385e8541c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1932,11 +1932,7 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc, } ExprResult Init = InitExpr; - if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent() && - !FD->getDeclContext()->isDependentContext()) { - // Note: We don't type-check when we're in a dependent context, because - // the initialization-substitution code does not properly handle direct - // list initialization. We have the same hackaround for ctor-initializers. + if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { if (isa(InitExpr) && isStdInitializerList(FD->getType(), 0)) { Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) << /*at end of ctor*/1 << InitExpr->getSourceRange(); @@ -2318,10 +2314,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (ParenListExpr *ParenList = dyn_cast(Init)) { Args = ParenList->getExprs(); NumArgs = ParenList->getNumExprs(); - } else { - InitListExpr *InitList = cast(Init); + } else if (InitListExpr *InitList = dyn_cast(Init)) { Args = InitList->getInits(); NumArgs = InitList->getNumInits(); + } else { + // Template instantiation doesn't reconstruct ParenListExprs for us. + Args = &Init; + NumArgs = 1; } if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, IdLoc) @@ -2382,19 +2381,8 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (MemberInit.isInvalid()) return true; - // If we are in a dependent context, template instantiation will - // perform this type-checking again. Just save the arguments that we - // received. - // FIXME: This isn't quite ideal, since our ASTs don't capture all - // of the information that we have about the member - // initializer. However, deconstructing the ASTs is a dicey process, - // and this approach is far more likely to get the corner cases right. - if (CurContext->isDependentContext()) { - // The existing Init will do fine. - } else { - Init = MemberInit.get(); - CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); - } + Init = MemberInit.get(); + CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); } if (DirectMember) { @@ -9515,6 +9503,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, bool HadMultipleCandidates, + bool IsListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { @@ -9538,7 +9527,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs, HadMultipleCandidates, - RequiresZeroInit, ConstructKind, ParenRange); + IsListInitialization, RequiresZeroInit, + ConstructKind, ParenRange); } /// BuildCXXConstructExpr - Creates a complete call to a constructor, @@ -9548,39 +9538,19 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg ExprArgs, bool HadMultipleCandidates, + bool IsListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { MarkFunctionReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs, - HadMultipleCandidates, /*FIXME*/false, - RequiresZeroInit, + HadMultipleCandidates, + IsListInitialization, RequiresZeroInit, static_cast(ConstructKind), ParenRange)); } -bool Sema::InitializeVarWithConstructor(VarDecl *VD, - CXXConstructorDecl *Constructor, - MultiExprArg Exprs, - bool HadMultipleCandidates) { - // FIXME: Provide the correct paren SourceRange when available. - ExprResult TempResult = - BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, - Exprs, HadMultipleCandidates, false, - CXXConstructExpr::CK_Complete, SourceRange()); - if (TempResult.isInvalid()) - return true; - - Expr *Temp = TempResult.takeAs(); - CheckImplicitConversions(Temp, VD->getLocation()); - MarkFunctionReferenced(VD->getLocation(), Constructor); - Temp = MaybeCreateExprWithCleanups(Temp); - VD->setInit(Temp); - - return false; -} - void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (VD->isInvalidDecl()) return; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 4a93b118c6..629c9b210a 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2323,11 +2323,11 @@ static ExprResult BuildCXXCastArgument(Sema &S, S.CheckConstructorAccess(CastLoc, Constructor, InitializedEntity::InitializeTemporary(Ty), Constructor->getAccess()); - + ExprResult Result = S.BuildCXXConstructExpr(CastLoc, Ty, cast(Method), - ConstructorArgs, - HadMultipleCandidates, /*ZeroInit*/ false, + ConstructorArgs, HadMultipleCandidates, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); if (Result.isInvalid()) return ExprError(); @@ -2479,14 +2479,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, ToType, SCS.CopyConstructor, ConstructorArgs, /*HadMultipleCandidates*/ false, - /*ZeroInit*/ false, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); } return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), ToType, SCS.CopyConstructor, From, /*HadMultipleCandidates*/ false, - /*ZeroInit*/ false, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index a5a0a11ed6..a40bf9fd8e 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -4563,6 +4563,7 @@ static ExprResult CopyObject(Sema &S, CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, ConstructorArgs, HadMultipleCandidates, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -4652,7 +4653,8 @@ PerformConstructorInitialization(Sema &S, const InitializationKind &Kind, MultiExprArg Args, const InitializationSequence::Step& Step, - bool &ConstructorInitRequiresZeroInit) { + bool &ConstructorInitRequiresZeroInit, + bool IsListInitialization) { unsigned NumArgs = Args.size(); CXXConstructorDecl *Constructor = cast(Step.Function.Function); @@ -4710,13 +4712,12 @@ PerformConstructorInitialization(Sema &S, if (Kind.getKind() != InitializationKind::IK_DirectList) ParenRange = Kind.getParenRange(); - CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context, - Constructor, - TSInfo, - ConstructorArgs, - ParenRange, - HadMultipleCandidates, - ConstructorInitRequiresZeroInit)); + CurInit = S.Owned( + new (S.Context) CXXTemporaryObjectExpr(S.Context, Constructor, + TSInfo, ConstructorArgs, + ParenRange, IsListInitialization, + HadMultipleCandidates, + ConstructorInitRequiresZeroInit)); } else { CXXConstructExpr::ConstructionKind ConstructKind = CXXConstructExpr::CK_Complete; @@ -4741,6 +4742,7 @@ PerformConstructorInitialization(Sema &S, Constructor, /*Elidable=*/true, ConstructorArgs, HadMultipleCandidates, + IsListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, parenRange); @@ -4749,6 +4751,7 @@ PerformConstructorInitialization(Sema &S, Constructor, ConstructorArgs, HadMultipleCandidates, + IsListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, parenRange); @@ -5084,6 +5087,7 @@ InitializationSequence::Perform(Sema &S, CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, ConstructorArgs, HadMultipleCandidates, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -5239,7 +5243,8 @@ InitializationSequence::Perform(Sema &S, CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : Entity, Kind, Arg, *Step, - ConstructorInitRequiresZeroInit); + ConstructorInitRequiresZeroInit, + /*IsListInitialization*/ true); break; } @@ -5272,7 +5277,8 @@ InitializationSequence::Perform(Sema &S, CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : Entity, Kind, Args, *Step, - ConstructorInitRequiresZeroInit); + ConstructorInitRequiresZeroInit, + /*IsListInitialization*/ false); break; } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 5ad7b3437e..6d0aa21916 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2582,12 +2582,21 @@ Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) { return Instantiator.TransformExpr(E); } +ExprResult Sema::SubstInitializer(Expr *Init, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool CXXDirectInit) { + TemplateInstantiator Instantiator(*this, TemplateArgs, + SourceLocation(), + DeclarationName()); + return Instantiator.TransformInitializer(Init, CXXDirectInit); +} + bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall, const MultiLevelTemplateArgumentList &TemplateArgs, SmallVectorImpl &Outputs) { if (NumExprs == 0) return false; - + TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), DeclarationName()); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index cca7df3fc1..abe047194d 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3138,45 +3138,6 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, AnyErrors); } -ExprResult Sema::SubstInitializer(Expr *Init, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool CXXDirectInit) { - // Initializers are instantiated like expressions, except that various outer - // layers are stripped. - if (!Init) - return Owned(Init); - - if (ExprWithCleanups *ExprTemp = dyn_cast(Init)) - Init = ExprTemp->getSubExpr(); - - while (CXXBindTemporaryExpr *Binder = dyn_cast(Init)) - Init = Binder->getSubExpr(); - - if (ImplicitCastExpr *ICE = dyn_cast(Init)) - Init = ICE->getSubExprAsWritten(); - - // If this is a direct-initializer, we take apart CXXConstructExprs. - // Everything else is passed through. - CXXConstructExpr *Construct; - if (!CXXDirectInit || !(Construct = dyn_cast(Init)) || - isa(Construct)) - return SubstExpr(Init, TemplateArgs); - - SmallVector NewArgs; - if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, - TemplateArgs, NewArgs)) - return ExprError(); - - // Treat an empty initializer like none. - if (NewArgs.empty()) - return Owned((Expr*)0); - - // Build a ParenListExpr to represent anything else. - // FIXME: Fake locations! - SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart()); - return ActOnParenListExpr(Loc, Loc, NewArgs); -} - // TODO: this could be templated if the various decl types used the // same method name. static bool isInstantiationOf(ClassTemplateDecl *Pattern, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 8d66acbaf2..52f6c4d4c0 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -323,6 +323,15 @@ public: /// \returns the transformed expression. ExprResult TransformExpr(Expr *E); + /// \brief Transform the given initializer. + /// + /// By default, this routine transforms an initializer by stripping off the + /// semantic nodes added by initialization, then passing the result to + /// TransformExpr or TransformExprs. + /// + /// \returns the transformed initializer. + ExprResult TransformInitializer(Expr *Init, bool CXXDirectInit); + /// \brief Transform the given list of expressions. /// /// This routine transforms a list of expressions by invoking @@ -2113,6 +2122,7 @@ public: bool IsElidable, MultiExprArg Args, bool HadMultipleCandidates, + bool ListInitialization, bool RequiresZeroInit, CXXConstructExpr::ConstructionKind ConstructKind, SourceRange ParenRange) { @@ -2124,6 +2134,7 @@ public: return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable, ConvertedArgs, HadMultipleCandidates, + ListInitialization, RequiresZeroInit, ConstructKind, ParenRange); } @@ -2574,6 +2585,53 @@ ExprResult TreeTransform::TransformExpr(Expr *E) { return SemaRef.Owned(E); } +template +ExprResult TreeTransform::TransformInitializer(Expr *Init, + bool CXXDirectInit) { + // Initializers are instantiated like expressions, except that various outer + // layers are stripped. + if (!Init) + return SemaRef.Owned(Init); + + if (ExprWithCleanups *ExprTemp = dyn_cast(Init)) + Init = ExprTemp->getSubExpr(); + + while (CXXBindTemporaryExpr *Binder = dyn_cast(Init)) + Init = Binder->getSubExpr(); + + if (ImplicitCastExpr *ICE = dyn_cast(Init)) + Init = ICE->getSubExprAsWritten(); + + // If this is a direct-initializer, we take apart CXXConstructExprs. + // Everything else is passed through. + CXXConstructExpr *Construct; + if (!(Construct = dyn_cast(Init)) || + isa(Construct) || + (!CXXDirectInit && !Construct->isListInitialization())) + return getDerived().TransformExpr(Init); + + SmallVector NewArgs; + bool ArgChanged = false; + if (getDerived().TransformExprs(Construct->getArgs(), Construct->getNumArgs(), + /*IsCall*/true, NewArgs, &ArgChanged)) + return ExprError(); + + // If this was list initialization, revert to list form. + if (Construct->isListInitialization()) + return getDerived().RebuildInitList(Construct->getLocStart(), NewArgs, + Construct->getLocEnd(), + Construct->getType()); + + // Treat an empty initializer like none. + if (NewArgs.empty()) + return SemaRef.Owned((Expr*)0); + + // Build a ParenListExpr to represent anything else. + SourceRange Parens = Construct->getParenRange(); + return getDerived().RebuildParenListExpr(Parens.getBegin(), NewArgs, + Parens.getEnd()); +} + template bool TreeTransform::TransformExprs(Expr **Inputs, unsigned NumInputs, @@ -2656,7 +2714,9 @@ bool TreeTransform::TransformExprs(Expr **Inputs, continue; } - ExprResult Result = getDerived().TransformExpr(Inputs[I]); + ExprResult Result = + IsCall ? getDerived().TransformInitializer(Inputs[I], /*DirectInit*/false) + : getDerived().TransformExpr(Inputs[I]); if (Result.isInvalid()) return true; @@ -7747,11 +7807,13 @@ TreeTransform::TransformDependentScopeDeclRefExpr( template ExprResult TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { - // CXXConstructExprs are always implicit, so when we have a - // 1-argument construction we just transform that argument. + // CXXConstructExprs other than for list-initialization and + // CXXTemporaryObjectExpr are always implicit, so when we have + // a 1-argument construction we just transform that argument. if ((E->getNumArgs() == 1 || (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1)))) && - (!getDerived().DropCallArgument(E->getArg(0)))) + (!getDerived().DropCallArgument(E->getArg(0))) && + !E->isListInitialization()) return getDerived().TransformExpr(E->getArg(0)); TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName()); @@ -7787,6 +7849,7 @@ TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { Constructor, E->isElidable(), Args, E->hadMultipleCandidates(), + E->isListInitialization(), E->requiresZeroInitialization(), E->getConstructionKind(), E->getParenRange()); @@ -7844,6 +7907,7 @@ TreeTransform::TransformCXXTemporaryObjectExpr( return SemaRef.MaybeBindToTemporary(E); } + // FIXME: Pass in E->isListInitialization(). return getDerived().RebuildCXXTemporaryObjectExpr(T, /*FIXME:*/T->getTypeLoc().getEndLoc(), Args, diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 529cfea433..fe29ee652a 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1102,6 +1102,7 @@ void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { E->setLocation(ReadSourceLocation(Record, Idx)); E->setElidable(Record[Idx++]); E->setHadMultipleCandidates(Record[Idx++]); + E->setListInitialization(Record[Idx++]); E->setRequiresZeroInitialization(Record[Idx++]); E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); E->ParenRange = ReadSourceRange(Record, Idx); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 7e8ce42d7c..1591c6c86a 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1076,6 +1076,7 @@ void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { Writer.AddSourceLocation(E->getLocation(), Record); Record.push_back(E->isElidable()); Record.push_back(E->hadMultipleCandidates()); + Record.push_back(E->isListInitialization()); Record.push_back(E->requiresZeroInitialization()); Record.push_back(E->getConstructionKind()); // FIXME: stable encoding Writer.AddSourceRange(E->getParenRange(), Record); diff --git a/test/Index/recursive-cxx-member-calls.cpp b/test/Index/recursive-cxx-member-calls.cpp index 501dc2954f..3f68614fbe 100644 --- a/test/Index/recursive-cxx-member-calls.cpp +++ b/test/Index/recursive-cxx-member-calls.cpp @@ -831,9 +831,9 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) { // CHECK-tokens: Punctuation: ")" [87:38 - 87:39] CXXConstructor=StringSwitch:87:12 (Definition) // CHECK-tokens: Punctuation: ":" [87:40 - 87:41] CXXConstructor=StringSwitch:87:12 (Definition) // CHECK-tokens: Identifier: "Str" [87:42 - 87:45] MemberRef=Str:84:13 -// CHECK-tokens: Punctuation: "(" [87:45 - 87:46] UnexposedExpr= +// CHECK-tokens: Punctuation: "(" [87:45 - 87:46] CallExpr=StringRef:38:7 // CHECK-tokens: Identifier: "Str" [87:46 - 87:49] DeclRefExpr=Str:87:35 -// CHECK-tokens: Punctuation: ")" [87:49 - 87:50] UnexposedExpr= +// CHECK-tokens: Punctuation: ")" [87:49 - 87:50] CallExpr=StringRef:38:7 // CHECK-tokens: Punctuation: "," [87:50 - 87:51] CXXConstructor=StringSwitch:87:12 (Definition) // CHECK-tokens: Identifier: "Result" [87:52 - 87:58] MemberRef=Result:85:12 // CHECK-tokens: Punctuation: "(" [87:58 - 87:59] UnexposedExpr= @@ -1843,7 +1843,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) { // CHECK: 87:35: ParmDecl=Str:87:35 (Definition) Extent=[87:25 - 87:38] // CHECK: 87:25: TypeRef=class llvm::StringRef:38:7 Extent=[87:25 - 87:34] // CHECK: 87:42: MemberRef=Str:84:13 Extent=[87:42 - 87:45] -// CHECK: 87:45: UnexposedExpr= Extent=[87:45 - 87:50] +// CHECK: 87:42: CallExpr=StringRef:38:7 Extent=[87:42 - 87:50] // CHECK: 87:46: DeclRefExpr=Str:87:35 Extent=[87:46 - 87:49] // CHECK: 87:52: MemberRef=Result:85:12 Extent=[87:52 - 87:58] // CHECK: 87:58: UnexposedExpr= Extent=[87:58 - 87:61] diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp index a657ec81a1..45ec0cbfdd 100644 --- a/test/SemaCXX/cxx0x-initializer-constructor.cpp +++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -306,17 +306,63 @@ namespace init_list_default { } -// -namespace rdar11974632 { +// PR13470, +namespace PR13470 { + struct W { + explicit W(int); // expected-note {{here}} + }; + struct X { - X(const X&) = delete; + X(const X&) = delete; // expected-note 3 {{here}} X(int); }; + template void call(Fn f) { + f({1}); // expected-error {{constructor is explicit}} + f(T{1}); // expected-error {{call to deleted constructor}} + } + + void ref_w(const W &); // expected-note 2 {{not viable}} + void call_ref_w() { + ref_w({1}); // expected-error {{no matching function}} + ref_w(W{1}); + call(ref_w); // expected-note {{instantiation of}} + } + + void ref_x(const X &); + void call_ref_x() { + ref_x({1}); + ref_x(X{1}); + call(ref_x); // ok + } + + void val_x(X); // expected-note 2 {{parameter}} + void call_val_x() { + val_x({1}); + val_x(X{1}); // expected-error {{call to deleted constructor}} + call(val_x); // expected-note {{instantiation of}} + } + template - struct Y { + struct Y { X x{1}; + void f() { X x{1}; } + void h() { + ref_w({1}); // expected-error {{no matching function}} + ref_w(W{1}); + ref_x({1}); + ref_x(X{1}); + val_x({1}); + val_x(X{1}); // expected-error {{call to deleted constructor}} + } + Y() {} + Y(int) : x{1} {} }; Y yi; + Y yi2(0); + void g() { + yi.f(); + yi.h(); // ok, all diagnostics produced in template definition + } }