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