@@ -4633,6 +4633,59 @@ static void TryConstructorInitialization(Sema &S,
46334633 IsListInit | IsInitListCopy, AsInitializerList);
46344634}
46354635
4636+ static void TryOrBuildParenListInitialization (
4637+ Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
4638+ ArrayRef<Expr *> Args, InitializationSequence &Sequence, bool VerifyOnly,
4639+ ExprResult *Result = nullptr );
4640+
4641+ // / Attempt to initialize an object of a class type either by
4642+ // / direct-initialization, or by copy-initialization from an
4643+ // / expression of the same or derived class type. This corresponds
4644+ // / to the first two sub-bullets of C++2c [dcl.init.general] p16.6.
4645+ // /
4646+ // / \param IsAggrListInit Is this non-list-initialization being done as
4647+ // / part of a list-initialization of an aggregate
4648+ // / from a single expression of the same or
4649+ // / derived class type (C++2c [dcl.init.list] p3.2)?
4650+ static void TryConstructorOrParenListInitialization (
4651+ Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
4652+ MultiExprArg Args, QualType DestType, InitializationSequence &Sequence,
4653+ bool IsAggrListInit) {
4654+ // C++2c [dcl.init.general] p16.6:
4655+ // * Otherwise, if the destination type is a class type:
4656+ // * If the initializer expression is a prvalue and
4657+ // the cv-unqualified version of the source type is the same
4658+ // as the destination type, the initializer expression is used
4659+ // to initialize the destination object.
4660+ // * Otherwise, if the initialization is direct-initialization,
4661+ // or if it is copy-initialization where the cv-unqualified
4662+ // version of the source type is the same as or is derived from
4663+ // the class of the destination type, constructors are considered.
4664+ // The applicable constructors are enumerated, and the best one
4665+ // is chosen through overload resolution. Then:
4666+ // * If overload resolution is successful, the selected
4667+ // constructor is called to initialize the object, with
4668+ // the initializer expression or expression-list as its
4669+ // argument(s).
4670+ TryConstructorInitialization (S, Entity, Kind, Args, DestType, DestType,
4671+ Sequence, /* IsListInit=*/ false , IsAggrListInit);
4672+
4673+ // * Otherwise, if no constructor is viable, the destination type
4674+ // is an aggregate class, and the initializer is a parenthesized
4675+ // expression-list, the object is initialized as follows. [...]
4676+ // Parenthesized initialization of aggregates is a C++20 feature.
4677+ if (S.getLangOpts ().CPlusPlus20 &&
4678+ Kind.getKind () == InitializationKind::IK_Direct && Sequence.Failed () &&
4679+ Sequence.getFailureKind () ==
4680+ InitializationSequence::FK_ConstructorOverloadFailed &&
4681+ Sequence.getFailedOverloadResult () == OR_No_Viable_Function &&
4682+ (IsAggrListInit || DestType->isAggregateType ()))
4683+ TryOrBuildParenListInitialization (S, Entity, Kind, Args, Sequence,
4684+ /* VerifyOnly=*/ true );
4685+
4686+ // * Otherwise, the initialization is ill-formed.
4687+ }
4688+
46364689static bool
46374690ResolveOverloadedFunctionForReferenceBinding (Sema &S,
46384691 Expr *Initializer,
@@ -4846,11 +4899,16 @@ static void TryListInitialization(Sema &S,
48464899 QualType InitType = InitList->getInit (0 )->getType ();
48474900 if (S.Context .hasSameUnqualifiedType (InitType, DestType) ||
48484901 S.IsDerivedFrom (InitList->getBeginLoc (), InitType, DestType)) {
4902+ InitializationKind SubKind =
4903+ Kind.getKind () == InitializationKind::IK_DirectList
4904+ ? InitializationKind::CreateDirect (Kind.getLocation (),
4905+ InitList->getLBraceLoc (),
4906+ InitList->getRBraceLoc ())
4907+ : Kind;
48494908 Expr *InitListAsExpr = InitList;
4850- TryConstructorInitialization (S, Entity, Kind, InitListAsExpr, DestType,
4851- DestType, Sequence,
4852- /* InitListSyntax*/ false ,
4853- /* IsInitListCopy*/ true );
4909+ TryConstructorOrParenListInitialization (
4910+ S, Entity, SubKind, InitListAsExpr, DestType, Sequence,
4911+ /* IsAggrListInit=*/ true );
48544912 return ;
48554913 }
48564914 }
@@ -5709,7 +5767,7 @@ static void TryDefaultInitialization(Sema &S,
57095767static void TryOrBuildParenListInitialization (
57105768 Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
57115769 ArrayRef<Expr *> Args, InitializationSequence &Sequence, bool VerifyOnly,
5712- ExprResult *Result = nullptr ) {
5770+ ExprResult *Result) {
57135771 unsigned EntityIndexToProcess = 0 ;
57145772 SmallVector<Expr *, 4 > InitExprs;
57155773 QualType ResultType;
@@ -6688,42 +6746,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
66886746 (Context.hasSameUnqualifiedType (SourceType, DestType) ||
66896747 (Initializer && S.IsDerivedFrom (Initializer->getBeginLoc (),
66906748 SourceType, DestType))))) {
6691- TryConstructorInitialization (S, Entity, Kind, Args, DestType, DestType,
6692- *this );
6693-
6694- // We fall back to the "no matching constructor" path if the
6695- // failed candidate set has functions other than the three default
6696- // constructors. For example, conversion function.
6697- if (const auto *RD =
6698- dyn_cast<CXXRecordDecl>(DestType->getAs <RecordType>()->getDecl ());
6699- // In general, we should call isCompleteType for RD to check its
6700- // completeness, we don't call it here as it was already called in the
6701- // above TryConstructorInitialization.
6702- S.getLangOpts ().CPlusPlus20 && RD && RD->hasDefinition () &&
6703- RD->isAggregate () && Failed () &&
6704- getFailureKind () == FK_ConstructorOverloadFailed) {
6705- // Do not attempt paren list initialization if overload resolution
6706- // resolves to a deleted function .
6707- //
6708- // We may reach this condition if we have a union wrapping a class with
6709- // a non-trivial copy or move constructor and we call one of those two
6710- // constructors. The union is an aggregate, but the matched constructor
6711- // is implicitly deleted, so we need to prevent aggregate initialization
6712- // (otherwise, it'll attempt aggregate initialization by initializing
6713- // the first element with a reference to the union).
6714- OverloadCandidateSet::iterator Best;
6715- OverloadingResult OR = getFailedCandidateSet ().BestViableFunction (
6716- S, Kind.getLocation (), Best);
6717- if (OR != OverloadingResult::OR_Deleted) {
6718- // C++20 [dcl.init] 17.6.2.2:
6719- // - Otherwise, if no constructor is viable, the destination type is
6720- // an
6721- // aggregate class, and the initializer is a parenthesized
6722- // expression-list.
6723- TryOrBuildParenListInitialization (S, Entity, Kind, Args, *this ,
6724- /* VerifyOnly=*/ true );
6725- }
6726- }
6749+ TryConstructorOrParenListInitialization (S, Entity, Kind, Args, DestType,
6750+ *this , /* IsAggrListInit=*/ false );
67276751 } else {
67286752 // - Otherwise (i.e., for the remaining copy-initialization cases),
67296753 // user-defined conversion sequences that can convert from the
0 commit comments