summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:44:14 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:44:14 +0000
commit2b6b257f4e5503a7a2675bdb8735693db769f75c (patch)
treee85e046ae7003fe3bcc8b5454cd0fa3f7407b470 /lib/Sema/SemaOverload.cpp
parentb4348ed0b7e90c0831b925fbee00b5f179a99796 (diff)
Notes
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r--lib/Sema/SemaOverload.cpp648
1 files changed, 414 insertions, 234 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index d6a0ff7dc3d15..b025a397edca0 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -39,8 +39,8 @@ using namespace clang;
using namespace sema;
static bool functionHasPassObjectSizeParams(const FunctionDecl *FD) {
- return std::any_of(FD->param_begin(), FD->param_end(),
- std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
+ return llvm::any_of(FD->parameters(),
+ std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
}
/// A convenience routine for creating a decayed reference to a function.
@@ -293,6 +293,13 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
// A narrowing conversion is an implicit conversion ...
QualType FromType = getToType(0);
QualType ToType = getToType(1);
+
+ // A conversion to an enumeration type is narrowing if the conversion to
+ // the underlying type is narrowing. This only arises for expressions of
+ // the form 'Enum{init}'.
+ if (auto *ET = ToType->getAs<EnumType>())
+ ToType = ET->getDecl()->getIntegerType();
+
switch (Second) {
// 'bool' is an integral type; dispatch to the right place to handle it.
case ICK_Boolean_Conversion:
@@ -433,7 +440,7 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
/// dump - Print this standard conversion sequence to standard
/// error. Useful for debugging overloading issues.
-void StandardConversionSequence::dump() const {
+LLVM_DUMP_METHOD void StandardConversionSequence::dump() const {
raw_ostream &OS = llvm::errs();
bool PrintedSomething = false;
if (First != ICK_Identity) {
@@ -985,7 +992,7 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
}
bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
- bool UseUsingDeclRules) {
+ bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs) {
// C++ [basic.start.main]p2: This function shall not be overloaded.
if (New->isMain())
return false;
@@ -1041,7 +1048,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
//
// However, we don't consider either of these when deciding whether
// a member introduced by a shadow declaration is hidden.
- if (!UseUsingDeclRules && NewTemplate &&
+ if (!UseMemberUsingDeclRules && NewTemplate &&
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
false, TPL_TemplateMatch) ||
@@ -1061,7 +1068,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
if (OldMethod && NewMethod &&
!OldMethod->isStatic() && !NewMethod->isStatic()) {
if (OldMethod->getRefQualifier() != NewMethod->getRefQualifier()) {
- if (!UseUsingDeclRules &&
+ if (!UseMemberUsingDeclRules &&
(OldMethod->getRefQualifier() == RQ_None ||
NewMethod->getRefQualifier() == RQ_None)) {
// C++0x [over.load]p2:
@@ -1118,7 +1125,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return true;
}
- if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads) {
+ if (getLangOpts().CUDA && ConsiderCudaAttrs) {
CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New),
OldTarget = IdentifyCUDATarget(Old);
if (NewTarget == CFT_InvalidTarget || NewTarget == CFT_Global)
@@ -1129,7 +1136,10 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
// Don't allow mixing of HD with other kinds. This guarantees that
// we have only one viable function with this signature on any
// side of CUDA compilation .
- if ((NewTarget == CFT_HostDevice) || (OldTarget == CFT_HostDevice))
+ // __global__ functions can't be overloaded based on attribute
+ // difference because, like HD, they also exist on both sides.
+ if ((NewTarget == CFT_HostDevice) || (OldTarget == CFT_HostDevice) ||
+ (NewTarget == CFT_Global) || (OldTarget == CFT_Global))
return false;
// Allow overloading of functions with same signature, but
@@ -1147,7 +1157,16 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
/// \returns true if \arg FD is unavailable and current context is inside
/// an available function, false otherwise.
bool Sema::isFunctionConsideredUnavailable(FunctionDecl *FD) {
- return FD->isUnavailable() && !cast<Decl>(CurContext)->isUnavailable();
+ if (!FD->isUnavailable())
+ return false;
+
+ // Walk up the context of the caller.
+ Decl *C = cast<Decl>(CurContext);
+ do {
+ if (C->isUnavailable())
+ return false;
+ } while ((C = cast_or_null<Decl>(C->getDeclContext())));
+ return true;
}
/// \brief Tries a user-defined conversion from From to ToType.
@@ -1199,11 +1218,13 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
S.IsDerivedFrom(From->getLocStart(), FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
+ DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction;
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(From->getType());
ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = Constructor;
+ ICS.Standard.FoundCopyConstructor = Found;
if (ToCanon != FromCanon)
ICS.Standard.Second = ICK_Derived_To_Base;
}
@@ -1217,7 +1238,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
for (OverloadCandidateSet::iterator Cand = Conversions.begin();
Cand != Conversions.end(); ++Cand)
if (Cand->Viable)
- ICS.Ambiguous.addConversion(Cand->Function);
+ ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
break;
// Fall through.
@@ -1652,6 +1673,20 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
SCS.Second = ICK_Complex_Real;
FromType = ToType.getUnqualifiedType();
} else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) {
+ // FIXME: disable conversions between long double and __float128 if
+ // their representation is different until there is back end support
+ // We of course allow this conversion if long double is really double.
+ if (&S.Context.getFloatTypeSemantics(FromType) !=
+ &S.Context.getFloatTypeSemantics(ToType)) {
+ bool Float128AndLongDouble = ((FromType == S.Context.Float128Ty &&
+ ToType == S.Context.LongDoubleTy) ||
+ (FromType == S.Context.LongDoubleTy &&
+ ToType == S.Context.Float128Ty));
+ if (Float128AndLongDouble &&
+ (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) !=
+ &llvm::APFloat::IEEEdouble))
+ return false;
+ }
// Floating point conversions (C++ 4.8).
SCS.Second = ICK_Floating_Conversion;
FromType = ToType.getUnqualifiedType();
@@ -1809,8 +1844,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
(FromType->isSignedIntegerType() ||
// We can promote any unsigned integer type whose size is
// less than int to an int.
- (!FromType->isSignedIntegerType() &&
- Context.getTypeSize(FromType) < Context.getTypeSize(ToType)))) {
+ Context.getTypeSize(FromType) < Context.getTypeSize(ToType))) {
return To->getKind() == BuiltinType::Int;
}
@@ -1955,7 +1989,8 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
if (!getLangOpts().CPlusPlus &&
(FromBuiltin->getKind() == BuiltinType::Float ||
FromBuiltin->getKind() == BuiltinType::Double) &&
- (ToBuiltin->getKind() == BuiltinType::LongDouble))
+ (ToBuiltin->getKind() == BuiltinType::LongDouble ||
+ ToBuiltin->getKind() == BuiltinType::Float128))
return true;
// Half can be promoted to float.
@@ -2538,9 +2573,8 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
// Argument types are too different. Abort.
return false;
}
- if (LangOpts.ObjCAutoRefCount &&
- !Context.FunctionTypesMatchOnNSConsumedAttrs(FromFunctionType,
- ToFunctionType))
+ if (!Context.doFunctionTypesMatchOnExtParameterInfos(FromFunctionType,
+ ToFunctionType))
return false;
ConvertedType = ToType;
@@ -2919,6 +2953,10 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
Qualifiers FromQuals = FromType.getQualifiers();
Qualifiers ToQuals = ToType.getQualifiers();
+
+ // Ignore __unaligned qualifier if this type is void.
+ if (ToType.getUnqualifiedType()->isVoidType())
+ FromQuals.removeUnaligned();
// Objective-C ARC:
// Check Objective-C lifetime conversions.
@@ -3015,39 +3053,26 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence &User,
OverloadCandidateSet &CandidateSet,
bool AllowExplicit) {
- DeclContext::lookup_result R = S.LookupConstructors(To);
- for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end();
- Con != ConEnd; ++Con) {
- NamedDecl *D = *Con;
- DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
-
- // Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = nullptr;
- FunctionTemplateDecl *ConstructorTmpl
- = dyn_cast<FunctionTemplateDecl>(D);
- if (ConstructorTmpl)
- Constructor
- = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
- else
- Constructor = cast<CXXConstructorDecl>(D);
+ for (auto *D : S.LookupConstructors(To)) {
+ auto Info = getConstructorInfo(D);
+ if (!Info)
+ continue;
- bool Usable = !Constructor->isInvalidDecl() &&
- S.isInitListConstructor(Constructor) &&
- (AllowExplicit || !Constructor->isExplicit());
+ bool Usable = !Info.Constructor->isInvalidDecl() &&
+ S.isInitListConstructor(Info.Constructor) &&
+ (AllowExplicit || !Info.Constructor->isExplicit());
if (Usable) {
// If the first argument is (a reference to) the target type,
// suppress conversions.
- bool SuppressUserConversions =
- isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType);
- if (ConstructorTmpl)
- S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ nullptr,
- From, CandidateSet,
- SuppressUserConversions);
+ bool SuppressUserConversions = isFirstArgumentCompatibleWithType(
+ S.Context, Info.Constructor, ToType);
+ if (Info.ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
+ /*ExplicitArgs*/ nullptr, From,
+ CandidateSet, SuppressUserConversions);
else
- S.AddOverloadCandidate(Constructor, FoundDecl,
- From, CandidateSet,
- SuppressUserConversions);
+ S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, From,
+ CandidateSet, SuppressUserConversions);
}
}
@@ -3147,27 +3172,17 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
ListInitializing = true;
}
- DeclContext::lookup_result R = S.LookupConstructors(ToRecordDecl);
- for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end();
- Con != ConEnd; ++Con) {
- NamedDecl *D = *Con;
- DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
-
- // Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = nullptr;
- FunctionTemplateDecl *ConstructorTmpl
- = dyn_cast<FunctionTemplateDecl>(D);
- if (ConstructorTmpl)
- Constructor
- = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
- else
- Constructor = cast<CXXConstructorDecl>(D);
+ for (auto *D : S.LookupConstructors(ToRecordDecl)) {
+ auto Info = getConstructorInfo(D);
+ if (!Info)
+ continue;
- bool Usable = !Constructor->isInvalidDecl();
+ bool Usable = !Info.Constructor->isInvalidDecl();
if (ListInitializing)
- Usable = Usable && (AllowExplicit || !Constructor->isExplicit());
+ Usable = Usable && (AllowExplicit || !Info.Constructor->isExplicit());
else
- Usable = Usable &&Constructor->isConvertingConstructor(AllowExplicit);
+ Usable = Usable &&
+ Info.Constructor->isConvertingConstructor(AllowExplicit);
if (Usable) {
bool SuppressUserConversions = !ConstructorsOnly;
if (SuppressUserConversions && ListInitializing) {
@@ -3176,18 +3191,18 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// If the first argument is (a reference to) the target type,
// suppress conversions.
SuppressUserConversions = isFirstArgumentCompatibleWithType(
- S.Context, Constructor, ToType);
+ S.Context, Info.Constructor, ToType);
}
}
- if (ConstructorTmpl)
- S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ nullptr,
- llvm::makeArrayRef(Args, NumArgs),
- CandidateSet, SuppressUserConversions);
+ if (Info.ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(
+ Info.ConstructorTmpl, Info.FoundDecl,
+ /*ExplicitArgs*/ nullptr, llvm::makeArrayRef(Args, NumArgs),
+ CandidateSet, SuppressUserConversions);
else
// Allow one user-defined conversion when user specifies a
// From->ToType conversion via an static cast (c-style, etc).
- S.AddOverloadCandidate(Constructor, FoundDecl,
+ S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions);
}
@@ -4127,6 +4142,10 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
T2Quals.removeObjCLifetime();
}
+ // MS compiler ignores __unaligned qualifier for references; do the same.
+ T1Quals.removeUnaligned();
+ T2Quals.removeUnaligned();
+
if (T1Quals == T2Quals)
return Ref_Compatible;
else if (T1Quals.compatiblyIncludes(T2Quals))
@@ -4248,7 +4267,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
Cand != CandidateSet.end(); ++Cand)
if (Cand->Viable)
- ICS.Ambiguous.addConversion(Cand->Function);
+ ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
return true;
case OR_No_Viable_Function:
@@ -4448,13 +4467,16 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// initialization fails.
//
// Note that we only want to check address spaces and cvr-qualifiers here.
- // ObjC GC and lifetime qualifiers aren't important.
+ // ObjC GC, lifetime and unaligned qualifiers aren't important.
Qualifiers T1Quals = T1.getQualifiers();
Qualifiers T2Quals = T2.getQualifiers();
T1Quals.removeObjCGCAttr();
T1Quals.removeObjCLifetime();
T2Quals.removeObjCGCAttr();
T2Quals.removeObjCLifetime();
+ // MS compiler ignores __unaligned qualifier for references; do the same.
+ T1Quals.removeUnaligned();
+ T2Quals.removeUnaligned();
if (!T1Quals.compatiblyIncludes(T2Quals))
return ICS;
}
@@ -5838,12 +5860,12 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
}
}
-ObjCMethodDecl *Sema::SelectBestMethod(Selector Sel, MultiExprArg Args,
- bool IsInstance) {
- SmallVector<ObjCMethodDecl*, 4> Methods;
- if (!CollectMultipleMethodsInGlobalPool(Sel, Methods, IsInstance))
+ObjCMethodDecl *
+Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance,
+ SmallVectorImpl<ObjCMethodDecl *> &Methods) {
+ if (Methods.size() <= 1)
return nullptr;
-
+
for (unsigned b = 0, e = Methods.size(); b < e; b++) {
bool Match = true;
ObjCMethodDecl *Method = Methods[b];
@@ -5952,37 +5974,28 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
SFINAETrap Trap(*this);
SmallVector<Expr *, 16> ConvertedArgs;
bool InitializationFailed = false;
- bool ContainsValueDependentExpr = false;
// Convert the arguments.
- for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- if (i == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
+ for (unsigned I = 0, E = Args.size(); I != E; ++I) {
+ ExprResult R;
+ if (I == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
!cast<CXXMethodDecl>(Function)->isStatic() &&
!isa<CXXConstructorDecl>(Function)) {
CXXMethodDecl *Method = cast<CXXMethodDecl>(Function);
- ExprResult R =
- PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr,
- Method, Method);
- if (R.isInvalid()) {
- InitializationFailed = true;
- break;
- }
- ContainsValueDependentExpr |= R.get()->isValueDependent();
- ConvertedArgs.push_back(R.get());
+ R = PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr,
+ Method, Method);
} else {
- ExprResult R =
- PerformCopyInitialization(InitializedEntity::InitializeParameter(
- Context,
- Function->getParamDecl(i)),
- SourceLocation(),
- Args[i]);
- if (R.isInvalid()) {
- InitializationFailed = true;
- break;
- }
- ContainsValueDependentExpr |= R.get()->isValueDependent();
- ConvertedArgs.push_back(R.get());
+ R = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context, Function->getParamDecl(I)),
+ SourceLocation(), Args[I]);
}
+
+ if (R.isInvalid()) {
+ InitializationFailed = true;
+ break;
+ }
+
+ ConvertedArgs.push_back(R.get());
}
if (InitializationFailed || Trap.hasErrorOccurred())
@@ -6002,7 +6015,6 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
InitializationFailed = true;
break;
}
- ContainsValueDependentExpr |= R.get()->isValueDependent();
ConvertedArgs.push_back(R.get());
}
@@ -6012,18 +6024,14 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
for (auto *EIA : EnableIfAttrs) {
APValue Result;
- if (EIA->getCond()->isValueDependent()) {
- // Don't even try now, we'll examine it after instantiation.
- continue;
- }
-
+ // FIXME: This doesn't consider value-dependent cases, because doing so is
+ // very difficult. Ideally, we should handle them more gracefully.
if (!EIA->getCond()->EvaluateWithSubstitution(
- Result, Context, Function, llvm::makeArrayRef(ConvertedArgs))) {
- if (!ContainsValueDependentExpr)
- return EIA;
- } else if (!Result.isInt() || !Result.getInt().getBoolValue()) {
+ Result, Context, Function, llvm::makeArrayRef(ConvertedArgs)))
+ return EIA;
+
+ if (!Result.isInt() || !Result.getInt().getBoolValue())
return EIA;
- }
}
return nullptr;
}
@@ -6814,7 +6822,8 @@ namespace {
/// enumeration types.
class BuiltinCandidateTypeSet {
/// TypeSet - A set of types.
- typedef llvm::SmallPtrSet<QualType, 8> TypeSet;
+ typedef llvm::SetVector<QualType, SmallVector<QualType, 8>,
+ llvm::SmallPtrSet<QualType, 8>> TypeSet;
/// PointerTypes - The set of pointer types that will be used in the
/// built-in candidates.
@@ -6913,7 +6922,7 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
const Qualifiers &VisibleQuals) {
// Insert this type.
- if (!PointerTypes.insert(Ty).second)
+ if (!PointerTypes.insert(Ty))
return false;
QualType PointeeTy;
@@ -6981,7 +6990,7 @@ bool
BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
QualType Ty) {
// Insert this type.
- if (!MemberPointerTypes.insert(Ty).second)
+ if (!MemberPointerTypes.insert(Ty))
return false;
const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
@@ -7187,13 +7196,13 @@ class BuiltinOperatorOverloadBuilder {
// provided via the getArithmeticType() method below.
// The "promoted arithmetic types" are the arithmetic
// types are that preserved by promotion (C++ [over.built]p2).
- static const unsigned FirstIntegralType = 3;
- static const unsigned LastIntegralType = 20;
- static const unsigned FirstPromotedIntegralType = 3,
- LastPromotedIntegralType = 11;
+ static const unsigned FirstIntegralType = 4;
+ static const unsigned LastIntegralType = 21;
+ static const unsigned FirstPromotedIntegralType = 4,
+ LastPromotedIntegralType = 12;
static const unsigned FirstPromotedArithmeticType = 0,
- LastPromotedArithmeticType = 11;
- static const unsigned NumArithmeticTypes = 20;
+ LastPromotedArithmeticType = 12;
+ static const unsigned NumArithmeticTypes = 21;
/// \brief Get the canonical type for a given arithmetic type index.
CanQualType getArithmeticType(unsigned index) {
@@ -7204,6 +7213,7 @@ class BuiltinOperatorOverloadBuilder {
&ASTContext::FloatTy,
&ASTContext::DoubleTy,
&ASTContext::LongDoubleTy,
+ &ASTContext::Float128Ty,
// Start of integral types.
&ASTContext::IntTy,
@@ -7246,7 +7256,7 @@ class BuiltinOperatorOverloadBuilder {
// (we could precompute SLL x UI for all known platforms, but it's
// better not to make any assumptions).
// We assume that int128 has a higher rank than long long on all platforms.
- enum PromotedType {
+ enum PromotedType : int8_t {
Dep=-1,
Flt, Dbl, LDbl, SI, SL, SLL, S128, UI, UL, ULL, U128
};
@@ -8476,16 +8486,31 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
}
}
-// Determines whether Cand1 is "better" in terms of its enable_if attrs than
-// Cand2 for overloading. This function assumes that all of the enable_if attrs
-// on Cand1 and Cand2 have conditions that evaluate to true.
-//
-// Cand1's set of enable_if attributes are said to be "better" than Cand2's iff
-// Cand1's first N enable_if attributes have precisely the same conditions as
-// Cand2's first N enable_if attributes (where N = the number of enable_if
-// attributes on Cand2), and Cand1 has more than N enable_if attributes.
-static bool hasBetterEnableIfAttrs(Sema &S, const FunctionDecl *Cand1,
- const FunctionDecl *Cand2) {
+namespace {
+enum class Comparison { Equal, Better, Worse };
+}
+
+/// Compares the enable_if attributes of two FunctionDecls, for the purposes of
+/// overload resolution.
+///
+/// Cand1's set of enable_if attributes are said to be "better" than Cand2's iff
+/// Cand1's first N enable_if attributes have precisely the same conditions as
+/// Cand2's first N enable_if attributes (where N = the number of enable_if
+/// attributes on Cand2), and Cand1 has more than N enable_if attributes.
+///
+/// Note that you can have a pair of candidates such that Cand1's enable_if
+/// attributes are worse than Cand2's, and Cand2's enable_if attributes are
+/// worse than Cand1's.
+static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
+ const FunctionDecl *Cand2) {
+ // Common case: One (or both) decls don't have enable_if attrs.
+ bool Cand1Attr = Cand1->hasAttr<EnableIfAttr>();
+ bool Cand2Attr = Cand2->hasAttr<EnableIfAttr>();
+ if (!Cand1Attr || !Cand2Attr) {
+ if (Cand1Attr == Cand2Attr)
+ return Comparison::Equal;
+ return Cand1Attr ? Comparison::Better : Comparison::Worse;
+ }
// FIXME: The next several lines are just
// specific_attr_iterator<EnableIfAttr> but going in declaration order,
@@ -8493,10 +8518,10 @@ static bool hasBetterEnableIfAttrs(Sema &S, const FunctionDecl *Cand1,
auto Cand1Attrs = getOrderedEnableIfAttrs(Cand1);
auto Cand2Attrs = getOrderedEnableIfAttrs(Cand2);
- // Candidate 1 is better if it has strictly more attributes and
- // the common sequence is identical.
- if (Cand1Attrs.size() <= Cand2Attrs.size())
- return false;
+ // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1
+ // has fewer enable_if attributes than Cand2.
+ if (Cand1Attrs.size() < Cand2Attrs.size())
+ return Comparison::Worse;
auto Cand1I = Cand1Attrs.begin();
llvm::FoldingSetNodeID Cand1ID, Cand2ID;
@@ -8508,10 +8533,10 @@ static bool hasBetterEnableIfAttrs(Sema &S, const FunctionDecl *Cand1,
Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true);
Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true);
if (Cand1ID != Cand2ID)
- return false;
+ return Comparison::Worse;
}
- return true;
+ return Cand1I == Cand1Attrs.end() ? Comparison::Equal : Comparison::Better;
}
/// isBetterOverloadCandidate - Determines whether the first overload
@@ -8621,14 +8646,33 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
}
+ // FIXME: Work around a defect in the C++17 inheriting constructor wording.
+ // A derived-class constructor beats an (inherited) base class constructor.
+ bool Cand1IsInherited =
+ dyn_cast_or_null<ConstructorUsingShadowDecl>(Cand1.FoundDecl.getDecl());
+ bool Cand2IsInherited =
+ dyn_cast_or_null<ConstructorUsingShadowDecl>(Cand2.FoundDecl.getDecl());
+ if (Cand1IsInherited != Cand2IsInherited)
+ return Cand2IsInherited;
+ else if (Cand1IsInherited) {
+ assert(Cand2IsInherited);
+ auto *Cand1Class = cast<CXXRecordDecl>(Cand1.Function->getDeclContext());
+ auto *Cand2Class = cast<CXXRecordDecl>(Cand2.Function->getDeclContext());
+ if (Cand1Class->isDerivedFrom(Cand2Class))
+ return true;
+ if (Cand2Class->isDerivedFrom(Cand1Class))
+ return false;
+ // Inherited from sibling base classes: still ambiguous.
+ }
+
// Check for enable_if value-based overload resolution.
- if (Cand1.Function && Cand2.Function &&
- (Cand1.Function->hasAttr<EnableIfAttr>() ||
- Cand2.Function->hasAttr<EnableIfAttr>()))
- return hasBetterEnableIfAttrs(S, Cand1.Function, Cand2.Function);
+ if (Cand1.Function && Cand2.Function) {
+ Comparison Cmp = compareEnableIfAttrs(S, Cand1.Function, Cand2.Function);
+ if (Cmp != Comparison::Equal)
+ return Cmp == Comparison::Better;
+ }
- if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads &&
- Cand1.Function && Cand2.Function) {
+ if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) {
FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext);
return S.IdentifyCUDAPreference(Caller, Cand1.Function) >
S.IdentifyCUDAPreference(Caller, Cand2.Function);
@@ -8722,14 +8766,44 @@ OverloadingResult
OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
iterator &Best,
bool UserDefinedConversion) {
+ llvm::SmallVector<OverloadCandidate *, 16> Candidates;
+ std::transform(begin(), end(), std::back_inserter(Candidates),
+ [](OverloadCandidate &Cand) { return &Cand; });
+
+ // [CUDA] HD->H or HD->D calls are technically not allowed by CUDA
+ // but accepted by both clang and NVCC. However during a particular
+ // compilation mode only one call variant is viable. We need to
+ // exclude non-viable overload candidates from consideration based
+ // only on their host/device attributes. Specifically, if one
+ // candidate call is WrongSide and the other is SameSide, we ignore
+ // the WrongSide candidate.
+ if (S.getLangOpts().CUDA) {
+ const FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext);
+ bool ContainsSameSideCandidate =
+ llvm::any_of(Candidates, [&](OverloadCandidate *Cand) {
+ return Cand->Function &&
+ S.IdentifyCUDAPreference(Caller, Cand->Function) ==
+ Sema::CFP_SameSide;
+ });
+ if (ContainsSameSideCandidate) {
+ auto IsWrongSideCandidate = [&](OverloadCandidate *Cand) {
+ return Cand->Function &&
+ S.IdentifyCUDAPreference(Caller, Cand->Function) ==
+ Sema::CFP_WrongSide;
+ };
+ Candidates.erase(std::remove_if(Candidates.begin(), Candidates.end(),
+ IsWrongSideCandidate),
+ Candidates.end());
+ }
+ }
+
// Find the best viable function.
Best = end();
- for (iterator Cand = begin(); Cand != end(); ++Cand) {
+ for (auto *Cand : Candidates)
if (Cand->Viable)
if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc,
UserDefinedConversion))
Best = Cand;
- }
// If we didn't find any viable functions, abort.
if (Best == end())
@@ -8739,7 +8813,7 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// Make sure that this function is better than every other viable
// function. If not, we have an ambiguity.
- for (iterator Cand = begin(); Cand != end(); ++Cand) {
+ for (auto *Cand : Candidates) {
if (Cand->Viable &&
Cand != Best &&
!isBetterOverloadCandidate(S, *Best, *Cand, Loc,
@@ -8782,10 +8856,12 @@ enum OverloadCandidateKind {
oc_implicit_move_constructor,
oc_implicit_copy_assignment,
oc_implicit_move_assignment,
- oc_implicit_inherited_constructor
+ oc_inherited_constructor,
+ oc_inherited_constructor_template
};
OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
+ NamedDecl *Found,
FunctionDecl *Fn,
std::string &Description) {
bool isTemplate = false;
@@ -8797,11 +8873,13 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
}
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
- if (!Ctor->isImplicit())
- return isTemplate ? oc_constructor_template : oc_constructor;
-
- if (Ctor->getInheritedConstructor())
- return oc_implicit_inherited_constructor;
+ if (!Ctor->isImplicit()) {
+ if (isa<ConstructorUsingShadowDecl>(Found))
+ return isTemplate ? oc_inherited_constructor_template
+ : oc_inherited_constructor;
+ else
+ return isTemplate ? oc_constructor_template : oc_constructor;
+ }
if (Ctor->isDefaultConstructor())
return oc_implicit_default_constructor;
@@ -8833,14 +8911,13 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
return isTemplate ? oc_function_template : oc_function;
}
-void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) {
- const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
- if (!Ctor) return;
-
- Ctor = Ctor->getInheritedConstructor();
- if (!Ctor) return;
-
- S.Diag(Ctor->getLocation(), diag::note_ovl_candidate_inherited_constructor);
+void MaybeEmitInheritedConstructorNote(Sema &S, Decl *FoundDecl) {
+ // FIXME: It'd be nice to only emit a note once per using-decl per overload
+ // set.
+ if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl))
+ S.Diag(FoundDecl->getLocation(),
+ diag::note_ovl_candidate_inherited_constructor)
+ << Shadow->getNominatedBaseClass();
}
} // end anonymous namespace
@@ -8879,8 +8956,8 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
return false;
}
- auto I = std::find_if(FD->param_begin(), FD->param_end(),
- std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
+ auto I = llvm::find_if(
+ FD->parameters(), std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
if (I == FD->param_end())
return true;
@@ -8914,19 +8991,19 @@ bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
}
// Notes the location of an overload candidate.
-void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType,
- bool TakingAddress) {
+void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
+ QualType DestType, bool TakingAddress) {
if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn))
return;
std::string FnDesc;
- OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc);
+ OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Found, Fn, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
<< (unsigned) K << FnDesc;
HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
Diag(Fn->getLocation(), PD);
- MaybeEmitInheritedConstructorNote(*this, Fn);
+ MaybeEmitInheritedConstructorNote(*this, Found);
}
// Notes the location of all overload candidates designated through
@@ -8943,11 +9020,11 @@ void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType,
I != IEnd; ++I) {
if (FunctionTemplateDecl *FunTmpl =
dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) {
- NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType,
+ NoteOverloadCandidate(*I, FunTmpl->getTemplatedDecl(), DestType,
TakingAddress);
} else if (FunctionDecl *Fun
= dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
- NoteOverloadCandidate(Fun, DestType, TakingAddress);
+ NoteOverloadCandidate(*I, Fun, DestType, TakingAddress);
}
}
}
@@ -8971,7 +9048,7 @@ void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
if (CandsShown >= 4 && ShowOverloads == Ovl_Best)
break;
++CandsShown;
- S.NoteOverloadCandidate(*I);
+ S.NoteOverloadCandidate(I->first, I->second);
}
if (I != E)
S.Diag(SourceLocation(), diag::note_ovl_too_many_candidates) << int(E - I);
@@ -8996,7 +9073,8 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
}
std::string FnDesc;
- OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
+ OverloadCandidateKind FnKind =
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
Expr *FromExpr = Conv.Bad.FromExpr;
QualType FromTy = Conv.Bad.getFromType();
@@ -9013,7 +9091,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< ToTy << Name << I+1;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9026,8 +9104,10 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
else {
// TODO: detect and diagnose the full richness of const mismatches.
if (CanQual<PointerType> FromPT = CFromTy->getAs<PointerType>())
- if (CanQual<PointerType> ToPT = CToTy->getAs<PointerType>())
- CFromTy = FromPT->getPointeeType(), CToTy = ToPT->getPointeeType();
+ if (CanQual<PointerType> ToPT = CToTy->getAs<PointerType>()) {
+ CFromTy = FromPT->getPointeeType();
+ CToTy = ToPT->getPointeeType();
+ }
}
if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() &&
@@ -9042,7 +9122,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< FromTy
<< FromQs.getAddressSpace() << ToQs.getAddressSpace()
<< (unsigned) isObjectArgument << I+1;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9053,7 +9133,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< FromTy
<< FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
<< (unsigned) isObjectArgument << I+1;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9064,7 +9144,16 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< FromTy
<< FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
<< (unsigned) isObjectArgument << I+1;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
+ return;
+ }
+
+ if (FromQs.hasUnaligned() != ToQs.hasUnaligned()) {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_unaligned)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << FromQs.hasUnaligned() << I+1;
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9082,7 +9171,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << (CVR - 1) << I+1;
}
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9093,7 +9182,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << ToTy << (unsigned) isObjectArgument << I+1;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9104,11 +9193,14 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (const PointerType *PTy = TempFromTy->getAs<PointerType>())
TempFromTy = PTy->getPointeeType();
if (TempFromTy->isIncompleteType()) {
+ // Emit the generic diagnostic and, optionally, add the hints to it.
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ << FromTy << ToTy << (unsigned) isObjectArgument << I+1
+ << (unsigned) (Cand->Fix.Kind);
+
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9147,7 +9239,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< (unsigned) isObjectArgument << I + 1;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
}
@@ -9159,7 +9251,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< (BaseToDerivedConversion - 1)
<< FromTy << ToTy << I+1;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9172,7 +9264,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << ToTy << (unsigned) isObjectArgument << I+1;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
}
@@ -9194,7 +9286,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
FDiag << *HI;
S.Diag(Fn->getLocation(), FDiag);
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
}
/// Additional arity mismatch diagnosis specific to a function overload
@@ -9228,7 +9320,8 @@ static bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
}
/// General arity mismatch diagnosis over a candidate in a candidate set.
-static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
+static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D,
+ unsigned NumFormalArgs) {
assert(isa<FunctionDecl>(D) &&
"The templated declaration should at least be a function"
" when diagnosing bad template argument deduction due to too many"
@@ -9258,7 +9351,8 @@ static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
}
std::string Description;
- OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description);
+ OverloadCandidateKind FnKind =
+ ClassifyOverloadCandidate(S, Found, Fn, Description);
if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName())
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
@@ -9268,28 +9362,25 @@ static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
<< (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
<< mode << modeCount << NumFormalArgs;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Found);
}
/// Arity mismatch diagnosis specific to a function overload candidate.
static void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
unsigned NumFormalArgs) {
if (!CheckArityMismatch(S, Cand, NumFormalArgs))
- DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs);
+ DiagnoseArityMismatch(S, Cand->FoundDecl, Cand->Function, NumFormalArgs);
}
static TemplateDecl *getDescribedTemplate(Decl *Templated) {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated))
- return FD->getDescribedFunctionTemplate();
- else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated))
- return RD->getDescribedClassTemplate();
-
+ if (TemplateDecl *TD = Templated->getDescribedTemplate())
+ return TD;
llvm_unreachable("Unsupported: Getting the described template declaration"
" for bad deduction diagnosis");
}
/// Diagnose a failed template-argument deduction.
-static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
+static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
DeductionFailureInfo &DeductionFailure,
unsigned NumArgs,
bool TakingCandidateAddress) {
@@ -9307,7 +9398,7 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_incomplete_deduction)
<< ParamD->getDeclName();
- MaybeEmitInheritedConstructorNote(S, Templated);
+ MaybeEmitInheritedConstructorNote(S, Found);
return;
}
@@ -9332,7 +9423,7 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_underqualified)
<< ParamD->getDeclName() << Arg << NonCanonParam;
- MaybeEmitInheritedConstructorNote(S, Templated);
+ MaybeEmitInheritedConstructorNote(S, Found);
return;
}
@@ -9351,7 +9442,7 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
diag::note_ovl_candidate_inconsistent_deduction)
<< which << ParamD->getDeclName() << *DeductionFailure.getFirstArg()
<< *DeductionFailure.getSecondArg();
- MaybeEmitInheritedConstructorNote(S, Templated);
+ MaybeEmitInheritedConstructorNote(S, Found);
return;
}
@@ -9374,18 +9465,18 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
<< (index + 1);
}
- MaybeEmitInheritedConstructorNote(S, Templated);
+ MaybeEmitInheritedConstructorNote(S, Found);
return;
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
- DiagnoseArityMismatch(S, Templated, NumArgs);
+ DiagnoseArityMismatch(S, Found, Templated, NumArgs);
return;
case Sema::TDK_InstantiationDepth:
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_instantiation_depth);
- MaybeEmitInheritedConstructorNote(S, Templated);
+ MaybeEmitInheritedConstructorNote(S, Found);
return;
case Sema::TDK_SubstitutionFailure: {
@@ -9423,7 +9514,7 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_substitution_failure)
<< TemplateArgString << SFINAEArgString << R;
- MaybeEmitInheritedConstructorNote(S, Templated);
+ MaybeEmitInheritedConstructorNote(S, Found);
return;
}
@@ -9495,7 +9586,7 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
// note_ovl_candidate_bad_deduction, which is uselessly vague.
case Sema::TDK_MiscellaneousDeductionFailure:
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction);
- MaybeEmitInheritedConstructorNote(S, Templated);
+ MaybeEmitInheritedConstructorNote(S, Found);
return;
}
}
@@ -9509,7 +9600,7 @@ static void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
if (CheckArityMismatch(S, Cand, NumArgs))
return;
}
- DiagnoseBadDeduction(S, Cand->Function, // pattern
+ DiagnoseBadDeduction(S, Cand->FoundDecl, Cand->Function, // pattern
Cand->DeductionFailure, NumArgs, TakingCandidateAddress);
}
@@ -9522,7 +9613,8 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
CalleeTarget = S.IdentifyCUDATarget(Callee);
std::string FnDesc;
- OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Callee, FnDesc);
+ OverloadCandidateKind FnKind =
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, FnDesc);
S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
<< (unsigned)FnKind << CalleeTarget << CallerTarget;
@@ -9599,18 +9691,19 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
if (Cand->Viable && (Fn->isDeleted() ||
S.isFunctionConsideredUnavailable(Fn))) {
std::string FnDesc;
- OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
+ OverloadCandidateKind FnKind =
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
<< FnKind << FnDesc
<< (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
// We don't really have anything else to say about viable candidates.
if (Cand->Viable) {
- S.NoteOverloadCandidate(Fn);
+ S.NoteOverloadCandidate(Cand->FoundDecl, Fn);
return;
}
@@ -9620,19 +9713,20 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
return DiagnoseArityMismatch(S, Cand, NumArgs);
case ovl_fail_bad_deduction:
- return DiagnoseBadDeduction(S, Cand, NumArgs, TakingCandidateAddress);
+ return DiagnoseBadDeduction(S, Cand, NumArgs,
+ TakingCandidateAddress);
case ovl_fail_illegal_constructor: {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_illegal_constructor)
<< (Fn->getPrimaryTemplate() ? 1 : 0);
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
case ovl_fail_trivial_conversion:
case ovl_fail_bad_final_conversion:
case ovl_fail_final_conversion_not_exact:
- return S.NoteOverloadCandidate(Fn);
+ return S.NoteOverloadCandidate(Cand->FoundDecl, Fn);
case ovl_fail_bad_conversion: {
unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
@@ -9643,7 +9737,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
// FIXME: this currently happens when we're called from SemaInit
// when user-conversion overload fails. Figure out how to handle
// those conditions and diagnose them well.
- return S.NoteOverloadCandidate(Fn);
+ return S.NoteOverloadCandidate(Cand->FoundDecl, Fn);
}
case ovl_fail_bad_target:
@@ -9691,7 +9785,6 @@ static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
<< FnType;
- MaybeEmitInheritedConstructorNote(S, Cand->Surrogate);
}
static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc,
@@ -9721,8 +9814,8 @@ static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
if (ICS.isBad()) break; // all meaningless after first invalid
if (!ICS.isAmbiguous()) continue;
- ICS.DiagnoseAmbiguousConversion(S, OpLoc,
- S.PDiag(diag::note_ambiguous_type_conversion));
+ ICS.DiagnoseAmbiguousConversion(
+ S, OpLoc, S.PDiag(diag::note_ambiguous_type_conversion));
}
}
@@ -10089,7 +10182,7 @@ struct CompareTemplateSpecCandidatesForDisplay {
/// deductions.
void TemplateSpecCandidate::NoteDeductionFailure(Sema &S,
bool ForTakingAddress) {
- DiagnoseBadDeduction(S, Specialization, // pattern
+ DiagnoseBadDeduction(S, FoundDecl, Specialization, // pattern
DeductionFailure, /*NumArgs=*/0, ForTakingAddress);
}
@@ -10252,21 +10345,32 @@ public:
}
}
- if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads &&
- Matches.size() > 1)
+ if (S.getLangOpts().CUDA && Matches.size() > 1)
EliminateSuboptimalCudaMatches();
}
bool hasComplained() const { return HasComplained; }
private:
- // Is A considered a better overload candidate for the desired type than B?
+ bool candidateHasExactlyCorrectType(const FunctionDecl *FD) {
+ QualType Discard;
+ return Context.hasSameUnqualifiedType(TargetFunctionType, FD->getType()) ||
+ S.IsNoReturnConversion(FD->getType(), TargetFunctionType, Discard);
+ }
+
+ /// \return true if A is considered a better overload candidate for the
+ /// desired type than B.
bool isBetterCandidate(const FunctionDecl *A, const FunctionDecl *B) {
- return hasBetterEnableIfAttrs(S, A, B);
+ // If A doesn't have exactly the correct type, we don't want to classify it
+ // as "better" than anything else. This way, the user is required to
+ // disambiguate for us if there are multiple candidates and no exact match.
+ return candidateHasExactlyCorrectType(A) &&
+ (!candidateHasExactlyCorrectType(B) ||
+ compareEnableIfAttrs(S, A, B) == Comparison::Better);
}
- // Returns true if we've eliminated any (read: all but one) candidates, false
- // otherwise.
+ /// \return true if we were able to eliminate all but one overload candidate,
+ /// false otherwise.
bool eliminiateSuboptimalOverloadCandidates() {
// Same algorithm as overload resolution -- one pass to pick the "best",
// another pass to be sure that nothing is better than the best.
@@ -10331,7 +10435,7 @@ private:
Info, /*InOverloadResolution=*/true)) {
// Make a note of the failed deduction for diagnostics.
FailedCandidates.addCandidate()
- .set(FunctionTemplate->getTemplatedDecl(),
+ .set(CurAccessFunPair, FunctionTemplate->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, Result, Info));
return false;
}
@@ -10339,7 +10443,6 @@ private:
// Template argument deduction ensures that we have an exact match or
// compatible pointer-to-function arguments that would be adjusted by ICS.
// This function template specicalization works.
- Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
assert(S.isSameOrCompatibleFunctionType(
Context.getCanonicalType(Specialization->getType()),
Context.getCanonicalType(TargetFunctionType)));
@@ -10380,12 +10483,9 @@ private:
if (!S.checkAddressOfFunctionIsAvailable(FunDecl))
return false;
- QualType ResultTy;
- if (Context.hasSameUnqualifiedType(TargetFunctionType,
- FunDecl->getType()) ||
- S.IsNoReturnConversion(FunDecl->getType(), TargetFunctionType,
- ResultTy) ||
- (!S.getLangOpts().CPlusPlus && TargetType->isVoidPointerType())) {
+ // If we're in C, we need to support types that aren't exactly identical.
+ if (!S.getLangOpts().CPlusPlus ||
+ candidateHasExactlyCorrectType(FunDecl)) {
Matches.push_back(std::make_pair(
CurAccessFunPair, cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
FoundNonTemplateFunction = true;
@@ -10451,9 +10551,10 @@ private:
UnresolvedSetIterator Result = S.getMostSpecialized(
MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates,
SourceExpr->getLocStart(), S.PDiag(),
- S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0]
- .second->getDeclName(),
- S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function_template,
+ S.PDiag(diag::err_addr_ovl_ambiguous)
+ << Matches[0].second->getDeclName(),
+ S.PDiag(diag::note_ovl_candidate)
+ << (unsigned)oc_function_template,
Complain, TargetFunctionType);
if (Result != MatchesCopy.end()) {
@@ -10501,7 +10602,7 @@ public:
if (FunctionDecl *Fun =
dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
if (!functionHasPassObjectSizeParams(Fun))
- S.NoteOverloadCandidate(Fun, TargetFunctionType,
+ S.NoteOverloadCandidate(*I, Fun, TargetFunctionType,
/*TakingAddress=*/true);
FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
}
@@ -10614,6 +10715,72 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
}
/// \brief Given an expression that refers to an overloaded function, try to
+/// resolve that function to a single function that can have its address taken.
+/// This will modify `Pair` iff it returns non-null.
+///
+/// This routine can only realistically succeed if all but one candidates in the
+/// overload set for SrcExpr cannot have their addresses taken.
+FunctionDecl *
+Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E,
+ DeclAccessPair &Pair) {
+ OverloadExpr::FindResult R = OverloadExpr::find(E);
+ OverloadExpr *Ovl = R.Expression;
+ FunctionDecl *Result = nullptr;
+ DeclAccessPair DAP;
+ // Don't use the AddressOfResolver because we're specifically looking for
+ // cases where we have one overload candidate that lacks
+ // enable_if/pass_object_size/...
+ for (auto I = Ovl->decls_begin(), E = Ovl->decls_end(); I != E; ++I) {
+ auto *FD = dyn_cast<FunctionDecl>(I->getUnderlyingDecl());
+ if (!FD)
+ return nullptr;
+
+ if (!checkAddressOfFunctionIsAvailable(FD))
+ continue;
+
+ // We have more than one result; quit.
+ if (Result)
+ return nullptr;
+ DAP = I.getPair();
+ Result = FD;
+ }
+
+ if (Result)
+ Pair = DAP;
+ return Result;
+}
+
+/// \brief Given an overloaded function, tries to turn it into a non-overloaded
+/// function reference using resolveAddressOfOnlyViableOverloadCandidate. This
+/// will perform access checks, diagnose the use of the resultant decl, and, if
+/// necessary, perform a function-to-pointer decay.
+///
+/// Returns false if resolveAddressOfOnlyViableOverloadCandidate fails.
+/// Otherwise, returns true. This may emit diagnostics and return true.
+bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(
+ ExprResult &SrcExpr) {
+ Expr *E = SrcExpr.get();
+ assert(E->getType() == Context.OverloadTy && "SrcExpr must be an overload");
+
+ DeclAccessPair DAP;
+ FunctionDecl *Found = resolveAddressOfOnlyViableOverloadCandidate(E, DAP);
+ if (!Found)
+ return false;
+
+ // Emitting multiple diagnostics for a function that is both inaccessible and
+ // unavailable is consistent with our behavior elsewhere. So, always check
+ // for both.
+ DiagnoseUseOfDecl(Found, E->getExprLoc());
+ CheckAddressOfMemberAccess(E, DAP);
+ Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found);
+ if (Fixed->getType()->isFunctionType())
+ SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false);
+ else
+ SrcExpr = Fixed;
+ return true;
+}
+
+/// \brief Given an expression that refers to an overloaded function, try to
/// resolve that overloaded function expression down to a single function.
///
/// This routine can only resolve template-ids that refer to a single function
@@ -10671,7 +10838,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
// Make a note of the failed deduction for diagnostics.
// TODO: Actually use the failed-deduction info?
FailedCandidates.addCandidate()
- .set(FunctionTemplate->getTemplatedDecl(),
+ .set(I.getPair(), FunctionTemplate->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, Result, Info));
continue;
}
@@ -12236,6 +12403,16 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< MD->getDeclName();
}
}
+
+ if (CXXDestructorDecl *DD =
+ dyn_cast<CXXDestructorDecl>(TheCall->getMethodDecl())) {
+ // a->A::f() doesn't go through the vtable, except in AppleKext mode.
+ bool CallCanBeVirtual = !MemExpr->hasQualifier() || getLangOpts().AppleKext;
+ CheckVirtualDtorCall(DD, MemExpr->getLocStart(), /*IsDelete=*/false,
+ CallCanBeVirtual, /*WarnOnNonAbstractTypes=*/true,
+ MemExpr->getMemberLoc());
+ }
+
return MaybeBindToTemporary(TheCall);
}
@@ -12843,6 +13020,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
= Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
QualType MemPtrType
= Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
+ // Under the MS ABI, lock down the inheritance model now.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ (void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType);
return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
VK_RValue, OK_Ordinary,