diff options
21 files changed, 204 insertions, 172 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index aba33e38397..73b4fb94a49 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1783,7 +1783,7 @@ public: }; /// Store information needed for an explicit specifier. -/// used by CXXDeductionGuideDecl, CXXConstructorDecl and CXXConversionDecl. +/// Used by CXXDeductionGuideDecl, CXXConstructorDecl and CXXConversionDecl. class ExplicitSpecifier { llvm::PointerIntPair<Expr *, 2, ExplicitSpecKind> ExplicitSpec{ nullptr, ExplicitSpecKind::ResolvedFalse}; @@ -1796,20 +1796,22 @@ public: const Expr *getExpr() const { return ExplicitSpec.getPointer(); } Expr *getExpr() { return ExplicitSpec.getPointer(); } - /// Return true if the ExplicitSpecifier isn't defaulted. + /// Determine if the declaration had an explicit specifier of any kind. bool isSpecified() const { return ExplicitSpec.getInt() != ExplicitSpecKind::ResolvedFalse || ExplicitSpec.getPointer(); } - /// Check for Equivalence of explicit specifiers. - /// Return True if the explicit specifier are equivalent false otherwise. + /// Check for equivalence of explicit specifiers. + /// \return true if the explicit specifier are equivalent, false otherwise. bool isEquivalent(const ExplicitSpecifier Other) const; - /// Return true if the explicit specifier is already resolved to be explicit. + /// Determine whether this specifier is known to correspond to an explicit + /// declaration. Returns false if the specifier is absent or has an + /// expression that is value-dependent or evaluates to false. bool isExplicit() const { return ExplicitSpec.getInt() == ExplicitSpecKind::ResolvedTrue; } - /// Return true if the ExplicitSpecifier isn't valid. + /// Determine if the explicit specifier is invalid. /// This state occurs after a substitution failures. bool isInvalid() const { return ExplicitSpec.getInt() == ExplicitSpecKind::Unresolved && @@ -1817,9 +1819,7 @@ public: } void setKind(ExplicitSpecKind Kind) { ExplicitSpec.setInt(Kind); } void setExpr(Expr *E) { ExplicitSpec.setPointer(E); } - // getFromDecl - retrieve the explicit specifier in the given declaration. - // if the given declaration has no explicit. the returned explicit specifier - // is defaulted. .isSpecified() will be false. + // Retrieve the explicit specifier in the given declaration, if any. static ExplicitSpecifier getFromDecl(FunctionDecl *Function); static const ExplicitSpecifier getFromDecl(const FunctionDecl *Function) { return getFromDecl(const_cast<FunctionDecl *>(Function)); diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e71bddc06b5..53d4571fa8a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3871,10 +3871,9 @@ def note_ovl_candidate : Note< "| has different qualifiers (expected %5 but found %6)" "| has different exception specification}4">; -def note_ovl_candidate_explicit_forbidden : Note< - "candidate %0 ignored: cannot be explicit">; -def note_explicit_bool_resolved_to_true : Note< - "explicit(bool) specifier resolved to true">; +def note_ovl_candidate_explicit : Note< + "explicit %select{constructor|conversion function|deduction guide}0 " + "is not a candidate%select{| (explicit specifier evaluates to true)}1">; def note_ovl_candidate_inherited_constructor : Note< "constructor from base class %0 inherited here">; def note_ovl_candidate_inherited_constructor_slice : Note< diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 0ccb658c6a7..1394c623696 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -732,10 +732,9 @@ class Sema; /// attribute disabled it. ovl_fail_enable_if, - /// This candidate constructor or conversion fonction - /// is used implicitly but the explicit(bool) specifier - /// was resolved to true - ovl_fail_explicit_resolved, + /// This candidate constructor or conversion function is explicit but + /// the context doesn't permit explicit functions. + ovl_fail_explicit, /// This candidate was not viable because its address could not be taken. ovl_fail_addr_not_available, diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 94d524a63f5..d89d37d8499 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3877,9 +3877,6 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, if (!Info.Constructor || Info.Constructor->isInvalidDecl()) continue; - if (!AllowExplicit && Info.Constructor->isExplicit()) - continue; - if (OnlyListConstructors && !S.isInitListConstructor(Info.Constructor)) continue; @@ -3951,18 +3948,16 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, else Conv = cast<CXXConversionDecl>(D); - if (AllowExplicit || !Conv->isExplicit()) { - if (ConvTemplate) - S.AddTemplateConversionCandidate( - ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, - CandidateSet, AllowExplicit, AllowExplicit, - /*AllowResultConversion*/ false); - else - S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, - DestType, CandidateSet, AllowExplicit, - AllowExplicit, - /*AllowResultConversion*/ false); - } + if (ConvTemplate) + S.AddTemplateConversionCandidate( + ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, + CandidateSet, AllowExplicit, AllowExplicit, + /*AllowResultConversion*/ false); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, + DestType, CandidateSet, AllowExplicit, + AllowExplicit, + /*AllowResultConversion*/ false); } } } @@ -4495,7 +4490,7 @@ static OverloadingResult TryRefInitWithConversionFunction( continue; if (!Info.Constructor->isInvalidDecl() && - Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) { + Info.Constructor->isConvertingConstructor(/*AllowExplicit*/true)) { if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate( Info.ConstructorTmpl, Info.FoundDecl, @@ -4540,8 +4535,7 @@ static OverloadingResult TryRefInitWithConversionFunction( // FIXME: Do we need to make sure that we only consider conversion // candidates with reference-compatible results? That might be needed to // break recursion. - if ((AllowExplicitConvs || !Conv->isExplicit()) && - (AllowRValues || + if ((AllowRValues || Conv->getConversionType()->isLValueReferenceType())) { if (ConvTemplate) S.AddTemplateConversionCandidate( @@ -5153,7 +5147,7 @@ static void TryUserDefinedConversion(Sema &S, continue; if (!Info.Constructor->isInvalidDecl() && - Info.Constructor->isConvertingConstructor(AllowExplicit)) { + Info.Constructor->isConvertingConstructor(/*AllowExplicit*/true)) { if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate( Info.ConstructorTmpl, Info.FoundDecl, @@ -5197,16 +5191,14 @@ static void TryUserDefinedConversion(Sema &S, else Conv = cast<CXXConversionDecl>(D); - if (AllowExplicit || !Conv->isExplicit()) { - if (ConvTemplate) - S.AddTemplateConversionCandidate( - ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, - CandidateSet, AllowExplicit, AllowExplicit); - else - S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, - DestType, CandidateSet, AllowExplicit, - AllowExplicit); - } + if (ConvTemplate) + S.AddTemplateConversionCandidate( + ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, + CandidateSet, AllowExplicit, AllowExplicit); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, + DestType, CandidateSet, AllowExplicit, + AllowExplicit); } } } @@ -9778,9 +9770,8 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( // C++ [over.match.copy]p1: (non-list copy-initialization from class) // The converting constructors of T are candidate functions. if (!AllowExplicit) { - // Only consider converting constructors. - if (GD->isExplicit()) - continue; + // Overload resolution checks whether the deduction guide is declared + // explicit for us. // When looking for a converting constructor, deduction guides that // could never be called with one argument are not interesting to diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index fa811ee2bd2..69609986be4 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3320,8 +3320,7 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, continue; bool Usable = !Info.Constructor->isInvalidDecl() && - S.isInitListConstructor(Info.Constructor) && - (AllowExplicit || !Info.Constructor->isExplicit()); + S.isInitListConstructor(Info.Constructor); if (Usable) { // If the first argument is (a reference to) the target type, // suppress conversions. @@ -3443,11 +3442,9 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, continue; bool Usable = !Info.Constructor->isInvalidDecl(); - if (ListInitializing) - Usable = Usable && (AllowExplicit || !Info.Constructor->isExplicit()); - else - Usable = Usable && - Info.Constructor->isConvertingConstructor(AllowExplicit); + if (!ListInitializing) + Usable = Usable && Info.Constructor->isConvertingConstructor( + /*AllowExplicit*/ true); if (Usable) { bool SuppressUserConversions = !ConstructorsOnly; if (SuppressUserConversions && ListInitializing) { @@ -3501,16 +3498,14 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, else Conv = cast<CXXConversionDecl>(D); - if (AllowExplicit || !Conv->isExplicit()) { - if (ConvTemplate) - S.AddTemplateConversionCandidate( - ConvTemplate, FoundDecl, ActingContext, From, ToType, - CandidateSet, AllowObjCConversionOnExplicit, AllowExplicit); - else - S.AddConversionCandidate( - Conv, FoundDecl, ActingContext, From, ToType, CandidateSet, - AllowObjCConversionOnExplicit, AllowExplicit); - } + if (ConvTemplate) + S.AddTemplateConversionCandidate( + ConvTemplate, FoundDecl, ActingContext, From, ToType, + CandidateSet, AllowObjCConversionOnExplicit, AllowExplicit); + else + S.AddConversionCandidate( + Conv, FoundDecl, ActingContext, From, ToType, CandidateSet, + AllowObjCConversionOnExplicit, AllowExplicit); } } } @@ -4543,11 +4538,6 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, else Conv = cast<CXXConversionDecl>(D); - // If this is an explicit conversion, and we're not allowed to consider - // explicit conversions, skip it. - if (!AllowExplicit && Conv->isExplicit()) - continue; - if (AllowRvalues) { // If we are initializing an rvalue reference, don't permit conversion // functions that return lvalues. @@ -6183,6 +6173,15 @@ void Sema::AddOverloadCandidate( Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); + // Explicit functions are not actually candidates at all if we're not + // allowing them in this context, but keep them around so we can point + // to them in diagnostics. + if (!AllowExplicit && ExplicitSpecifier::getFromDecl(Function).isExplicit()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_explicit; + return; + } + if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() && !Function->getAttr<TargetAttr>()->isDefaultVersion()) { Candidate.Viable = false; @@ -6316,15 +6315,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; @@ -6923,6 +6913,12 @@ void Sema::AddMethodTemplateCandidate( Conversions, PO); } +/// Determine whether a given function template has a simple explicit specifier +/// or a non-value-dependent explicit-specification that evaluates to true. +static bool isNonDependentlyExplicit(FunctionTemplateDecl *FTD) { + return ExplicitSpecifier::getFromDecl(FTD->getTemplatedDecl()).isExplicit(); +} + /// Add a C++ function template specialization as a candidate /// in the candidate set, using template argument deduction to produce /// an appropriate function template specialization. @@ -6935,6 +6931,18 @@ void Sema::AddTemplateOverloadCandidate( if (!CandidateSet.isNewCandidate(FunctionTemplate, PO)) return; + // If the function template has a non-dependent explicit specification, + // exclude it now if appropriate; we are not permitted to perform deduction + // and substitution in this case. + if (!AllowExplicit && isNonDependentlyExplicit(FunctionTemplate)) { + OverloadCandidate &Candidate = CandidateSet.addCandidate(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = FunctionTemplate->getTemplatedDecl(); + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_explicit; + return; + } + // C++ [over.match.funcs]p7: // In each case where a candidate is a function template, candidate // function template specializations are generated using template argument @@ -7122,6 +7130,9 @@ void Sema::AddConversionCandidate( // Per C++ [over.match.conv]p1, [over.match.ref]p1, an explicit conversion // operator is only a candidate if its return type is the target type or // can be converted to the target type with a qualification conversion. + // + // FIXME: Include such functions in the candidate list and explain why we + // can't select them. if (Conversion->isExplicit() && !isAllowableExplicitConversion(*this, ConvType, ToType, AllowObjCConversionOnExplicit)) @@ -7143,6 +7154,15 @@ void Sema::AddConversionCandidate( Candidate.Viable = true; Candidate.ExplicitCallArguments = 1; + // Explicit functions are not actually candidates at all if we're not + // allowing them in this context, but keep them around so we can point + // to them in diagnostics. + if (!AllowExplicit && Conversion->isExplicit()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_explicit; + return; + } + // C++ [over.match.funcs]p4: // For conversion functions, the function is considered to be a member of // the class of the implicit implied object argument for the purpose of @@ -7267,13 +7287,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; @@ -7304,6 +7317,18 @@ void Sema::AddTemplateConversionCandidate( if (!CandidateSet.isNewCandidate(FunctionTemplate)) return; + // If the function template has a non-dependent explicit specification, + // exclude it now if appropriate; we are not permitted to perform deduction + // and substitution in this case. + if (!AllowExplicit && isNonDependentlyExplicit(FunctionTemplate)) { + OverloadCandidate &Candidate = CandidateSet.addCandidate(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = FunctionTemplate->getTemplatedDecl(); + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_explicit; + return; + } + TemplateDeductionInfo Info(CandidateSet.getLocation()); CXXConversionDecl *Specialization = nullptr; if (TemplateDeductionResult Result @@ -10764,30 +10789,36 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) { } static void DiagnoseFailedExplicitSpec(Sema &S, OverloadCandidate *Cand) { - ExplicitSpecifier ES; - const char *DeclName; + ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(Cand->Function); + assert(ES.isExplicit() && "not an explicit candidate"); + + unsigned Kind; switch (Cand->Function->getDeclKind()) { case Decl::Kind::CXXConstructor: - ES = cast<CXXConstructorDecl>(Cand->Function)->getExplicitSpecifier(); - DeclName = "constructor"; + Kind = 0; break; case Decl::Kind::CXXConversion: - ES = cast<CXXConversionDecl>(Cand->Function)->getExplicitSpecifier(); - DeclName = "conversion operator"; + Kind = 1; break; case Decl::Kind::CXXDeductionGuide: - ES = cast<CXXDeductionGuideDecl>(Cand->Function)->getExplicitSpecifier(); - DeclName = "deductiong guide"; + Kind = Cand->Function->isImplicit() ? 0 : 2; 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); + + // Note the location of the first (in-class) declaration; a redeclaration + // (particularly an out-of-class definition) will typically lack the + // 'explicit' specifier. + // FIXME: This is probably a good thing to do for all 'candidate' notes. + FunctionDecl *First = Cand->Function->getFirstDecl(); + if (FunctionDecl *Pattern = First->getTemplateInstantiationPattern()) + First = Pattern->getFirstDecl(); + + S.Diag(First->getLocation(), + diag::note_ovl_candidate_explicit) + << Kind << (ES.getExpr() ? 1 : 0) + << (ES.getExpr() ? ES.getExpr()->getSourceRange() : SourceRange()); } static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) { @@ -10888,7 +10919,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_enable_if: return DiagnoseFailedEnableIfAttr(S, Cand); - case ovl_fail_explicit_resolved: + case ovl_fail_explicit: return DiagnoseFailedExplicitSpec(S, Cand); case ovl_fail_ext_disabled: @@ -11053,6 +11084,23 @@ struct CompareOverloadCandidatesForDisplay { OverloadCandidateSet::CandidateSetKind CSK) : S(S), NumArgs(NArgs), CSK(CSK) {} + OverloadFailureKind EffectiveFailureKind(const OverloadCandidate *C) const { + // If there are too many or too few arguments, that's the high-order bit we + // want to sort by, even if the immediate failure kind was something else. + if (C->FailureKind == ovl_fail_too_many_arguments || + C->FailureKind == ovl_fail_too_few_arguments) + return static_cast<OverloadFailureKind>(C->FailureKind); + + if (C->Function) { + if (NumArgs > C->Function->getNumParams() && !C->Function->isVariadic()) + return ovl_fail_too_many_arguments; + if (NumArgs < C->Function->getMinRequiredArguments()) + return ovl_fail_too_few_arguments; + } + + return static_cast<OverloadFailureKind>(C->FailureKind); + } + bool operator()(const OverloadCandidate *L, const OverloadCandidate *R) { // Fast-path this check. @@ -11076,34 +11124,37 @@ struct CompareOverloadCandidatesForDisplay { // Criteria by which we can sort non-viable candidates: if (!L->Viable) { + OverloadFailureKind LFailureKind = EffectiveFailureKind(L); + OverloadFailureKind RFailureKind = EffectiveFailureKind(R); + // 1. Arity mismatches come after other candidates. - if (L->FailureKind == ovl_fail_too_many_arguments || - L->FailureKind == ovl_fail_too_few_arguments) { - if (R->FailureKind == ovl_fail_too_many_arguments || - R->FailureKind == ovl_fail_too_few_arguments) { + if (LFailureKind == ovl_fail_too_many_arguments || + LFailureKind == ovl_fail_too_few_arguments) { + if (RFailureKind == ovl_fail_too_many_arguments || + RFailureKind == ovl_fail_too_few_arguments) { int LDist = std::abs((int)L->getNumParams() - (int)NumArgs); int RDist = std::abs((int)R->getNumParams() - (int)NumArgs); if (LDist == RDist) { - if (L->FailureKind == R->FailureKind) + if (LFailureKind == RFailureKind) // Sort non-surrogates before surrogates. return !L->IsSurrogate && R->IsSurrogate; // Sort candidates requiring fewer parameters than there were // arguments given after candidates requiring more parameters // than there were arguments given. - return L->FailureKind == ovl_fail_too_many_arguments; + return LFailureKind == ovl_fail_too_many_arguments; } return LDist < RDist; } return false; } - if (R->FailureKind == ovl_fail_too_many_arguments || - R->FailureKind == ovl_fail_too_few_arguments) + if (RFailureKind == ovl_fail_too_many_arguments || + RFailureKind == ovl_fail_too_few_arguments) return true; // 2. Bad conversions come first and are ordered by the number // of bad conversions and quality of good conversions. - if (L->FailureKind == ovl_fail_bad_conversion) { - if (R->FailureKind != ovl_fail_bad_conversion) + if (LFailureKind == ovl_fail_bad_conversion) { + if (RFailureKind != ovl_fail_bad_conversion) return true; // The conversion that can be fixed with a smaller number of changes, @@ -11141,17 +11192,17 @@ struct CompareOverloadCandidatesForDisplay { if (leftBetter > 0) return true; if (leftBetter < 0) return false; - } else if (R->FailureKind == ovl_fail_bad_conversion) + } else if (RFailureKind == ovl_fail_bad_conversion) return false; - if (L->FailureKind == ovl_fail_bad_deduction) { - if (R->FailureKind != ovl_fail_bad_deduction) + if (LFailureKind == ovl_fail_bad_deduction) { + if (RFailureKind != ovl_fail_bad_deduction) return true; if (L->DeductionFailure.Result != R->DeductionFailure.Result) return RankDeductionFailure(L->DeductionFailure) < RankDeductionFailure(R->DeductionFailure); - } else if (R->FailureKind == ovl_fail_bad_deduction) + } else if (RFailureKind == ovl_fail_bad_deduction) return false; // TODO: others? @@ -11180,7 +11231,8 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, assert(!Cand->Viable); // Don't do anything on failures other than bad conversion. - if (Cand->FailureKind != ovl_fail_bad_conversion) return; + if (Cand->FailureKind != ovl_fail_bad_conversion) + return; // We only want the FixIts if all the arguments can be corrected. bool Unfixable = false; diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp index ed6c6c0bccf..f4e8521093f 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp @@ -38,7 +38,7 @@ namespace Numbers { // expected-note@-2 2 {{candidate constructor (the implicit move constructor) not viable}} #endif - explicit Number(double d) : d(d) {} + explicit Number(double d) : d(d) {} // expected-note 2{{explicit constructor is not a candidate}} double d; }; Number zero(0.0f); diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp index 869fc4f0149..3e8f18c9307 100644 --- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp @@ -65,7 +65,7 @@ namespace test3 { namespace explicit_ctor { struct A {}; struct B { // expected-note 2{{candidate}} - explicit B(const A&); + explicit B(const A&); // expected-note {{explicit constructor is not a candidate}} }; A a; const B &b(a); // expected-error {{no viable conversion}} diff --git a/clang/test/CXX/dcl.decl/dcl.init/p14-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/p14-0x.cpp index 419f2bff128..e7f50135216 100644 --- a/clang/test/CXX/dcl.decl/dcl.init/p14-0x.cpp +++ b/clang/test/CXX/dcl.decl/dcl.init/p14-0x.cpp @@ -5,7 +5,7 @@ struct NoDefault { NoDefault(int); }; struct Explicit { // expected-note 2 {{candidate}} expected-note {{here}} - explicit Explicit(int); + explicit Explicit(int); // expected-note {{not a candidate}} }; struct NoCopy { NoCopy(); diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp index 80a27e7863c..55d838e45a5 100644 --- a/clang/test/CXX/drs/dr15xx.cpp +++ b/clang/test/CXX/drs/dr15xx.cpp @@ -142,7 +142,7 @@ struct Z0 { // expected-note 0+ {{candidate}} }; struct Z { // expected-note 0+ {{candidate}} explicit Z(); // expected-note 0+ {{here}} - explicit Z(int); + explicit Z(int); // expected-note {{not a candidate}} explicit Z(int, int); // expected-note 0+ {{here}} }; template <class T> int Eat(T); // expected-note 0+ {{candidate}} diff --git a/clang/test/CXX/drs/dr1xx.cpp b/clang/test/CXX/drs/dr1xx.cpp index 26ab67d54d3..1e78c03be8a 100644 --- a/clang/test/CXX/drs/dr1xx.cpp +++ b/clang/test/CXX/drs/dr1xx.cpp @@ -600,7 +600,7 @@ namespace dr151 { // dr151: yes namespace dr152 { // dr152: yes struct A { A(); // expected-note 0-2{{not viable}} - explicit A(const A&); + explicit A(const A&); // expected-note 1-2{{not a candidate}} }; A a1 = A(); #if __cplusplus <= 201402L diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp index 63e51a76144..7fd94b658f4 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp @@ -27,7 +27,7 @@ void hiding() { struct ExplicitCopy { ExplicitCopy(); // expected-note 2{{not viable}} - explicit ExplicitCopy(const ExplicitCopy&); + explicit ExplicitCopy(const ExplicitCopy&); // expected-note 2{{not a candidate}} }; auto init_kind_1 = [ec(ExplicitCopy())] {}; auto init_kind_2 = [ec = ExplicitCopy()] {}; // expected-error {{no matching constructor}} diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp index 31a679f1ebc..c63f3097153 100644 --- a/clang/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp +++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp @@ -4,7 +4,7 @@ namespace ExplicitConv { struct X { }; // expected-note 2{{candidate constructor}} struct Y { - explicit operator X() const; + explicit operator X() const; // expected-note {{not a candidate}} }; void test(const Y& y) { @@ -18,8 +18,8 @@ namespace DR899 { struct C { }; // expected-note 2 {{candidate constructor}} struct A { - explicit operator int() const; - explicit operator C() const; + explicit operator int() const; // expected-note {{not a candidate}} + explicit operator C() const; // expected-note {{not a candidate}} }; struct B { diff --git a/clang/test/CXX/special/class.inhctor/p3.cpp b/clang/test/CXX/special/class.inhctor/p3.cpp index 19f15ebe0f0..9d50e0c05ce 100644 --- a/clang/test/CXX/special/class.inhctor/p3.cpp +++ b/clang/test/CXX/special/class.inhctor/p3.cpp @@ -15,7 +15,7 @@ D1 d1a(1), d1b(1, 1); D1 fd1() { return 1; } struct B2 { - explicit B2(int, int = 0, int = 0); + explicit B2(int, int = 0, int = 0); // expected-note {{not a candidate}} }; struct D2 : B2 { // expected-note 2{{candidate constructor}} using B2::B2; diff --git a/clang/test/PCH/cxx-explicit-specifier.cpp b/clang/test/PCH/cxx-explicit-specifier.cpp index a800cfc9d50..9c7b0560e5b 100644 --- a/clang/test/PCH/cxx-explicit-specifier.cpp +++ b/clang/test/PCH/cxx-explicit-specifier.cpp @@ -40,7 +40,9 @@ struct A { #else //expected-note@-6+ {{candidate constructor}} //expected-note@-9+ {{candidate constructor}} -//expected-note@-6+ {{candidate function}} +//expected-note-re@-7+ {{explicit constructor is not a candidate{{$}}}} +//expected-note@-7+ {{candidate function}} +//expected-note@-7+ {{explicit conversion function is not a candidate (explicit specifier evaluates to true)}} //CHECK: explicit{{ +}}A( //CHECK-NEXT: explicit(false){{ +}}operator @@ -73,12 +75,10 @@ B<true> b_true; B<false> b_false; #else //expected-note@-8 {{candidate template ignored}} -//expected-note@-8+ {{explicit constructor}} +//expected-note@-8 {{explicit constructor declared here}} //expected-note@-15+ {{candidate constructor}} -//expected-note@-8+ {{candidate conversion operator ignored}} -//expected-note@-9+ {{explicit(bool) specifier resolved to true}} -//expected-note@-12 {{explicit(bool) specifier resolved to true}} -//expected-note@-13+ {{candidate deductiong guide ignored}} +//expected-note@-8+ {{explicit conversion function is not a candidate (explicit specifier}} +//expected-note@-11 {{explicit constructor is not a candidate (explicit specifier}} //CHECK: explicit(b){{ +}}A //CHECK: explicit(b{{ +}}^{{ +}}T::value){{ +}}operator diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp index 1d3593d8ed1..1486abea8c6 100644 --- a/clang/test/SemaCXX/conversion-function.cpp +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -211,7 +211,7 @@ namespace smart_ptr { // expected-note@-2 {{candidate constructor (the implicit move constructor) not}} #endif - explicit X(Y); + explicit X(Y); // expected-note {{not a candidate}} }; Y make_Y(); diff --git a/clang/test/SemaCXX/convert-to-bool.cpp b/clang/test/SemaCXX/convert-to-bool.cpp index 117b50899b7..94d99414392 100644 --- a/clang/test/SemaCXX/convert-to-bool.cpp +++ b/clang/test/SemaCXX/convert-to-bool.cpp @@ -11,7 +11,7 @@ struct ConvToInt { }; struct ExplicitConvToBool { - explicit operator bool(); + explicit operator bool(); // expected-note {{explicit}} #if __cplusplus <= 199711L // C++03 or earlier modes // expected-warning@-2{{explicit conversion functions are a C++11 extension}} #endif @@ -45,7 +45,7 @@ void test_conv_to_bool(ConvToBool ctb, ConvToInt cti, ExplicitConvToBool ecb) { void accepts_bool(bool) { } // expected-note{{candidate function}} struct ExplicitConvToRef { - explicit operator int&(); + explicit operator int&(); // expected-note {{explicit}} #if (__cplusplus <= 199711L) // C++03 or earlier modes // expected-warning@-2{{explicit conversion functions are a C++11 extension}} #endif @@ -58,14 +58,14 @@ void test_explicit_bool(ExplicitConvToBool ecb) { } void test_explicit_conv_to_ref(ExplicitConvToRef ecr) { - int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'ExplicitConvToRef'}} + int& i1 = ecr; // expected-error{{no viable conversion from 'ExplicitConvToRef' to 'int'}} int& i2(ecr); // okay } struct A { }; struct B { }; struct C { - explicit operator A&(); + explicit operator A&(); // expected-note {{explicit}} #if __cplusplus <= 199711L // C++03 or earlier modes // expected-warning@-2{{explicit conversion functions are a C++11 extension}} #endif diff --git a/clang/test/SemaCXX/converting-constructor.cpp b/clang/test/SemaCXX/converting-constructor.cpp index 75002fa585b..d66e09e9c4b 100644 --- a/clang/test/SemaCXX/converting-constructor.cpp +++ b/clang/test/SemaCXX/converting-constructor.cpp @@ -36,7 +36,7 @@ class FromShortExplicitly { // expected-note{{candidate constructor (the implici #endif public: - explicit FromShortExplicitly(short s); + explicit FromShortExplicitly(short s); // expected-note {{explicit constructor is not a candidate}} }; void explicit_constructor(short s) { diff --git a/clang/test/SemaCXX/copy-initialization.cpp b/clang/test/SemaCXX/copy-initialization.cpp index 8866fe70db8..29c91ba8563 100644 --- a/clang/test/SemaCXX/copy-initialization.cpp +++ b/clang/test/SemaCXX/copy-initialization.cpp @@ -4,9 +4,9 @@ class X { public: - explicit X(const X&); + explicit X(const X&); // expected-note 2{{not a candidate}} X(int*); // expected-note 3{{candidate constructor}} - explicit X(float*); // expected-note {{candidate constructor}} + explicit X(float*); // expected-note {{candidate constructor}} expected-note 2{{not a candidate}} }; class Y : public X { }; diff --git a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp index 56fa76f0a8b..df776b39054 100644 --- a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp +++ b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp @@ -55,8 +55,8 @@ template<int a> // expected-note@-1 {{candidate constructor}} expected-note@-1 {{candidate constructor}} // expected-note@-2 {{candidate constructor}} expected-note@-2 {{candidate constructor}} explicit(a == 0) -C(int), -C(double); +C(int), // expected-note 2{{not a candidate}} +C(double); // expected-note 2{{not a candidate}} }; C<0> c0 = 0.0; // expected-error {{no viable conversion}} @@ -105,7 +105,7 @@ template<bool b> struct A { // expected-note@-1+ {{candidate constructor}} // expected-note@-2+ {{candidate function}} - explicit(b) A(int, int = 0); + explicit(b) A(int, int = 0); // expected-note {{not a candidate}} // expected-note@-1+ {{explicit constructor declared here}} }; @@ -154,10 +154,9 @@ struct A { // expected-note@-2 {{candidate constructor}} expected-note@-2 {{candidate constructor}} template<typename T2> explicit(a ^ is_same<T1, T2>::value) - // expected-note@-1+ {{explicit(bool) specifier resolved to true}} A(T2) {} // expected-note@-1+ {{explicit constructor declared here}} - // expected-note@-2+ {{candidate constructor ignored}} + // expected-note@-2+ {{not a candidate}} }; A<true, int> a0 = 0.0; // expected-error {{no viable conversion}} @@ -196,17 +195,15 @@ struct A { // expected-note@-1+ {{candidate constructor}} template<typename T> explicit(enable_ifv<is_same<int, T>::value, a>::value) - //expected-note@-1 {{explicit(bool) specifier resolved to true}} A(T) {} // expected-note@-1+ {{substitution failure}} - // expected-note@-2 {{candidate constructor ignored}} + // expected-note@-2 {{not a candidate}} // expected-note@-3 {{explicit constructor declared here}} template<typename T, bool c = true> explicit(enable_ifv<is_same<bool, T>::value, a>::value) - //expected-note@-1 {{explicit(bool) specifier resolved to true}} A(T) {} // expected-note@-1+ {{substitution failure}} - // expected-note@-2 {{candidate constructor ignored}} + // expected-note@-2 {{not a candidate}} // expected-note@-3 {{explicit constructor declared here}} }; @@ -236,7 +233,7 @@ namespace conversion { template<bool a> struct A { - explicit(a) operator int (); + explicit(a) operator int (); // expected-note+ {{not a candidate}} }; template<bool a> @@ -293,10 +290,9 @@ template<bool a> struct A { template<typename T2> explicit(enable_ifv<is_same<B, T2>::value, a>::value) - // expected-note@-1+ {{explicit(bool) specifier resolved to true}} operator T2() { return T2(); }; // expected-note@-1+ {{substitution failure}} - // expected-note@-2+ {{candidate conversion}} + // expected-note@-2+ {{not a candidate}} }; A<false> A_false; @@ -348,9 +344,8 @@ struct A { // expected-note@-2+ {{candidate function}} template<typename ... Ts> explicit((is_same<T, Ts>::value && ...)) - // expected-note@-1 {{explicit(bool) specifier resolved to true}} A(Ts...); - // expected-note@-1 {{candidate constructor}} + // expected-note@-1 {{not a candidate}} // expected-note@-2 {{explicit constructor}} }; @@ -517,8 +512,8 @@ class Y { }; // expected-note+ {{candidate constructor (the implicit}} template<bool b> struct Z { explicit(b) operator X() const; - explicit(b) operator Y() const; - explicit(b) operator int() const; + explicit(b) operator Y() const; // expected-note 2{{not a candidate}} + explicit(b) operator int() const; // expected-note {{not a candidate}} }; void testExplicit() @@ -559,9 +554,7 @@ template<typename T1> struct C { template<typename T> explicit(!is_same<T1, T>::value) - // expected-note@-1+ {{explicit(bool) specifier resolved to true}} - operator T(); - // expected-note@-1+ {{candidate conversion operator ignored}} + operator T(); // expected-note+ {{explicit conversion function is not a candidate}} }; using Bool = C<bool>; @@ -684,10 +677,9 @@ template<typename T1 = int, typename T2 = int> struct A { // expected-note@-1+ {{candidate template ignored}} explicit(!is_same<T1, T2>::value) - // expected-note@-1+ {{explicit(bool) specifier resolved to true}} A(T1 = 0, T2 = 0) {} - // expected-note@-1 {{explicit constructor}} - // expected-note@-2+ {{candidate deductiong guide ignored}} + // expected-note@-1 {{explicit constructor declared here}} + // expected-note@-2 2{{explicit constructor is not a candidate}} }; A a0 = 0; @@ -723,15 +715,14 @@ using size_t = decltype(sizeof(0)); struct Str {// expected-note+ {{candidate constructor}} template <size_t N> - explicit(N > 7)// expected-note {{resolved to true}} - Str(char const (&str)[N]); + explicit(N > 7) + Str(char const (&str)[N]); // expected-note {{explicit constructor is not a candidate}} }; template <size_t N> Str::Str(char const(&str)[N]) { } -// expected-note@-1 {{candidate constructor}} Str a = "short"; Str b = "not so short";// expected-error {{no viable conversion}} -}
\ No newline at end of file +} diff --git a/clang/test/SemaCXX/default1.cpp b/clang/test/SemaCXX/default1.cpp index 3bc6f832b68..457cada13bd 100644 --- a/clang/test/SemaCXX/default1.cpp +++ b/clang/test/SemaCXX/default1.cpp @@ -31,7 +31,7 @@ struct Y { // expected-note 2{{candidate constructor (the implicit copy construc // expected-note@-2 2 {{candidate constructor (the implicit move constructor) not viable}} #endif - explicit Y(int); + explicit Y(int); // expected-note 2{{explicit constructor is not a candidate}} }; void k(Y y = 17); // expected-error{{no viable conversion}} \ diff --git a/clang/test/SemaCXX/explicit.cpp b/clang/test/SemaCXX/explicit.cpp index 58760d347f0..ba2c36d99da 100644 --- a/clang/test/SemaCXX/explicit.cpp +++ b/clang/test/SemaCXX/explicit.cpp @@ -7,7 +7,7 @@ struct A { }; struct B { // expected-note+ {{candidate}} - explicit B(int); + explicit B(int); // expected-note {{not a candidate}} }; B::B(int) { } // expected-note+ {{here}} @@ -78,8 +78,8 @@ namespace Conversion { struct Z { explicit operator X() const; - explicit operator Y() const; - explicit operator int() const; + explicit operator Y() const; // expected-note 2{{not a candidate}} + explicit operator int() const; // expected-note {{not a candidate}} }; Z z; @@ -118,7 +118,7 @@ namespace Conversion { }; struct NotBool { - explicit operator bool(); // expected-note {{conversion to integral type 'bool'}} + explicit operator bool(); // expected-note {{conversion to integral type 'bool'}} expected-note 4{{explicit conversion function is not a candidate}} }; Bool b; NotBool n; |