diff options
author | Yang Fan <nullptr.cpp@gmail.com> | 2021-01-04 17:36:58 +0800 |
---|---|---|
committer | Yang Fan <nullptr.cpp@gmail.com> | 2021-01-06 10:05:40 +0800 |
commit | 74f93bc373d089e757bb65cf8b30b63a4eae8b69 (patch) | |
tree | 6e94d1bd564abf9d189c7a439bbe4b33ee89548a /clang/lib/Sema/SemaInit.cpp | |
parent | f4bcbdf9cea16bf91ba342268f681de45e15733c (diff) | |
download | llvm-74f93bc373d089e757bb65cf8b30b63a4eae8b69.zip llvm-74f93bc373d089e757bb65cf8b30b63a4eae8b69.tar.gz llvm-74f93bc373d089e757bb65cf8b30b63a4eae8b69.tar.bz2 |
[Sema] Fix deleted function problem in implicitly movable test
In implicitly movable test, a two-stage overload resolution is performed.
If the first overload resolution selects a deleted function, Clang directly
performs the second overload resolution, without checking whether the
deleted function matches the additional criteria.
This patch fixes the above problem.
Reviewed By: Quuxplusone
Differential Revision: https://reviews.llvm.org/D92936
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 90 |
1 files changed, 56 insertions, 34 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 6d2e609..b5f31bf 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4115,11 +4115,13 @@ static void TryConstructorInitialization(Sema &S, IsListInit); } if (Result) { - Sequence.SetOverloadFailure(IsListInit ? - InitializationSequence::FK_ListConstructorOverloadFailed : - InitializationSequence::FK_ConstructorOverloadFailed, - Result); - return; + Sequence.SetOverloadFailure( + IsListInit ? InitializationSequence::FK_ListConstructorOverloadFailed + : InitializationSequence::FK_ConstructorOverloadFailed, + Result); + + if (Result != OR_Deleted) + return; } bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -4140,31 +4142,45 @@ static void TryConstructorInitialization(Sema &S, return; } - // C++11 [dcl.init]p6: - // If a program calls for the default initialization of an object - // of a const-qualified type T, T shall be a class type with a - // user-provided default constructor. - // C++ core issue 253 proposal: - // If the implicit default constructor initializes all subobjects, no - // initializer should be required. - // The 253 proposal is for example needed to process libstdc++ headers in 5.x. CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function); - if (Kind.getKind() == InitializationKind::IK_Default && - Entity.getType().isConstQualified()) { - if (!CtorDecl->getParent()->allowConstDefaultInit()) { - if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) - Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + if (Result != OR_Deleted) { + // C++11 [dcl.init]p6: + // If a program calls for the default initialization of an object + // of a const-qualified type T, T shall be a class type with a + // user-provided default constructor. + // C++ core issue 253 proposal: + // If the implicit default constructor initializes all subobjects, no + // initializer should be required. + // The 253 proposal is for example needed to process libstdc++ headers + // in 5.x. + if (Kind.getKind() == InitializationKind::IK_Default && + Entity.getType().isConstQualified()) { + if (!CtorDecl->getParent()->allowConstDefaultInit()) { + if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + return; + } + } + + // C++11 [over.match.list]p1: + // In copy-list-initialization, if an explicit constructor is chosen, the + // initializer is ill-formed. + if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { + Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); return; } } - // C++11 [over.match.list]p1: - // In copy-list-initialization, if an explicit constructor is chosen, the - // initializer is ill-formed. - if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { - Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); + // [class.copy.elision]p3: + // In some copy-initialization contexts, a two-stage overload resolution + // is performed. + // If the first overload resolution selects a deleted function, we also + // need the initialization sequence to decide whether to perform the second + // overload resolution. + // For deleted functions in other contexts, there is no need to get the + // initialization sequence. + if (Result == OR_Deleted && Kind.getKind() != InitializationKind::IK_Copy) return; - } // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. @@ -5258,9 +5274,17 @@ static void TryUserDefinedConversion(Sema &S, if (OverloadingResult Result = CandidateSet.BestViableFunction(S, DeclLoc, Best)) { Sequence.SetOverloadFailure( - InitializationSequence::FK_UserConversionOverloadFailed, - Result); - return; + InitializationSequence::FK_UserConversionOverloadFailed, Result); + + // [class.copy.elision]p3: + // In some copy-initialization contexts, a two-stage overload resolution + // is performed. + // If the first overload resolution selects a deleted function, we also + // need the initialization sequence to decide whether to perform the second + // overload resolution. + if (!(Result == OR_Deleted && + Kind.getKind() == InitializationKind::IK_Copy)) + return; } FunctionDecl *Function = Best->Function; @@ -5564,13 +5588,11 @@ static bool TryOCLZeroOpaqueTypeInitialization(Sema &S, return false; } -InitializationSequence::InitializationSequence(Sema &S, - const InitializedEntity &Entity, - const InitializationKind &Kind, - MultiExprArg Args, - bool TopLevelOfInitList, - bool TreatUnavailableAsInvalid) - : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) { +InitializationSequence::InitializationSequence( + Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, + MultiExprArg Args, bool TopLevelOfInitList, bool TreatUnavailableAsInvalid) + : FailedOverloadResult(OR_Success), + FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) { InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList, TreatUnavailableAsInvalid); } |