summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/DeclCXX.h18
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td7
-rw-r--r--clang/include/clang/Sema/Overload.h7
-rw-r--r--clang/lib/Sema/SemaInit.cpp55
-rw-r--r--clang/lib/Sema/SemaOverload.cpp188
-rw-r--r--clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp2
-rw-r--r--clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp2
-rw-r--r--clang/test/CXX/dcl.decl/dcl.init/p14-0x.cpp2
-rw-r--r--clang/test/CXX/drs/dr15xx.cpp2
-rw-r--r--clang/test/CXX/drs/dr1xx.cpp2
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp2
-rw-r--r--clang/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp6
-rw-r--r--clang/test/CXX/special/class.inhctor/p3.cpp2
-rw-r--r--clang/test/PCH/cxx-explicit-specifier.cpp12
-rw-r--r--clang/test/SemaCXX/conversion-function.cpp2
-rw-r--r--clang/test/SemaCXX/convert-to-bool.cpp8
-rw-r--r--clang/test/SemaCXX/converting-constructor.cpp2
-rw-r--r--clang/test/SemaCXX/copy-initialization.cpp4
-rw-r--r--clang/test/SemaCXX/cxx2a-explicit-bool.cpp43
-rw-r--r--clang/test/SemaCXX/default1.cpp2
-rw-r--r--clang/test/SemaCXX/explicit.cpp8
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;
OpenPOWER on IntegriCloud