@@ -4633,6 +4633,59 @@ static void TryConstructorInitialization(Sema &S,
4633
4633
IsListInit | IsInitListCopy, AsInitializerList);
4634
4634
}
4635
4635
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
+
4636
4689
static bool
4637
4690
ResolveOverloadedFunctionForReferenceBinding (Sema &S,
4638
4691
Expr *Initializer,
@@ -4847,10 +4900,15 @@ static void TryListInitialization(Sema &S,
4847
4900
if (S.Context .hasSameUnqualifiedType (InitType, DestType) ||
4848
4901
S.IsDerivedFrom (InitList->getBeginLoc (), InitType, DestType)) {
4849
4902
Expr *InitListAsExpr = InitList;
4850
- TryConstructorInitialization (S, Entity, Kind, InitListAsExpr, DestType,
4851
- DestType, Sequence,
4852
- /* InitListSyntax*/ false ,
4853
- /* IsInitListCopy*/ true );
4903
+ InitializationKind SubKind =
4904
+ Kind.getKind () == InitializationKind::IK_DirectList
4905
+ ? InitializationKind::CreateDirect (Kind.getLocation (),
4906
+ InitList->getLBraceLoc (),
4907
+ InitList->getRBraceLoc ())
4908
+ : Kind;
4909
+ TryConstructorOrParenListInitialization (
4910
+ S, Entity, SubKind, InitListAsExpr, DestType, Sequence,
4911
+ /* IsAggrListInit=*/ true );
4854
4912
return ;
4855
4913
}
4856
4914
}
@@ -5709,7 +5767,7 @@ static void TryDefaultInitialization(Sema &S,
5709
5767
static void TryOrBuildParenListInitialization (
5710
5768
Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
5711
5769
ArrayRef<Expr *> Args, InitializationSequence &Sequence, bool VerifyOnly,
5712
- ExprResult *Result = nullptr ) {
5770
+ ExprResult *Result) {
5713
5771
unsigned EntityIndexToProcess = 0 ;
5714
5772
SmallVector<Expr *, 4 > InitExprs;
5715
5773
QualType ResultType;
@@ -6688,42 +6746,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
6688
6746
(Context.hasSameUnqualifiedType (SourceType, DestType) ||
6689
6747
(Initializer && S.IsDerivedFrom (Initializer->getBeginLoc (),
6690
6748
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 );
6727
6751
} else {
6728
6752
// - Otherwise (i.e., for the remaining copy-initialization cases),
6729
6753
// user-defined conversion sequences that can convert from the
0 commit comments