@@ -4634,6 +4634,59 @@ static void TryConstructorInitialization(Sema &S,
4634
4634
IsListInit | IsInitListCopy, AsInitializerList);
4635
4635
}
4636
4636
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
+
4637
4690
static bool
4638
4691
ResolveOverloadedFunctionForReferenceBinding (Sema &S,
4639
4692
Expr *Initializer,
@@ -4847,11 +4900,16 @@ static void TryListInitialization(Sema &S,
4847
4900
QualType InitType = InitList->getInit (0 )->getType ();
4848
4901
if (S.Context .hasSameUnqualifiedType (InitType, DestType) ||
4849
4902
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;
4850
4909
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 );
4855
4913
return ;
4856
4914
}
4857
4915
}
@@ -5710,7 +5768,7 @@ static void TryDefaultInitialization(Sema &S,
5710
5768
static void TryOrBuildParenListInitialization (
5711
5769
Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
5712
5770
ArrayRef<Expr *> Args, InitializationSequence &Sequence, bool VerifyOnly,
5713
- ExprResult *Result = nullptr ) {
5771
+ ExprResult *Result) {
5714
5772
unsigned EntityIndexToProcess = 0 ;
5715
5773
SmallVector<Expr *, 4 > InitExprs;
5716
5774
QualType ResultType;
@@ -6689,42 +6747,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
6689
6747
(Context.hasSameUnqualifiedType (SourceType, DestType) ||
6690
6748
(Initializer && S.IsDerivedFrom (Initializer->getBeginLoc (),
6691
6749
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 );
6728
6752
} else {
6729
6753
// - Otherwise (i.e., for the remaining copy-initialization cases),
6730
6754
// user-defined conversion sequences that can convert from the
0 commit comments