From: Sebastian Redl Date: Sat, 4 Feb 2012 21:27:47 +0000 (+0000) Subject: A useful approximation of initializer list constructors. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6cd03dbb310f472b14b8d6d69d8c9b5b7f1200e2;p=clang A useful approximation of initializer list constructors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149792 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index 8b4573b371..36ffde9098 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -838,11 +838,15 @@ public: void AddListInitializationStep(QualType T); /// \brief Add a constructor-initialization step. + /// + /// \arg FromInitList The constructor call is syntactically an initializer + /// list. + /// \arg AsInitList The constructor is called as an init list constructor. void AddConstructorInitializationStep(CXXConstructorDecl *Constructor, AccessSpecifier Access, QualType T, bool HadMultipleCandidates, - bool FromInitList); + bool FromInitList, bool AsInitList); /// \brief Add a zero-initialization step. void AddZeroInitializationStep(QualType T); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6a7af457bb..7673f1d5f2 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -5824,9 +5824,6 @@ bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { if (!Specialization) return false; - if (Specialization->getSpecializationKind() != TSK_ImplicitInstantiation) - return false; - Template = Specialization->getSpecializedTemplate(); Arguments = Specialization->getTemplateArgs().data(); } else if (const TemplateSpecializationType *TST = diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 5caced9d69..406f524e04 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2566,9 +2566,10 @@ InitializationSequence AccessSpecifier Access, QualType T, bool HadMultipleCandidates, - bool FromInitList) { + bool FromInitList, bool AsInitList) { Step S; - S.Kind = FromInitList ? SK_ListConstructorCall : SK_ConstructorInitialization; + S.Kind = FromInitList && !AsInitList ? SK_ListConstructorCall + : SK_ConstructorInitialization; S.Type = T; S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Constructor; @@ -2727,7 +2728,8 @@ static bool TryListConstructionSpecialCases(Sema &S, DefaultConstructor->getAccess(), DestType, /*MultipleCandidates=*/false, - /*FromInitList=*/true); + /*FromInitList=*/true, + /*AsInitList=*/false); return true; } } @@ -2795,7 +2797,7 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, if (!Constructor->isInvalidDecl() && (AllowExplicit || !Constructor->isExplicit()) && - (!OnlyListConstructors || !S.isInitListConstructor(Constructor))) { + (!OnlyListConstructors || S.isInitListConstructor(Constructor))) { if (ConstructorTmpl) S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, @@ -2860,13 +2862,7 @@ static void TryConstructorInitialization(Sema &S, bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct || Kind.getKind() == InitializationKind::IK_Value || Kind.getKind() == InitializationKind::IK_Default); - - if (InitListSyntax) { - // Time to unwrap the init list. - InitListExpr *ILE = cast(Args[0]); - Args = ILE->getInits(); - NumArgs = ILE->getNumInits(); - } + bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy; // - Otherwise, if T is a class type, constructors are considered. The // applicable constructors are enumerated, and the best one is chosen @@ -2874,13 +2870,42 @@ static void TryConstructorInitialization(Sema &S, DeclContext::lookup_iterator ConStart, ConEnd; llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl); + OverloadingResult Result = OR_No_Viable_Function; OverloadCandidateSet::iterator Best; - if (OverloadingResult Result = - ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, - CandidateSet, ConStart, ConEnd, Best, - Kind.getKind() == InitializationKind::IK_Copy, - AllowExplicit, - /*OnlyListConstructors=*/false)) { + bool AsInitializerList = false; + + // C++11 [over.match.list]p1: + // When objects of non-aggregate type T are list-initialized, overload + // resolution selects the constructor in two phases: + // - Initially, the candidate functions are the initializer-list + // constructors of the class T and the argument list consists of the + // initializer list as a single argument. + if (InitListSyntax) { + AsInitializerList = true; + Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, + CandidateSet, ConStart, ConEnd, Best, + CopyInitialization, AllowExplicit, + /*OnlyListConstructor=*/true); + + // Time to unwrap the init list. + InitListExpr *ILE = cast(Args[0]); + Args = ILE->getInits(); + NumArgs = ILE->getNumInits(); + } + + // C++11 [over.match.list]p1: + // - If no viable initializer-list constructor is found, overload resolution + // is performed again, where the candidate functions are all the + // constructors of the class T nad the argument list consists of the + // elements of the initializer list. + if (Result == OR_No_Viable_Function) { + AsInitializerList = false; + Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, + CandidateSet, ConStart, ConEnd, Best, + CopyInitialization, AllowExplicit, + /*OnlyListConstructors=*/false); + } + if (Result) { Sequence.SetOverloadFailure(InitListSyntax ? InitializationSequence::FK_ListConstructorOverloadFailed : InitializationSequence::FK_ConstructorOverloadFailed, @@ -2906,7 +2931,7 @@ static void TryConstructorInitialization(Sema &S, Sequence.AddConstructorInitializationStep(CtorDecl, Best->FoundDecl.getAccess(), DestType, HadMultipleCandidates, - InitListSyntax); + InitListSyntax, AsInitializerList); } static bool