aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r--lib/Sema/SemaOverload.cpp724
1 files changed, 461 insertions, 263 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2144845f4dd3..08af485ef4c7 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -223,6 +223,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const {
// a pointer.
if (getToType(1)->isBooleanType() &&
(getFromType()->isPointerType() ||
+ getFromType()->isMemberPointerType() ||
getFromType()->isObjCObjectPointerType() ||
getFromType()->isBlockPointerType() ||
getFromType()->isNullPtrType() ||
@@ -288,11 +289,11 @@ static const Expr *IgnoreNarrowingConversion(const Expr *Converted) {
/// value of the expression prior to the narrowing conversion.
/// \param ConstantType If this is an NK_Constant_Narrowing conversion, the
/// type of the expression prior to the narrowing conversion.
-NarrowingKind
-StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
- const Expr *Converted,
- APValue &ConstantValue,
- QualType &ConstantType) const {
+/// \param IgnoreFloatToIntegralConversion If true type-narrowing conversions
+/// from floating point types to integral types should be ignored.
+NarrowingKind StandardConversionSequence::getNarrowingKind(
+ ASTContext &Ctx, const Expr *Converted, APValue &ConstantValue,
+ QualType &ConstantType, bool IgnoreFloatToIntegralConversion) const {
assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++");
// C++11 [dcl.init.list]p7:
@@ -327,7 +328,10 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
FloatingIntegralConversion:
if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
return NK_Type_Narrowing;
- } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
+ } else if (FromType->isIntegralOrUnscopedEnumerationType() &&
+ ToType->isRealFloatingType()) {
+ if (IgnoreFloatToIntegralConversion)
+ return NK_Not_Narrowing;
llvm::APSInt IntConstantValue;
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
assert(Initializer && "Unknown conversion expression");
@@ -580,7 +584,7 @@ namespace {
};
}
-/// \brief Convert from Sema's representation of template deduction information
+/// Convert from Sema's representation of template deduction information
/// to the form used in overload-candidate information.
DeductionFailureInfo
clang::MakeDeductionFailureInfo(ASTContext &Context,
@@ -625,6 +629,8 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
break;
}
+ case Sema::TDK_IncompletePack:
+ // FIXME: It's slightly wasteful to allocate two TemplateArguments for this.
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified: {
// FIXME: Should allocate from normal heap so that we can free this later.
@@ -667,6 +673,7 @@ void DeductionFailureInfo::Destroy() {
case Sema::TDK_NonDependentConversionFailure:
break;
+ case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
@@ -716,6 +723,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_InvalidExplicitArguments:
return TemplateParameter::getFromOpaqueValue(Data);
+ case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
return static_cast<DFIParamWithArguments*>(Data)->Param;
@@ -736,6 +744,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_Incomplete:
+ case Sema::TDK_IncompletePack:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
@@ -773,6 +782,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_NonDependentConversionFailure:
return nullptr;
+ case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
@@ -794,6 +804,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_Incomplete:
+ case Sema::TDK_IncompletePack:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
@@ -997,6 +1008,13 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
Match = *I;
return Ovl_Match;
}
+
+ // Builtins that have custom typechecking or have a reference should
+ // not be overloadable or redeclarable.
+ if (!getASTContext().canBuiltinBeRedeclared(OldF)) {
+ Match = *I;
+ return Ovl_NonFunction;
+ }
} else if (isa<UsingDecl>(OldD) || isa<UsingPackDecl>(OldD)) {
// We can overload with these, which can show up when doing
// redeclaration checks for UsingDecls.
@@ -1182,7 +1200,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return false;
}
-/// \brief Checks availability of the function depending on the current
+/// Checks availability of the function depending on the current
/// function context. Inside an unavailable function, unavailability is ignored.
///
/// \returns true if \arg FD is unavailable and current context is inside
@@ -1200,7 +1218,7 @@ bool Sema::isFunctionConsideredUnavailable(FunctionDecl *FD) {
return true;
}
-/// \brief Tries a user-defined conversion from From to ToType.
+/// Tries a user-defined conversion from From to ToType.
///
/// Produces an implicit conversion sequence for when a standard conversion
/// is not an option. See TryImplicitConversion for more information.
@@ -1412,7 +1430,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
return PerformImplicitConversion(From, ToType, ICS, Action);
}
-/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// Determine whether the conversion from FromType to ToType is a valid
/// conversion that strips "noexcept" or "noreturn" off the nested function
/// type.
bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
@@ -1473,12 +1491,10 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
// Drop 'noexcept' if not present in target type.
if (const auto *FromFPT = dyn_cast<FunctionProtoType>(FromFn)) {
const auto *ToFPT = cast<FunctionProtoType>(ToFn);
- if (FromFPT->isNothrow(Context) && !ToFPT->isNothrow(Context)) {
+ if (FromFPT->isNothrow() && !ToFPT->isNothrow()) {
FromFn = cast<FunctionType>(
- Context.getFunctionType(FromFPT->getReturnType(),
- FromFPT->getParamTypes(),
- FromFPT->getExtProtoInfo().withExceptionSpec(
- FunctionProtoType::ExceptionSpecInfo()))
+ Context.getFunctionTypeWithExceptionSpec(QualType(FromFPT, 0),
+ EST_None)
.getTypePtr());
Changed = true;
}
@@ -1511,7 +1527,7 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
return true;
}
-/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// Determine whether the conversion from FromType to ToType is a valid
/// vector conversion.
///
/// \param ICK Will be set to the vector conversion kind, if this is a vector
@@ -1766,8 +1782,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
(FromType == S.Context.LongDoubleTy &&
ToType == S.Context.Float128Ty));
if (Float128AndLongDouble &&
- (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) !=
- &llvm::APFloat::IEEEdouble()))
+ (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) ==
+ &llvm::APFloat::PPCDoubleDouble()))
return false;
}
// Floating point conversions (C++ 4.8).
@@ -1998,6 +2014,14 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
isCompleteType(From->getLocStart(), FromType))
return Context.hasSameUnqualifiedType(
ToType, FromEnumType->getDecl()->getPromotionType());
+
+ // C++ [conv.prom]p5:
+ // If the bit-field has an enumerated type, it is treated as any other
+ // value of that type for promotion purposes.
+ //
+ // ... so do not fall through into the bit-field checks below in C++.
+ if (getLangOpts().CPlusPlus)
+ return false;
}
// C++0x [conv.prom]p2:
@@ -2045,6 +2069,11 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// other value of that type for promotion purposes (C++ 4.5p3).
// FIXME: We should delay checking of bit-fields until we actually perform the
// conversion.
+ //
+ // FIXME: In C, only bit-fields of types _Bool, int, or unsigned int may be
+ // promoted, per C11 6.3.1.1/2. We promote all bit-fields (including enum
+ // bit-fields and those whose underlying type is larger than int) for GCC
+ // compatibility.
if (From) {
if (FieldDecl *MemberDecl = From->getSourceBitField()) {
llvm::APSInt BitWidth;
@@ -2111,7 +2140,7 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
return false;
}
-/// \brief Determine if a conversion is a complex promotion.
+/// Determine if a conversion is a complex promotion.
///
/// A complex promotion is defined as a complex -> complex conversion
/// where the conversion between the underlying real types is a
@@ -2345,7 +2374,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
return false;
}
-/// \brief Adopt the given qualifiers for the given type.
+/// Adopt the given qualifiers for the given type.
static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){
Qualifiers TQs = T.getQualifiers();
@@ -2533,7 +2562,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
return false;
}
-/// \brief Determine whether this is an Objective-C writeback conversion,
+/// Determine whether this is an Objective-C writeback conversion,
/// used for parameter passing when performing automatic reference counting.
///
/// \param FromType The type we're converting form.
@@ -2593,7 +2622,7 @@ bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType,
IncompatibleObjC))
return false;
- /// \brief Construct the type we're converting to, which is a pointer to
+ /// Construct the type we're converting to, which is a pointer to
/// __autoreleasing pointee.
FromPointee = Context.getQualifiedType(FromPointee, FromQuals);
ConvertedType = Context.getPointerType(FromPointee);
@@ -2803,9 +2832,9 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
// Handle exception specification differences on canonical type (in C++17
// onwards).
if (cast<FunctionProtoType>(FromFunction->getCanonicalTypeUnqualified())
- ->isNothrow(Context) !=
+ ->isNothrow() !=
cast<FunctionProtoType>(ToFunction->getCanonicalTypeUnqualified())
- ->isNothrow(Context)) {
+ ->isNothrow()) {
PDiag << ft_noexcept;
return;
}
@@ -3065,7 +3094,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
// in multi-level pointers, subject to the following rules: [...]
bool PreviousToQualsIncludeConst = true;
bool UnwrappedAnyPointer = false;
- while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) {
+ while (Context.UnwrapSimilarTypes(FromType, ToType)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
@@ -3121,6 +3150,15 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
= PreviousToQualsIncludeConst && ToQuals.hasConst();
}
+ // Allows address space promotion by language rules implemented in
+ // Type::Qualifiers::isAddressSpaceSupersetOf.
+ Qualifiers FromQuals = FromType.getQualifiers();
+ Qualifiers ToQuals = ToType.getQualifiers();
+ if (!ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
+ !FromQuals.isAddressSpaceSupersetOf(ToQuals)) {
+ return false;
+ }
+
// We are left with FromType and ToType being the pointee types
// after unwrapping the original FromType and ToType the same number
// of types. If we unwrapped any pointers, and if FromType and
@@ -3129,7 +3167,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
}
-/// \brief - Determine whether this is a conversion from a scalar type to an
+/// - Determine whether this is a conversion from a scalar type to an
/// atomic type.
///
/// If successful, updates \c SCS's second and third steps in the conversion
@@ -3472,7 +3510,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
return true;
}
-/// \brief Compare the user-defined conversion functions or constructors
+/// Compare the user-defined conversion functions or constructors
/// of two user-defined conversion sequences to determine whether any ordering
/// is possible.
static ImplicitConversionSequence::CompareKind
@@ -3620,16 +3658,6 @@ CompareImplicitConversionSequences(Sema &S, SourceLocation Loc,
return Result;
}
-static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) {
- while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
- Qualifiers Quals;
- T1 = Context.getUnqualifiedArrayType(T1, Quals);
- T2 = Context.getUnqualifiedArrayType(T2, Quals);
- }
-
- return Context.hasSameUnqualifiedType(T1, T2);
-}
-
// Per 13.3.3.2p3, compare the given standard conversion sequences to
// determine if one is a proper subset of the other.
static ImplicitConversionSequence::CompareKind
@@ -3653,7 +3681,7 @@ compareStandardConversionSubsets(ASTContext &Context,
Result = ImplicitConversionSequence::Worse;
else
return ImplicitConversionSequence::Indistinguishable;
- } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1)))
+ } else if (!Context.hasSimilarType(SCS1.getToType(1), SCS2.getToType(1)))
return ImplicitConversionSequence::Indistinguishable;
if (SCS1.Third == SCS2.Third) {
@@ -3674,7 +3702,7 @@ compareStandardConversionSubsets(ASTContext &Context,
return ImplicitConversionSequence::Indistinguishable;
}
-/// \brief Determine whether one of the given reference bindings is better
+/// Determine whether one of the given reference bindings is better
/// than the other based on what kind of bindings they are.
static bool
isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
@@ -3927,7 +3955,7 @@ CompareQualificationConversions(Sema &S,
: ImplicitConversionSequence::Better;
}
- while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) {
+ while (S.Context.UnwrapSimilarTypes(T1, T2)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
@@ -4199,7 +4227,7 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
return ImplicitConversionSequence::Indistinguishable;
}
-/// \brief Determine whether the given type is valid, e.g., it is not an invalid
+/// Determine whether the given type is valid, e.g., it is not an invalid
/// C++ class.
static bool isTypeValid(QualType T) {
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
@@ -4302,7 +4330,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
return Ref_Related;
}
-/// \brief Look for a user-defined conversion to a value reference-compatible
+/// Look for a user-defined conversion to a value reference-compatible
/// with DeclType. Return true if something definite is found.
static bool
FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
@@ -4429,7 +4457,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
llvm_unreachable("Invalid OverloadResult!");
}
-/// \brief Compute an implicit conversion sequence for reference
+/// Compute an implicit conversion sequence for reference
/// initialization.
static ImplicitConversionSequence
TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
@@ -5137,6 +5165,13 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
FromRecordType = From->getType();
DestType = ImplicitParamRecordType;
FromClassification = From->Classify(Context);
+
+ // When performing member access on an rvalue, materialize a temporary.
+ if (From->isRValue()) {
+ From = CreateMaterializeTemporaryExpr(FromRecordType, From,
+ Method->getRefQualifier() !=
+ RefQualifierKind::RQ_RValue);
+ }
}
// Note that we always use the true parent context when performing
@@ -5145,7 +5180,8 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
*this, From->getLocStart(), From->getType(), FromClassification, Method,
Method->getParent());
if (ICS.isBad()) {
- if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
+ switch (ICS.Bad.Kind) {
+ case BadConversionSequence::bad_qualifiers: {
Qualifiers FromQs = FromRecordType.getQualifiers();
Qualifiers ToQs = DestType.getQualifiers();
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
@@ -5158,10 +5194,28 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
<< Method->getDeclName();
return ExprError();
}
+ break;
+ }
+
+ case BadConversionSequence::lvalue_ref_to_rvalue:
+ case BadConversionSequence::rvalue_ref_to_lvalue: {
+ bool IsRValueQualified =
+ Method->getRefQualifier() == RefQualifierKind::RQ_RValue;
+ Diag(From->getLocStart(), diag::err_member_function_call_bad_ref)
+ << Method->getDeclName() << FromClassification.isRValue()
+ << IsRValueQualified;
+ Diag(Method->getLocation(), diag::note_previous_decl)
+ << Method->getDeclName();
+ return ExprError();
+ }
+
+ case BadConversionSequence::no_conversion:
+ case BadConversionSequence::unrelated_class:
+ break;
}
return Diag(From->getLocStart(),
- diag::err_implicit_object_parameter_init)
+ diag::err_member_function_call_bad_type)
<< ImplicitParamRecordType << FromRecordType << From->getSourceRange();
}
@@ -5380,10 +5434,11 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
SmallVector<PartialDiagnosticAt, 8> Notes;
Expr::EvalResult Eval;
Eval.Diag = &Notes;
+ Expr::ConstExprUsage Usage = CCE == Sema::CCEK_TemplateArg
+ ? Expr::EvaluateForMangling
+ : Expr::EvaluateForCodeGen;
- if ((T->isReferenceType()
- ? !Result.get()->EvaluateAsLValue(Eval, S.Context)
- : !Result.get()->EvaluateAsRValue(Eval, S.Context)) ||
+ if (!Result.get()->EvaluateAsConstantExpr(Eval, Usage, S.Context) ||
(RequireInt && !Eval.Val.isInt())) {
// The expression can't be folded, so we can't keep it at this position in
// the AST.
@@ -5622,7 +5677,7 @@ collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType,
}
}
-/// \brief Attempt to convert the given expression to a type which is accepted
+/// Attempt to convert the given expression to a type which is accepted
/// by the given converter.
///
/// This routine will attempt to convert an expression of class type to a
@@ -5940,6 +5995,13 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
+ if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() &&
+ !Function->getAttr<TargetAttr>()->isDefaultVersion()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_non_default_multiversion_function;
+ return;
+ }
+
if (Constructor) {
// C++ [class.copy]p3:
// A member function template is never instantiated to perform the copy
@@ -6220,12 +6282,17 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
if (!Function->isVariadic() && Args.size() < Function->getNumParams()) {
for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) {
ParmVarDecl *P = Function->getParamDecl(i);
- ExprResult R = S.PerformCopyInitialization(
- InitializedEntity::InitializeParameter(S.Context,
- Function->getParamDecl(i)),
- SourceLocation(),
- P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg()
- : P->getDefaultArg());
+ Expr *DefArg = P->hasUninstantiatedDefaultArg()
+ ? P->getUninstantiatedDefaultArg()
+ : P->getDefaultArg();
+ // This can only happen in code completion, i.e. when PartialOverloading
+ // is true.
+ if (!DefArg)
+ return false;
+ ExprResult R =
+ S.PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ S.Context, Function->getParamDecl(i)),
+ SourceLocation(), DefArg);
if (R.isInvalid())
return false;
ConvertedArgs.push_back(R.get());
@@ -6336,67 +6403,65 @@ bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,
});
}
-/// \brief Add all of the function declarations in the given function set to
+/// Add all of the function declarations in the given function set to
/// the overload candidate set.
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs,
bool SuppressUserConversions,
bool PartialOverloading,
bool FirstArgumentIsBase) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- ArrayRef<Expr *> FunctionArgs = Args;
- if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
- QualType ObjectType;
- Expr::Classification ObjectClassification;
- if (Args.size() > 0) {
- if (Expr *E = Args[0]) {
- // Use the explit base to restrict the lookup:
- ObjectType = E->getType();
- ObjectClassification = E->Classify(Context);
- } // .. else there is an implit base.
- FunctionArgs = Args.slice(1);
- }
- AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
- cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
- ObjectClassification, FunctionArgs, CandidateSet,
- SuppressUserConversions, PartialOverloading);
- } else {
- // Slice the first argument (which is the base) when we access
- // static method as non-static
- if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) &&
- !isa<CXXConstructorDecl>(FD)))) {
- assert(cast<CXXMethodDecl>(FD)->isStatic());
- FunctionArgs = Args.slice(1);
- }
- AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
- SuppressUserConversions, PartialOverloading);
- }
- } else {
- FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
- if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
- !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) {
- QualType ObjectType;
- Expr::Classification ObjectClassification;
+ ArrayRef<Expr *> FunctionArgs = Args;
+
+ FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ FunctionDecl *FD =
+ FunTmpl ? FunTmpl->getTemplatedDecl() : cast<FunctionDecl>(D);
+
+ if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
+ QualType ObjectType;
+ Expr::Classification ObjectClassification;
+ if (Args.size() > 0) {
if (Expr *E = Args[0]) {
- // Use the explit base to restrict the lookup:
+ // Use the explicit base to restrict the lookup:
ObjectType = E->getType();
ObjectClassification = E->Classify(Context);
- } // .. else there is an implit base.
+ } // .. else there is an implicit base.
+ FunctionArgs = Args.slice(1);
+ }
+ if (FunTmpl) {
AddMethodTemplateCandidate(
FunTmpl, F.getPair(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
ExplicitTemplateArgs, ObjectType, ObjectClassification,
- Args.slice(1), CandidateSet, SuppressUserConversions,
+ FunctionArgs, CandidateSet, SuppressUserConversions,
PartialOverloading);
} else {
- AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
- ExplicitTemplateArgs, Args,
- CandidateSet, SuppressUserConversions,
- PartialOverloading);
+ AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
+ cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
+ ObjectClassification, FunctionArgs, CandidateSet,
+ SuppressUserConversions, PartialOverloading);
+ }
+ } else {
+ // This branch handles both standalone functions and static methods.
+
+ // Slice the first argument (which is the base) when we access
+ // static method as non-static.
+ if (Args.size() > 0 &&
+ (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) &&
+ !isa<CXXConstructorDecl>(FD)))) {
+ assert(cast<CXXMethodDecl>(FD)->isStatic());
+ FunctionArgs = Args.slice(1);
+ }
+ if (FunTmpl) {
+ AddTemplateOverloadCandidate(
+ FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs,
+ CandidateSet, SuppressUserConversions, PartialOverloading);
+ } else {
+ AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
+ SuppressUserConversions, PartialOverloading);
}
}
}
@@ -6564,9 +6629,15 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
+
+ if (Method->isMultiVersion() && Method->hasAttr<TargetAttr>() &&
+ !Method->getAttr<TargetAttr>()->isDefaultVersion()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_non_default_multiversion_function;
+ }
}
-/// \brief Add a C++ member function template as a candidate to the candidate
+/// Add a C++ member function template as a candidate to the candidate
/// set, using template argument deduction to produce an appropriate member
/// function template specialization.
void
@@ -6634,7 +6705,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
Conversions);
}
-/// \brief Add a C++ function template specialization as a candidate
+/// Add a C++ function template specialization as a candidate
/// in the candidate set, using template argument deduction to produce
/// an appropriate function template specialization.
void
@@ -6967,9 +7038,15 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
+
+ if (Conversion->isMultiVersion() && Conversion->hasAttr<TargetAttr>() &&
+ !Conversion->getAttr<TargetAttr>()->isDefaultVersion()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_non_default_multiversion_function;
+ }
}
-/// \brief Adds a conversion function template specialization
+/// Adds a conversion function template specialization
/// candidate to the overload set, using template argument deduction
/// to deduce the template arguments of the conversion function
/// template from the type that we are converting to (C++
@@ -7124,7 +7201,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
}
}
-/// \brief Add overload candidates for overloaded operators that are
+/// Add overload candidates for overloaded operators that are
/// member functions.
///
/// Add the overloaded operator candidates that are member functions
@@ -7260,18 +7337,18 @@ class BuiltinCandidateTypeSet {
/// used in the built-in candidates.
TypeSet EnumerationTypes;
- /// \brief The set of vector types that will be used in the built-in
+ /// The set of vector types that will be used in the built-in
/// candidates.
TypeSet VectorTypes;
- /// \brief A flag indicating non-record types are viable candidates
+ /// A flag indicating non-record types are viable candidates
bool HasNonRecordTypes;
- /// \brief A flag indicating whether either arithmetic or enumeration types
+ /// A flag indicating whether either arithmetic or enumeration types
/// were present in the candidate set.
bool HasArithmeticOrEnumeralTypes;
- /// \brief A flag indicating whether the nullptr type was present in the
+ /// A flag indicating whether the nullptr type was present in the
/// candidate set.
bool HasNullPtrType;
@@ -7524,7 +7601,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
}
}
-/// \brief Helper function for AddBuiltinOperatorCandidates() that adds
+/// Helper function for AddBuiltinOperatorCandidates() that adds
/// the volatile- and non-volatile-qualified assignment operators for the
/// given type to the candidate set.
static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
@@ -7602,7 +7679,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
namespace {
-/// \brief Helper class to manage the addition of builtin operator overload
+/// Helper class to manage the addition of builtin operator overload
/// candidates. It provides shared state and utility methods used throughout
/// the process, as well as a helper method to add each group of builtin
/// operator overloads from the standard to a candidate set.
@@ -7658,6 +7735,8 @@ class BuiltinOperatorOverloadBuilder {
ArithmeticTypes.push_back(S.Context.BoolTy);
ArithmeticTypes.push_back(S.Context.CharTy);
ArithmeticTypes.push_back(S.Context.WCharTy);
+ if (S.Context.getLangOpts().Char8)
+ ArithmeticTypes.push_back(S.Context.Char8Ty);
ArithmeticTypes.push_back(S.Context.Char16Ty);
ArithmeticTypes.push_back(S.Context.Char32Ty);
ArithmeticTypes.push_back(S.Context.SignedCharTy);
@@ -7673,7 +7752,7 @@ class BuiltinOperatorOverloadBuilder {
"Enough inline storage for all arithmetic types.");
}
- /// \brief Helper method to factor out the common pattern of adding overloads
+ /// Helper method to factor out the common pattern of adding overloads
/// for '++' and '--' builtin operators.
void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
bool HasVolatile,
@@ -7733,11 +7812,13 @@ public:
InitArithmeticTypes();
}
+ // Increment is deprecated for bool since C++17.
+ //
// C++ [over.built]p3:
//
- // For every pair (T, VQ), where T is an arithmetic type, and VQ
- // is either volatile or empty, there exist candidate operator
- // functions of the form
+ // For every pair (T, VQ), where T is an arithmetic type other
+ // than bool, and VQ is either volatile or empty, there exist
+ // candidate operator functions of the form
//
// VQ T& operator++(VQ T&);
// T operator++(VQ T&, int);
@@ -7754,10 +7835,16 @@ public:
if (!HasArithmeticOrEnumeralCandidateType)
return;
- for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
- Arith < NumArithmeticTypes; ++Arith) {
+ for (unsigned Arith = 0; Arith < NumArithmeticTypes; ++Arith) {
+ const auto TypeOfT = ArithmeticTypes[Arith];
+ if (TypeOfT == S.Context.BoolTy) {
+ if (Op == OO_MinusMinus)
+ continue;
+ if (Op == OO_PlusPlus && S.getLangOpts().CPlusPlus17)
+ continue;
+ }
addPlusPlusMinusMinusStyleOverloads(
- ArithmeticTypes[Arith],
+ TypeOfT,
VisibleTypeConversionsQuals.hasVolatile(),
VisibleTypeConversionsQuals.hasRestrict());
}
@@ -7929,7 +8016,8 @@ public:
// bool operator>=(T, T);
// bool operator==(T, T);
// bool operator!=(T, T);
- void addRelationalPointerOrEnumeralOverloads() {
+ // R operator<=>(T, T)
+ void addGenericBinaryPointerOrEnumeralOverloads() {
// C++ [over.match.oper]p3:
// [...]the built-in candidates include all of the candidate operator
// functions defined in 13.6 that, compared to the given operator, [...]
@@ -8002,7 +8090,6 @@ public:
UserDefinedBinaryOperators.count(std::make_pair(CanonType,
CanonType)))
continue;
-
QualType ParamTypes[2] = { *Enum, *Enum };
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
@@ -8120,6 +8207,41 @@ public:
}
}
+ // C++2a [over.built]p14:
+ //
+ // For every integral type T there exists a candidate operator function
+ // of the form
+ //
+ // std::strong_ordering operator<=>(T, T)
+ //
+ // C++2a [over.built]p15:
+ //
+ // For every pair of floating-point types L and R, there exists a candidate
+ // operator function of the form
+ //
+ // std::partial_ordering operator<=>(L, R);
+ //
+ // FIXME: The current specification for integral types doesn't play nice with
+ // the direction of p0946r0, which allows mixed integral and unscoped-enum
+ // comparisons. Under the current spec this can lead to ambiguity during
+ // overload resolution. For example:
+ //
+ // enum A : int {a};
+ // auto x = (a <=> (long)42);
+ //
+ // error: call is ambiguous for arguments 'A' and 'long'.
+ // note: candidate operator<=>(int, int)
+ // note: candidate operator<=>(long, long)
+ //
+ // To avoid this error, this function deviates from the specification and adds
+ // the mixed overloads `operator<=>(L, R)` where L and R are promoted
+ // arithmetic types (the same as the generic relational overloads).
+ //
+ // For now this function acts as a placeholder.
+ void addThreeWayArithmeticOverloads() {
+ addGenericBinaryArithmeticOverloads();
+ }
+
// C++ [over.built]p17:
//
// For every pair of promoted integral types L and R, there
@@ -8688,12 +8810,14 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_Greater:
case OO_LessEqual:
case OO_GreaterEqual:
- OpBuilder.addRelationalPointerOrEnumeralOverloads();
+ OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
OpBuilder.addGenericBinaryArithmeticOverloads();
break;
case OO_Spaceship:
- llvm_unreachable("<=> expressions not supported yet");
+ OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
+ OpBuilder.addThreeWayArithmeticOverloads();
+ break;
case OO_Percent:
case OO_Caret:
@@ -8764,7 +8888,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
}
}
-/// \brief Add function candidates found via argument-dependent lookup
+/// Add function candidates found via argument-dependent lookup
/// to the set of overloading candidates.
///
/// This routine performs argument-dependent name lookup based on the
@@ -8870,6 +8994,47 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
return Cand1I == Cand1Attrs.end() ? Comparison::Equal : Comparison::Better;
}
+static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
+ const OverloadCandidate &Cand2) {
+ if (!Cand1.Function || !Cand1.Function->isMultiVersion() || !Cand2.Function ||
+ !Cand2.Function->isMultiVersion())
+ return false;
+
+ // If this is a cpu_dispatch/cpu_specific multiversion situation, prefer
+ // cpu_dispatch, else arbitrarily based on the identifiers.
+ bool Cand1CPUDisp = Cand1.Function->hasAttr<CPUDispatchAttr>();
+ bool Cand2CPUDisp = Cand2.Function->hasAttr<CPUDispatchAttr>();
+ const auto *Cand1CPUSpec = Cand1.Function->getAttr<CPUSpecificAttr>();
+ const auto *Cand2CPUSpec = Cand2.Function->getAttr<CPUSpecificAttr>();
+
+ if (!Cand1CPUDisp && !Cand2CPUDisp && !Cand1CPUSpec && !Cand2CPUSpec)
+ return false;
+
+ if (Cand1CPUDisp && !Cand2CPUDisp)
+ return true;
+ if (Cand2CPUDisp && !Cand1CPUDisp)
+ return false;
+
+ if (Cand1CPUSpec && Cand2CPUSpec) {
+ if (Cand1CPUSpec->cpus_size() != Cand2CPUSpec->cpus_size())
+ return Cand1CPUSpec->cpus_size() < Cand2CPUSpec->cpus_size();
+
+ std::pair<CPUSpecificAttr::cpus_iterator, CPUSpecificAttr::cpus_iterator>
+ FirstDiff = std::mismatch(
+ Cand1CPUSpec->cpus_begin(), Cand1CPUSpec->cpus_end(),
+ Cand2CPUSpec->cpus_begin(),
+ [](const IdentifierInfo *LHS, const IdentifierInfo *RHS) {
+ return LHS->getName() == RHS->getName();
+ });
+
+ assert(FirstDiff.first != Cand1CPUSpec->cpus_end() &&
+ "Two different cpu-specific versions should not have the same "
+ "identifier list, otherwise they'd be the same decl!");
+ return (*FirstDiff.first)->getName() < (*FirstDiff.second)->getName();
+ }
+ llvm_unreachable("No way to get here unless both had cpu_dispatch");
+}
+
/// isBetterOverloadCandidate - Determines whether the first overload
/// candidate is a better candidate than the second (C++ 13.3.3p1).
bool clang::isBetterOverloadCandidate(
@@ -9067,7 +9232,10 @@ bool clang::isBetterOverloadCandidate(
functionHasPassObjectSizeParams(Cand1.Function);
bool HasPS2 = Cand2.Function != nullptr &&
functionHasPassObjectSizeParams(Cand2.Function);
- return HasPS1 != HasPS2 && HasPS1;
+ if (HasPS1 != HasPS2 && HasPS1)
+ return true;
+
+ return isBetterMultiversionCandidate(Cand1, Cand2);
}
/// Determine whether two declarations are "equivalent" for the purposes of
@@ -9137,7 +9305,7 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations(
}
}
-/// \brief Computes the best viable function (C++ 13.3.3)
+/// Computes the best viable function (C++ 13.3.3)
/// within an overload candidate set.
///
/// \param Loc The location of the function name (or operator symbol) for
@@ -9228,66 +9396,77 @@ enum OverloadCandidateKind {
oc_function,
oc_method,
oc_constructor,
- oc_function_template,
- oc_method_template,
- oc_constructor_template,
oc_implicit_default_constructor,
oc_implicit_copy_constructor,
oc_implicit_move_constructor,
oc_implicit_copy_assignment,
oc_implicit_move_assignment,
- oc_inherited_constructor,
- oc_inherited_constructor_template
+ oc_inherited_constructor
+};
+
+enum OverloadCandidateSelect {
+ ocs_non_template,
+ ocs_template,
+ ocs_described_template,
};
-static OverloadCandidateKind
+static std::pair<OverloadCandidateKind, OverloadCandidateSelect>
ClassifyOverloadCandidate(Sema &S, NamedDecl *Found, FunctionDecl *Fn,
std::string &Description) {
- bool isTemplate = false;
+ bool isTemplate = Fn->isTemplateDecl() || Found->isTemplateDecl();
if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) {
isTemplate = true;
Description = S.getTemplateArgumentBindingsText(
- FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
+ FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
}
- if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
- if (!Ctor->isImplicit()) {
- if (isa<ConstructorUsingShadowDecl>(Found))
- return isTemplate ? oc_inherited_constructor_template
- : oc_inherited_constructor;
- else
- return isTemplate ? oc_constructor_template : oc_constructor;
- }
+ OverloadCandidateSelect Select = [&]() {
+ if (!Description.empty())
+ return ocs_described_template;
+ return isTemplate ? ocs_template : ocs_non_template;
+ }();
- if (Ctor->isDefaultConstructor())
- return oc_implicit_default_constructor;
+ OverloadCandidateKind Kind = [&]() {
+ if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
+ if (!Ctor->isImplicit()) {
+ if (isa<ConstructorUsingShadowDecl>(Found))
+ return oc_inherited_constructor;
+ else
+ return oc_constructor;
+ }
- if (Ctor->isMoveConstructor())
- return oc_implicit_move_constructor;
+ if (Ctor->isDefaultConstructor())
+ return oc_implicit_default_constructor;
- assert(Ctor->isCopyConstructor() &&
- "unexpected sort of implicit constructor");
- return oc_implicit_copy_constructor;
- }
+ if (Ctor->isMoveConstructor())
+ return oc_implicit_move_constructor;
- if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
- // This actually gets spelled 'candidate function' for now, but
- // it doesn't hurt to split it out.
- if (!Meth->isImplicit())
- return isTemplate ? oc_method_template : oc_method;
+ assert(Ctor->isCopyConstructor() &&
+ "unexpected sort of implicit constructor");
+ return oc_implicit_copy_constructor;
+ }
- if (Meth->isMoveAssignmentOperator())
- return oc_implicit_move_assignment;
+ if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
+ // This actually gets spelled 'candidate function' for now, but
+ // it doesn't hurt to split it out.
+ if (!Meth->isImplicit())
+ return oc_method;
- if (Meth->isCopyAssignmentOperator())
- return oc_implicit_copy_assignment;
+ if (Meth->isMoveAssignmentOperator())
+ return oc_implicit_move_assignment;
- assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
- return oc_method;
- }
+ if (Meth->isCopyAssignmentOperator())
+ return oc_implicit_copy_assignment;
+
+ assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
+ return oc_method;
+ }
- return isTemplate ? oc_function_template : oc_function;
+ return oc_function;
+ }();
+
+ return std::make_pair(Kind, Select);
}
void MaybeEmitInheritedConstructorNote(Sema &S, Decl *FoundDecl) {
@@ -9313,7 +9492,7 @@ static bool isFunctionAlwaysEnabled(const ASTContext &Ctx,
return true;
}
-/// \brief Returns true if we can take the address of the function.
+/// Returns true if we can take the address of the function.
///
/// \param Complain - If true, we'll emit a diagnostic
/// \param InOverloadResolution - For the purposes of emitting a diagnostic, are
@@ -9375,11 +9554,16 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
QualType DestType, bool TakingAddress) {
if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn))
return;
+ if (Fn->isMultiVersion() && Fn->hasAttr<TargetAttr>() &&
+ !Fn->getAttr<TargetAttr>()->isDefaultVersion())
+ return;
std::string FnDesc;
- OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Found, Fn, FnDesc);
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> KSPair =
+ ClassifyOverloadCandidate(*this, Found, Fn, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
- << (unsigned) K << Fn << FnDesc;
+ << (unsigned)KSPair.first << (unsigned)KSPair.second
+ << Fn << FnDesc;
HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
Diag(Fn->getLocation(), PD);
@@ -9453,7 +9637,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
}
std::string FnDesc;
- OverloadCandidateKind FnKind =
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
Expr *FromExpr = Conv.Bad.FromExpr;
@@ -9468,9 +9652,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
DeclarationName Name = cast<OverloadExpr>(E)->getName();
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << ToTy << Name << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << ToTy
+ << Name << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9497,43 +9681,38 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy
- << FromQs.getAddressSpaceAttributePrintValue()
- << ToQs.getAddressSpaceAttributePrintValue()
- << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_ownership)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy
- << FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
- << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
+ << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy
- << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
- << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
+ << (unsigned)isObjectArgument << I + 1;
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;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << FromQs.hasUnaligned() << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9543,14 +9722,14 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (isObjectArgument) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << (CVR - 1);
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << (CVR - 1);
} else {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << (CVR - 1) << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << (CVR - 1) << I + 1;
}
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
@@ -9560,9 +9739,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
// telling the user that it has type void is not useful.
if (FromExpr && isa<InitListExpr>(FromExpr)) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_list_argument)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9576,10 +9755,10 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
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
- << (unsigned) (Cand->Fix.Kind);
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1
+ << (unsigned)(Cand->Fix.Kind);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
@@ -9617,21 +9796,19 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
ToTy.getNonReferenceType().getCanonicalType() ==
FromTy.getNonReferenceType().getCanonicalType()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_lvalue)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << (unsigned) isObjectArgument << I + 1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (unsigned)isObjectArgument << I + 1
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange());
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
}
if (BaseToDerivedConversion) {
- S.Diag(Fn->getLocation(),
- diag::note_ovl_candidate_bad_base_to_derived_conv)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << (BaseToDerivedConversion - 1)
- << FromTy << ToTy << I+1;
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_base_to_derived_conv)
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << (BaseToDerivedConversion - 1) << FromTy << ToTy << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9642,9 +9819,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
Qualifiers ToQs = CToTy.getQualifiers();
if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_arc_conv)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9656,10 +9833,10 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
// Emit the generic diagnostic and, optionally, add the hints to it.
PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv);
- FDiag << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I + 1
- << (unsigned) (Cand->Fix.Kind);
+ FDiag << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1
+ << (unsigned)(Cand->Fix.Kind);
// If we can fix the conversion, suggest the FixIts.
for (std::vector<FixItHint>::iterator HI = Cand->Fix.Hints.begin(),
@@ -9732,17 +9909,18 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D,
}
std::string Description;
- OverloadCandidateKind FnKind =
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Found, Fn, Description);
if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName())
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
- << mode << Fn->getParamDecl(0) << NumFormalArgs;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << Description << mode << Fn->getParamDecl(0) << NumFormalArgs;
else
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
- << mode << modeCount << NumFormalArgs;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << Description << mode << modeCount << NumFormalArgs;
+
MaybeEmitInheritedConstructorNote(S, Found);
}
@@ -9783,6 +9961,17 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
return;
}
+ case Sema::TDK_IncompletePack: {
+ assert(ParamD && "no parameter found for incomplete deduction result");
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_incomplete_deduction_pack)
+ << ParamD->getDeclName()
+ << (DeductionFailure.getFirstArg()->pack_size() + 1)
+ << *DeductionFailure.getFirstArg();
+ MaybeEmitInheritedConstructorNote(S, Found);
+ return;
+ }
+
case Sema::TDK_Underqualified: {
assert(ParamD && "no parameter found for bad qualifiers deduction result");
TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
@@ -10017,11 +10206,13 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
CalleeTarget = S.IdentifyCUDATarget(Callee);
std::string FnDesc;
- OverloadCandidateKind FnKind =
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, FnDesc);
S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
- << (unsigned)FnKind << CalleeTarget << CallerTarget;
+ << (unsigned)FnKindPair.first << (unsigned)ocs_non_template
+ << FnDesc /* Ignored */
+ << CalleeTarget << CallerTarget;
// This could be an implicit constructor for which we could not infer the
// target due to a collsion. Diagnose that case.
@@ -10030,7 +10221,7 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
CXXRecordDecl *ParentClass = Meth->getParent();
Sema::CXXSpecialMember CSM;
- switch (FnKind) {
+ switch (FnKindPair.first) {
default:
return;
case oc_implicit_default_constructor:
@@ -10102,12 +10293,12 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
if (Cand->Viable) {
if (Fn->isDeleted() || S.isFunctionConsideredUnavailable(Fn)) {
std::string FnDesc;
- OverloadCandidateKind FnKind =
- ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
- << FnKind << FnDesc
- << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -10176,6 +10367,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
assert(!Available);
break;
}
+ case ovl_non_default_multiversion_function:
+ // Do nothing, these should simply be ignored.
+ break;
}
}
@@ -10257,6 +10451,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
case Sema::TDK_Invalid:
case Sema::TDK_Incomplete:
+ case Sema::TDK_IncompletePack:
return 1;
case Sema::TDK_Underqualified:
@@ -10493,9 +10688,8 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
}
}
-/// PrintOverloadCandidates - When overload resolution fails, prints
-/// diagnostic messages containing the candidates in the candidate
-/// set.
+/// When overload resolution fails, prints diagnostic messages containing the
+/// candidates in the candidate set.
void OverloadCandidateSet::NoteCandidates(
Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args,
StringRef Opc, SourceLocation OpLoc,
@@ -10642,8 +10836,8 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
// in general, want to list every possible builtin candidate.
}
- std::sort(Cands.begin(), Cands.end(),
- CompareTemplateSpecCandidatesForDisplay(S));
+ llvm::sort(Cands.begin(), Cands.end(),
+ CompareTemplateSpecCandidatesForDisplay(S));
// FIXME: Perhaps rename OverloadsShown and getShowOverloads()
// for generalization purposes (?).
@@ -10912,6 +11106,11 @@ private:
if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext))
if (!Caller->isImplicit() && !S.IsAllowedCUDACall(Caller, FunDecl))
return false;
+ if (FunDecl->isMultiVersion()) {
+ const auto *TA = FunDecl->getAttr<TargetAttr>();
+ if (TA && !TA->isDefaultVersion())
+ return false;
+ }
// If any candidate has a placeholder return type, trigger its deduction
// now.
@@ -10993,9 +11192,9 @@ private:
MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates,
SourceExpr->getLocStart(), S.PDiag(),
S.PDiag(diag::err_addr_ovl_ambiguous)
- << Matches[0].second->getDeclName(),
+ << Matches[0].second->getDeclName(),
S.PDiag(diag::note_ovl_candidate)
- << (unsigned)oc_function_template,
+ << (unsigned)oc_function << (unsigned)ocs_described_template,
Complain, TargetFunctionType);
if (Result != MatchesCopy.end()) {
@@ -11157,7 +11356,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
return Fn;
}
-/// \brief Given an expression that refers to an overloaded function, try to
+/// 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.
///
@@ -11193,7 +11392,7 @@ Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E,
return Result;
}
-/// \brief Given an overloaded function, tries to turn it into a non-overloaded
+/// 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
/// requested, potentially perform a function-to-pointer decay.
@@ -11207,7 +11406,8 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(
DeclAccessPair DAP;
FunctionDecl *Found = resolveAddressOfOnlyViableOverloadCandidate(E, DAP);
- if (!Found)
+ if (!Found || Found->isCPUDispatchMultiVersion() ||
+ Found->isCPUSpecificMultiVersion())
return false;
// Emitting multiple diagnostics for a function that is both inaccessible and
@@ -11223,7 +11423,7 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(
return true;
}
-/// \brief Given an expression that refers to an overloaded function, try to
+/// 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
@@ -11309,9 +11509,6 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
return Matched;
}
-
-
-
// Resolve and fix an overloaded expression that can be resolved
// because it identifies a single function template specialization.
//
@@ -11395,7 +11592,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
return true;
}
-/// \brief Add a single candidate to the overload set.
+/// Add a single candidate to the overload set.
static void AddOverloadedCallCandidate(Sema &S,
DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
@@ -11434,7 +11631,7 @@ static void AddOverloadedCallCandidate(Sema &S,
assert(!KnownValid && "unhandled case in overloaded call candidate");
}
-/// \brief Add the overload candidates named by callee and/or found by argument
+/// Add the overload candidates named by callee and/or found by argument
/// dependent lookup to the given overload set.
void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
ArrayRef<Expr *> Args,
@@ -11726,7 +11923,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
RParenLoc);
}
-/// \brief Constructs and populates an OverloadedCandidateSet from
+/// Constructs and populates an OverloadedCandidateSet from
/// the given function.
/// \returns true when an the ExprResult output parameter has been set.
bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
@@ -11866,7 +12063,7 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
<< Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
- // We emitted an error for the unvailable/deleted function call but keep
+ // We emitted an error for the unavailable/deleted function call but keep
// the call in the AST.
FunctionDecl *FDecl = (*Best)->Function;
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
@@ -11932,7 +12129,7 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
(Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
}
-/// \brief Create a unary operation that may resolve to an overloaded
+/// Create a unary operation that may resolve to an overloaded
/// operator.
///
/// \param OpLoc The location of the operator itself (e.g., '*').
@@ -11978,7 +12175,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (Input->isTypeDependent()) {
if (Fns.empty())
return new (Context) UnaryOperator(Input, Opc, Context.DependentTy,
- VK_RValue, OK_Ordinary, OpLoc);
+ VK_RValue, OK_Ordinary, OpLoc, false);
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
UnresolvedLookupExpr *Fn
@@ -12077,7 +12274,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
// break out so that we will build the appropriate built-in
// operator node.
ExprResult InputRes = PerformImplicitConversion(
- Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing);
+ Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing,
+ CCK_ForBuiltinOverloadedOp);
if (InputRes.isInvalid())
return ExprError();
Input = InputRes.get();
@@ -12123,7 +12321,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
-/// \brief Create a binary operation that may resolve to an overloaded
+/// Create a binary operation that may resolve to an overloaded
/// operator.
///
/// \param OpLoc The location of the operator itself (e.g., '+').
@@ -12321,16 +12519,16 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
// operator node.
- ExprResult ArgsRes0 =
- PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0],
- Best->Conversions[0], AA_Passing);
+ ExprResult ArgsRes0 = PerformImplicitConversion(
+ Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.get();
- ExprResult ArgsRes1 =
- PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1],
- Best->Conversions[1], AA_Passing);
+ ExprResult ArgsRes1 = PerformImplicitConversion(
+ Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.get();
@@ -12346,7 +12544,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BO_Comma)
break;
- // For class as left operand for assignment or compound assigment
+ // For class as left operand for assignment or compound assignment
// operator do not fall through to handling in built-in, but report that
// no overloaded assignment operator found
ExprResult Result = ExprError();
@@ -12533,16 +12731,16 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
// operator node.
- ExprResult ArgsRes0 =
- PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0],
- Best->Conversions[0], AA_Passing);
+ ExprResult ArgsRes0 = PerformImplicitConversion(
+ Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.get();
- ExprResult ArgsRes1 =
- PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1],
- Best->Conversions[1], AA_Passing);
+ ExprResult ArgsRes1 = PerformImplicitConversion(
+ Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.get();
@@ -13508,7 +13706,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
VK_RValue, OK_Ordinary,
- UnOp->getOperatorLoc());
+ UnOp->getOperatorLoc(), false);
}
}
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -13519,7 +13717,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
Context.getPointerType(SubExpr->getType()),
VK_RValue, OK_Ordinary,
- UnOp->getOperatorLoc());
+ UnOp->getOperatorLoc(), false);
}
// C++ [except.spec]p17: