diff options
author | Hans Wennborg <hans@hanshq.net> | 2019-05-06 09:51:10 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2019-05-06 09:51:10 +0000 |
commit | 06edb03dd121a51d2ea4702e224140252a720c86 (patch) | |
tree | 939bf7451f40c9e3145b6c4ae5f6d30328f0b409 /lib/Sema/SemaOverload.cpp | |
parent | 6dab16d8d8d89a49727becbb0d910ddd31983f96 (diff) | |
download | clang-06edb03dd121a51d2ea4702e224140252a720c86.tar.gz |
Revert r359949 "[clang] adding explicit(bool) from c++2a"
This caused Clang to start erroring on the following:
struct S {
template <typename = int> explicit S();
};
struct T : S {};
struct U : T {
U();
};
U::U() {}
$ clang -c /tmp/x.cc
/tmp/x.cc:10:4: error: call to implicitly-deleted default constructor of 'T'
U::U() {}
^
/tmp/x.cc:5:12: note: default constructor of 'T' is implicitly deleted
because base class 'S' has no default constructor
struct T : S {};
^
1 error generated.
See discussion on the cfe-commits email thread.
This also reverts the follow-ups r359966 and r359968.
> this patch adds support for the explicit bool specifier.
>
> Changes:
> - The parsing for the explicit(bool) specifier was added in ParseDecl.cpp.
> - The storage of the explicit specifier was changed. the explicit specifier was stored as a boolean value in the FunctionDeclBitfields and in the DeclSpec class. now it is stored as a PointerIntPair<Expr*, 2> with a flag and a potential expression in CXXConstructorDecl, CXXDeductionGuideDecl, CXXConversionDecl and in the DeclSpec class.
> - Following the AST change, Serialization, ASTMatchers, ASTComparator and ASTPrinter were adapted.
> - Template instantiation was adapted to instantiate the potential expressions of the explicit(bool) specifier When instantiating their associated declaration.
> - The Add*Candidate functions were adapted, they now take a Boolean indicating if the context allowing explicit constructor or conversion function and this boolean is used to remove invalid overloads that required template instantiation to be detected.
> - Test for Semantic and Serialization were added.
>
> This patch is not yet complete. I still need to check that interaction with CTAD and deduction guides is correct. and add more tests for AST operations. But I wanted first feedback.
> Perhaps this patch should be spited in smaller patches, but making each patch testable as a standalone may be tricky.
>
> Patch by Tyker
>
> Differential Revision: https://reviews.llvm.org/D60934
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@360024 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 173 |
1 files changed, 63 insertions, 110 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 1ef932e05e..df979b68b6 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -3242,13 +3242,10 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, From, - CandidateSet, SuppressUserConversions, - /*PartialOverloading*/ false, - AllowExplicit); + CandidateSet, SuppressUserConversions); else S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, From, - CandidateSet, SuppressUserConversions, - /*PartialOverloading*/ false, AllowExplicit); + CandidateSet, SuppressUserConversions); } } @@ -3375,15 +3372,13 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, S.AddTemplateOverloadCandidate( Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, llvm::makeArrayRef(Args, NumArgs), - CandidateSet, SuppressUserConversions, - /*PartialOverloading*/ false, AllowExplicit); + CandidateSet, SuppressUserConversions); else // Allow one user-defined conversion when user specifies a // From->ToType conversion via an static cast (c-style, etc). S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, llvm::makeArrayRef(Args, NumArgs), - CandidateSet, SuppressUserConversions, - /*PartialOverloading*/ false, AllowExplicit); + CandidateSet, SuppressUserConversions); } } } @@ -3415,13 +3410,14 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) - S.AddTemplateConversionCandidate( - ConvTemplate, FoundDecl, ActingContext, From, ToType, - CandidateSet, AllowObjCConversionOnExplicit, AllowExplicit); + S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl, + ActingContext, From, ToType, + CandidateSet, + AllowObjCConversionOnExplicit); else - S.AddConversionCandidate( - Conv, FoundDecl, ActingContext, From, ToType, CandidateSet, - AllowObjCConversionOnExplicit, AllowExplicit); + S.AddConversionCandidate(Conv, FoundDecl, ActingContext, + From, ToType, CandidateSet, + AllowObjCConversionOnExplicit); } } } @@ -4449,13 +4445,13 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, } if (ConvTemplate) - S.AddTemplateConversionCandidate( - ConvTemplate, I.getPair(), ActingDC, Init, DeclType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false, AllowExplicit); + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, + Init, DeclType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false); else - S.AddConversionCandidate( - Conv, I.getPair(), ActingDC, Init, DeclType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false, AllowExplicit); + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, + DeclType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false); } bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -5418,7 +5414,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, // condition shall be a contextually converted constant expression of type // bool. ImplicitConversionSequence ICS = - CCE == Sema::CCEK_ConstexprIf || CCE == Sema::CCEK_ExplicitBool + CCE == Sema::CCEK_ConstexprIf ? TryContextuallyConvertToBool(S, From) : TryCopyInitialization(S, From, T, /*SuppressUserConversions=*/false, @@ -5734,13 +5730,12 @@ collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType, if (ConvTemplate) SemaRef.AddTemplateConversionCandidate( - ConvTemplate, FoundDecl, ActingContext, From, ToType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false, /*AllowExplicit*/ true); + ConvTemplate, FoundDecl, ActingContext, From, ToType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false); else SemaRef.AddConversionCandidate(Conv, FoundDecl, ActingContext, From, ToType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false, - /*AllowExplicit*/ true); + /*AllowObjCConversionOnExplicit=*/false); } } @@ -5992,11 +5987,13 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context, /// \param PartialOverloading true if we are performing "partial" overloading /// based on an incomplete set of function arguments. This feature is used by /// code completion. -void Sema::AddOverloadCandidate( - FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, - OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions, - ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions) { +void Sema::AddOverloadCandidate(FunctionDecl *Function, + DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, + bool SuppressUserConversions, + bool PartialOverloading, bool AllowExplicit, + ADLCallKind IsADLCandidate, + ConversionSequenceList EarlyConversions) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -6153,11 +6150,13 @@ void Sema::AddOverloadCandidate( // (13.3.3.1) that converts that argument to the corresponding // parameter of F. QualType ParamType = Proto->getParamType(ArgIdx); - Candidate.Conversions[ArgIdx] = TryCopyInitialization( - *this, Args[ArgIdx], ParamType, SuppressUserConversions, - /*InOverloadResolution=*/true, - /*AllowObjCWritebackConversion=*/ - getLangOpts().ObjCAutoRefCount, AllowExplicitConversions); + Candidate.Conversions[ArgIdx] + = TryCopyInitialization(*this, Args[ArgIdx], ParamType, + SuppressUserConversions, + /*InOverloadResolution=*/true, + /*AllowObjCWritebackConversion=*/ + getLangOpts().ObjCAutoRefCount, + AllowExplicit); if (Candidate.Conversions[ArgIdx].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -6171,15 +6170,6 @@ void Sema::AddOverloadCandidate( } } - if (!AllowExplicit) { - ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(Function); - if (ES.getKind() != ExplicitSpecKind::ResolvedFalse) { - Candidate.Viable = false; - Candidate.FailureKind = ovl_fail_explicit_resolved; - return; - } - } - if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_enable_if; @@ -6769,7 +6759,7 @@ void Sema::AddTemplateOverloadCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate) { + bool PartialOverloading, ADLCallKind IsADLCandidate) { if (!CandidateSet.isNewCandidate(FunctionTemplate)) return; @@ -6818,10 +6808,9 @@ void Sema::AddTemplateOverloadCandidate( // Add the function template specialization produced by template argument // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); - AddOverloadCandidate( - Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions, - PartialOverloading, AllowExplicit, - /*AllowExplicitConversions*/ false, IsADLCandidate, Conversions); + AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, + SuppressUserConversions, PartialOverloading, + /*AllowExplicit*/ false, IsADLCandidate, Conversions); } /// Check that implicit conversion sequences can be formed for each argument @@ -6926,11 +6915,14 @@ static bool isAllowableExplicitConversion(Sema &S, /// and ToType is the type that we're eventually trying to convert to /// (which may or may not be the same type as the type that the /// conversion function produces). -void Sema::AddConversionCandidate( - CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, Expr *From, QualType ToType, - OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion) { +void +Sema::AddConversionCandidate(CXXConversionDecl *Conversion, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + Expr *From, QualType ToType, + OverloadCandidateSet& CandidateSet, + bool AllowObjCConversionOnExplicit, + bool AllowResultConversion) { assert(!Conversion->getDescribedFunctionTemplate() && "Conversion function templates use AddTemplateConversionCandidate"); QualType ConvType = Conversion->getConversionType().getNonReferenceType(); @@ -7089,13 +7081,6 @@ void Sema::AddConversionCandidate( "Can only end up with a standard conversion sequence or failure"); } - if (!AllowExplicit && Conversion->getExplicitSpecifier().getKind() != - ExplicitSpecKind::ResolvedFalse) { - Candidate.Viable = false; - Candidate.FailureKind = ovl_fail_explicit_resolved; - return; - } - if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, None)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_enable_if; @@ -7115,11 +7100,14 @@ void Sema::AddConversionCandidate( /// to deduce the template arguments of the conversion function /// template from the type that we are converting to (C++ /// [temp.deduct.conv]). -void Sema::AddTemplateConversionCandidate( - FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingDC, Expr *From, QualType ToType, - OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion) { +void +Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingDC, + Expr *From, QualType ToType, + OverloadCandidateSet &CandidateSet, + bool AllowObjCConversionOnExplicit, + bool AllowResultConversion) { assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) && "Only conversion function templates permitted here"); @@ -7149,7 +7137,7 @@ void Sema::AddTemplateConversionCandidate( assert(Specialization && "Missing function template specialization?"); AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType, CandidateSet, AllowObjCConversionOnExplicit, - AllowExplicit, AllowResultConversion); + AllowResultConversion); } /// AddSurrogateCandidate - Adds a "surrogate" candidate function that @@ -9003,14 +8991,12 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, /*SupressUserConversions=*/false, PartialOverloading, - /*AllowExplicitConversions*/ false, - /*AllowExplicit*/ false, ADLCallKind::UsesADL); + /*AllowExplicit=*/false, ADLCallKind::UsesADL); } else { - AddTemplateOverloadCandidate( - cast<FunctionTemplateDecl>(*I), FoundDecl, ExplicitTemplateArgs, Args, - CandidateSet, - /*SupressUserConversions=*/false, PartialOverloading, - /*AllowExplicit*/ false, ADLCallKind::UsesADL); + AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl, + ExplicitTemplateArgs, Args, CandidateSet, + /*SupressUserConversions=*/false, + PartialOverloading, ADLCallKind::UsesADL); } } } @@ -10341,33 +10327,6 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) { << Attr->getCond()->getSourceRange() << Attr->getMessage(); } -static void DiagnoseFailedExplicitSpec(Sema &S, OverloadCandidate *Cand) { - ExplicitSpecifier ES; - const char *DeclName; - switch (Cand->Function->getDeclKind()) { - case Decl::Kind::CXXConstructor: - ES = cast<CXXConstructorDecl>(Cand->Function)->getExplicitSpecifier(); - DeclName = "constructor"; - break; - case Decl::Kind::CXXConversion: - ES = cast<CXXConversionDecl>(Cand->Function)->getExplicitSpecifier(); - DeclName = "conversion operator"; - break; - case Decl::Kind::CXXDeductionGuide: - ES = cast<CXXDeductionGuideDecl>(Cand->Function)->getExplicitSpecifier(); - DeclName = "deductiong guide"; - break; - default: - llvm_unreachable("invalid Decl"); - } - assert(ES.getExpr() && "null expression should be handled before"); - S.Diag(Cand->Function->getLocation(), - diag::note_ovl_candidate_explicit_forbidden) - << DeclName; - S.Diag(ES.getExpr()->getBeginLoc(), - diag::note_explicit_bool_resolved_to_true); -} - static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) { FunctionDecl *Callee = Cand->Function; @@ -10452,9 +10411,6 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_enable_if: return DiagnoseFailedEnableIfAttr(S, Cand); - case ovl_fail_explicit_resolved: - return DiagnoseFailedExplicitSpec(S, Cand); - case ovl_fail_ext_disabled: return DiagnoseOpenCLExtensionDisabled(S, Cand); @@ -13025,11 +12981,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Microsoft supports direct constructor calls. if (getLangOpts().MicrosoftExt && isa<CXXConstructorDecl>(Func)) { - AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, - CandidateSet, - /*SuppressUserConversions*/ false, - /*PartialOverloading*/ false, - /*AllowExplicit*/ true); + AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), + Args, CandidateSet); } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) { // If explicit template arguments were provided, we can't call a // non-template member function. |