diff options
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 456 |
1 files changed, 300 insertions, 156 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 50230f0..a874489 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/PartialDiagnostic.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" #include <algorithm> @@ -388,13 +389,22 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, const unsigned ToWidth = Ctx.getIntWidth(ToType); if (FromWidth > ToWidth || - (FromWidth == ToWidth && FromSigned != ToSigned)) { + (FromWidth == ToWidth && FromSigned != ToSigned) || + (FromSigned && !ToSigned)) { // Not all values of FromType can be represented in ToType. llvm::APSInt InitializerValue; const Expr *Initializer = IgnoreNarrowingConversion(Converted); - if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { - ConstantValue = APValue(InitializerValue); - + if (!Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { + // Such conversions on variables are always narrowing. + return NK_Variable_Narrowing; + } + bool Narrowing = false; + if (FromWidth < ToWidth) { + // Negative -> unsigned is narrowing. Otherwise, more bits is never + // narrowing. + if (InitializerValue.isSigned() && InitializerValue.isNegative()) + Narrowing = true; + } else { // Add a bit to the InitializerValue so we don't have to worry about // signed vs. unsigned comparisons. InitializerValue = InitializerValue.extend( @@ -406,13 +416,13 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth()); ConvertedValue.setIsSigned(InitializerValue.isSigned()); // If the result is different, this was a narrowing conversion. - if (ConvertedValue != InitializerValue) { - ConstantType = Initializer->getType(); - return NK_Constant_Narrowing; - } - } else { - // Variables are always narrowings. - return NK_Variable_Narrowing; + if (ConvertedValue != InitializerValue) + Narrowing = true; + } + if (Narrowing) { + ConstantType = Initializer->getType(); + ConstantValue = APValue(InitializerValue); + return NK_Constant_Narrowing; } } return NK_Not_Narrowing; @@ -541,6 +551,7 @@ static MakeDeductionFailureInfo(ASTContext &Context, TemplateDeductionInfo &Info) { OverloadCandidate::DeductionFailureInfo Result; Result.Result = static_cast<unsigned>(TDK); + Result.HasDiagnostic = false; Result.Data = 0; switch (TDK) { case Sema::TDK_Success: @@ -567,6 +578,12 @@ static MakeDeductionFailureInfo(ASTContext &Context, case Sema::TDK_SubstitutionFailure: Result.Data = Info.take(); + if (Info.hasSFINAEDiagnostic()) { + PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt( + SourceLocation(), PartialDiagnostic::NullDiagnostic()); + Info.takeSFINAEDiagnostic(*Diag); + Result.HasDiagnostic = true; + } break; case Sema::TDK_NonDeducedMismatch: @@ -594,8 +611,12 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { break; case Sema::TDK_SubstitutionFailure: - // FIXME: Destroy the template arugment list? + // FIXME: Destroy the template argument list? Data = 0; + if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) { + Diag->~PartialDiagnosticAt(); + HasDiagnostic = false; + } break; // Unhandled @@ -605,6 +626,13 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { } } +PartialDiagnosticAt * +OverloadCandidate::DeductionFailureInfo::getSFINAEDiagnostic() { + if (HasDiagnostic) + return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic)); + return 0; +} + TemplateParameter OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { @@ -707,9 +735,12 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() { } void OverloadCandidateSet::clear() { - for (iterator i = begin(), e = end(); i != e; ++i) + for (iterator i = begin(), e = end(); i != e; ++i) { for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) i->Conversions[ii].~ImplicitConversionSequence(); + if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction) + i->DeductionFailure.Destroy(); + } NumInlineSequences = 0; Candidates.clear(); Functions.clear(); @@ -1657,7 +1688,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // We have already pre-calculated the promotion type, so this is trivial. if (ToType->isIntegerType() && - !RequireCompleteType(From->getLocStart(), FromType, PDiag())) + !RequireCompleteType(From->getLocStart(), FromType, 0)) return Context.hasSameUnqualifiedType(ToType, FromEnumType->getDecl()->getPromotionType()); } @@ -1987,7 +2018,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, if (getLangOpts().CPlusPlus && FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) && - !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) && + !RequireCompleteType(From->getLocStart(), FromPointeeType, 0) && IsDerivedFrom(FromPointeeType, ToPointeeType)) { ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, @@ -2469,7 +2500,7 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, /// for equality of their argument types. Caller has already checked that /// they have same number of arguments. This routine assumes that Objective-C /// pointer types which only differ in their protocol qualifiers are equal. -/// If the parameters are different, ArgPos will have the the parameter index +/// If the parameters are different, ArgPos will have the parameter index /// of the first different parameter. bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType, const FunctionProtoType *NewType, @@ -2531,13 +2562,17 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, Kind = CK_BitCast; - if (!IsCStyleOrFunctionalCast && - Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy) && - From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) - DiagRuntimeBehavior(From->getExprLoc(), From, - PDiag(diag::warn_impcast_bool_to_null_pointer) - << ToType << From->getSourceRange()); - + if (!IsCStyleOrFunctionalCast && !FromType->isAnyPointerType() && + From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) == + Expr::NPCK_ZeroExpression) { + if (Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy)) + DiagRuntimeBehavior(From->getExprLoc(), From, + PDiag(diag::warn_impcast_bool_to_null_pointer) + << ToType << From->getSourceRange()); + else if (!isUnevaluatedContext()) + Diag(From->getExprLoc(), diag::warn_non_literal_null_pointer) + << ToType << From->getSourceRange(); + } if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) { if (const PointerType *FromPtrType = FromType->getAs<PointerType>()) { QualType FromPointeeType = FromPtrType->getPointeeType(), @@ -2616,7 +2651,7 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToClass(ToTypePtr->getClass(), 0); if (!Context.hasSameUnqualifiedType(FromClass, ToClass) && - !RequireCompleteType(From->getLocStart(), ToClass, PDiag()) && + !RequireCompleteType(From->getLocStart(), ToClass, 0) && IsDerivedFrom(ToClass, FromClass)) { ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(), ToClass.getTypePtr()); @@ -2923,7 +2958,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, S.IsDerivedFrom(From->getType(), ToType))) ConstructorsOnly = true; - S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag()); + S.RequireCompleteType(From->getLocStart(), ToType, 0); // RequireCompleteType may have returned true due to some invalid decl // during template instantiation, but ToType may be complete enough now // to try to recover. @@ -3001,8 +3036,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Enumerate conversion functions, if we're allowed to. if (ConstructorsOnly || isa<InitListExpr>(From)) { - } else if (S.RequireCompleteType(From->getLocStart(), From->getType(), - S.PDiag(0) << From->getSourceRange())) { + } else if (S.RequireCompleteType(From->getLocStart(), From->getType(), 0)) { // No conversion functions from incomplete types. } else if (const RecordType *FromRecordType = From->getType()->getAs<RecordType>()) { @@ -3848,7 +3882,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, ObjCLifetimeConversion = false; if (UnqualT1 == UnqualT2) { // Nothing to do. - } else if (!RequireCompleteType(Loc, OrigT2, PDiag()) && + } else if (!RequireCompleteType(Loc, OrigT2, 0) && IsDerivedFrom(UnqualT2, UnqualT1)) DerivedToBase = true; else if (UnqualT1->isObjCObjectOrInterfaceType() && @@ -4135,7 +4169,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // qualifier. // This is also the point where rvalue references and lvalue inits no longer // go together. - if (!isRValRef && !T1.isConstQualified()) + if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified())) return ICS; // -- If the initializer expression @@ -4313,7 +4347,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // We need a complete type for what follows. Incomplete types can never be // initialized from init lists. - if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag())) + if (S.RequireCompleteType(From->getLocStart(), ToType, 0)) return Result; // C++11 [over.ics.list]p2: @@ -4995,29 +5029,9 @@ static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum) { /// \param Loc The source location of the construct that requires the /// conversion. /// -/// \param FromE The expression we're converting from. -/// -/// \param NotIntDiag The diagnostic to be emitted if the expression does not -/// have integral or enumeration type. -/// -/// \param IncompleteDiag The diagnostic to be emitted if the expression has -/// incomplete class type. +/// \param From The expression we're converting from. /// -/// \param ExplicitConvDiag The diagnostic to be emitted if we're calling an -/// explicit conversion function (because no implicit conversion functions -/// were available). This is a recovery mode. -/// -/// \param ExplicitConvNote The note to be emitted with \p ExplicitConvDiag, -/// showing which conversion was picked. -/// -/// \param AmbigDiag The diagnostic to be emitted if there is more than one -/// conversion function that could convert to integral or enumeration type. -/// -/// \param AmbigNote The note to be emitted with \p AmbigDiag for each -/// usable conversion function. -/// -/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion -/// function, which may be an extension in this case. +/// \param Diagnoser Used to output any diagnostics. /// /// \param AllowScopedEnumerations Specifies whether conversions to scoped /// enumerations should be considered. @@ -5026,13 +5040,7 @@ static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum) { /// successful. ExprResult Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, - const PartialDiagnostic &NotIntDiag, - const PartialDiagnostic &IncompleteDiag, - const PartialDiagnostic &ExplicitConvDiag, - const PartialDiagnostic &ExplicitConvNote, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &AmbigNote, - const PartialDiagnostic &ConvDiag, + ICEConvertDiagnoser &Diagnoser, bool AllowScopedEnumerations) { // We can't perform any more checking for type-dependent expressions. if (From->isTypeDependent()) @@ -5056,13 +5064,25 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, // expression of integral or enumeration type. const RecordType *RecordTy = T->getAs<RecordType>(); if (!RecordTy || !getLangOpts().CPlusPlus) { - if (NotIntDiag.getDiagID()) - Diag(Loc, NotIntDiag) << T << From->getSourceRange(); + if (!Diagnoser.Suppress) + Diagnoser.diagnoseNotInt(*this, Loc, T) << From->getSourceRange(); return Owned(From); } // We must have a complete class type. - if (RequireCompleteType(Loc, T, IncompleteDiag)) + struct TypeDiagnoserPartialDiag : TypeDiagnoser { + ICEConvertDiagnoser &Diagnoser; + Expr *From; + + TypeDiagnoserPartialDiag(ICEConvertDiagnoser &Diagnoser, Expr *From) + : TypeDiagnoser(Diagnoser.Suppress), Diagnoser(Diagnoser), From(From) {} + + virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + Diagnoser.diagnoseIncomplete(S, Loc, T) << From->getSourceRange(); + } + } IncompleteDiagnoser(Diagnoser, From); + + if (RequireCompleteType(Loc, T, IncompleteDiagnoser)) return Owned(From); // Look for a conversion to an integral or enumeration type. @@ -5092,7 +5112,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, switch (ViableConversions.size()) { case 0: - if (ExplicitConversions.size() == 1 && ExplicitConvDiag.getDiagID()) { + if (ExplicitConversions.size() == 1 && !Diagnoser.Suppress) { DeclAccessPair Found = ExplicitConversions[0]; CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); @@ -5104,14 +5124,12 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, std::string TypeStr; ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy()); - Diag(Loc, ExplicitConvDiag) - << T << ConvTy + Diagnoser.diagnoseExplicitConv(*this, Loc, T, ConvTy) << FixItHint::CreateInsertion(From->getLocStart(), "static_cast<" + TypeStr + ">(") << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()), ")"); - Diag(Conversion->getLocation(), ExplicitConvNote) - << ConvTy->isEnumeralType() << ConvTy; + Diagnoser.noteExplicitConv(*this, Conversion, ConvTy); // If we aren't in a SFINAE context, build a call to the // explicit conversion function. @@ -5142,12 +5160,12 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); QualType ConvTy = Conversion->getConversionType().getNonReferenceType(); - if (ConvDiag.getDiagID()) { + if (!Diagnoser.SuppressConversion) { if (isSFINAEContext()) return ExprError(); - Diag(Loc, ConvDiag) - << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange(); + Diagnoser.diagnoseConversion(*this, Loc, T, ConvTy) + << From->getSourceRange(); } ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, @@ -5163,24 +5181,24 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, } default: - if (!AmbigDiag.getDiagID()) - return Owned(From); + if (Diagnoser.Suppress) + return ExprError(); - Diag(Loc, AmbigDiag) - << T << From->getSourceRange(); + Diagnoser.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange(); for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { CXXConversionDecl *Conv = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); QualType ConvTy = Conv->getConversionType().getNonReferenceType(); - Diag(Conv->getLocation(), AmbigNote) - << ConvTy->isEnumeralType() << ConvTy; + Diagnoser.noteAmbiguous(*this, Conv, ConvTy); } return Owned(From); } if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations) && - NotIntDiag.getDiagID()) - Diag(Loc, NotIntDiag) << From->getType() << From->getSourceRange(); + !Diagnoser.Suppress) { + Diagnoser.diagnoseNotInt(*this, Loc, From->getType()) + << From->getSourceRange(); + } return DefaultLvalueConversion(From); } @@ -5190,7 +5208,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, /// @p SuppressUserConversions, then don't allow user-defined /// conversions via constructors or conversion operators. /// -/// \para PartialOverloading true if we are performing "partial" overloading +/// \param PartialOverloading true if we are performing "partial" overloading /// based on an incomplete set of function arguments. This feature is used by /// code completion. void @@ -5906,7 +5924,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, // empty. if (const RecordType *T1Rec = T1->getAs<RecordType>()) { // Complete the type if it can be completed. Otherwise, we're done. - if (RequireCompleteType(OpLoc, T1, PDiag())) + if (RequireCompleteType(OpLoc, T1, 0)) return; LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName); @@ -6098,40 +6116,49 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, const PointerType *PointerTy = Ty->getAs<PointerType>(); bool buildObjCPtr = false; if (!PointerTy) { - if (const ObjCObjectPointerType *PTy = Ty->getAs<ObjCObjectPointerType>()) { - PointeeTy = PTy->getPointeeType(); - buildObjCPtr = true; - } - else - llvm_unreachable("type was not a pointer type!"); - } - else + const ObjCObjectPointerType *PTy = Ty->castAs<ObjCObjectPointerType>(); + PointeeTy = PTy->getPointeeType(); + buildObjCPtr = true; + } else { PointeeTy = PointerTy->getPointeeType(); - + } + // Don't add qualified variants of arrays. For one, they're not allowed // (the qualifier would sink to the element type), and for another, the // only overload situation where it matters is subscript or pointer +- int, // and those shouldn't have qualifier variants anyway. if (PointeeTy->isArrayType()) return true; + unsigned BaseCVR = PointeeTy.getCVRQualifiers(); - if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy)) - BaseCVR = Array->getElementType().getCVRQualifiers(); bool hasVolatile = VisibleQuals.hasVolatile(); bool hasRestrict = VisibleQuals.hasRestrict(); // Iterate through all strict supersets of BaseCVR. for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) { if ((CVR | BaseCVR) != CVR) continue; - // Skip over Volatile/Restrict if no Volatile/Restrict found anywhere - // in the types. + // Skip over volatile if no volatile found anywhere in the types. if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue; - if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue; + + // Skip over restrict if no restrict found anywhere in the types, or if + // the type cannot be restrict-qualified. + if ((CVR & Qualifiers::Restrict) && + (!hasRestrict || + (!(PointeeTy->isAnyPointerType() || PointeeTy->isReferenceType())))) + continue; + + // Build qualified pointee type. QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); + + // Build qualified pointer type. + QualType QPointerTy; if (!buildObjCPtr) - PointerTypes.insert(Context.getPointerType(QPointeeTy)); + QPointerTy = Context.getPointerType(QPointeeTy); else - PointerTypes.insert(Context.getObjCObjectPointerType(QPointeeTy)); + QPointerTy = Context.getObjCObjectPointerType(QPointeeTy); + + // Insert qualified pointer type. + PointerTypes.insert(QPointerTy); } return true; @@ -6328,6 +6355,8 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { // as see them. bool done = false; while (!done) { + if (CanTy.isRestrictQualified()) + VRQuals.addRestrict(); if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>()) CanTy = ResTypePtr->getPointeeType(); else if (const MemberPointerType *ResTypeMPtr = @@ -6337,8 +6366,6 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { done = true; if (CanTy.isVolatileQualified()) VRQuals.addVolatile(); - if (CanTy.isRestrictQualified()) - VRQuals.addRestrict(); if (VRQuals.hasRestrict() && VRQuals.hasVolatile()) return VRQuals; } @@ -6368,12 +6395,12 @@ class BuiltinOperatorOverloadBuilder { // 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 = 18; + static const unsigned LastIntegralType = 20; static const unsigned FirstPromotedIntegralType = 3, - LastPromotedIntegralType = 9; + LastPromotedIntegralType = 11; static const unsigned FirstPromotedArithmeticType = 0, - LastPromotedArithmeticType = 9; - static const unsigned NumArithmeticTypes = 18; + LastPromotedArithmeticType = 11; + static const unsigned NumArithmeticTypes = 20; /// \brief Get the canonical type for a given arithmetic type index. CanQualType getArithmeticType(unsigned index) { @@ -6389,9 +6416,11 @@ class BuiltinOperatorOverloadBuilder { &ASTContext::IntTy, &ASTContext::LongTy, &ASTContext::LongLongTy, + &ASTContext::Int128Ty, &ASTContext::UnsignedIntTy, &ASTContext::UnsignedLongTy, &ASTContext::UnsignedLongLongTy, + &ASTContext::UnsignedInt128Ty, // End of promoted types. &ASTContext::BoolTy, @@ -6404,7 +6433,7 @@ class BuiltinOperatorOverloadBuilder { &ASTContext::UnsignedCharTy, &ASTContext::UnsignedShortTy, // End of integral types. - // FIXME: What about complex? + // FIXME: What about complex? What about half? }; return S.Context.*ArithmeticTypes[index]; } @@ -6423,20 +6452,24 @@ class BuiltinOperatorOverloadBuilder { // *except* when dealing with signed types of higher rank. // (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 { - Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL, Dep=-1 + Dep=-1, + Flt, Dbl, LDbl, SI, SL, SLL, S128, UI, UL, ULL, U128 }; - static PromotedType ConversionsTable[LastPromotedArithmeticType] + static const PromotedType ConversionsTable[LastPromotedArithmeticType] [LastPromotedArithmeticType] = { - /* Flt*/ { Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt }, - /* Dbl*/ { Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl }, - /*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl }, - /* SI*/ { Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL }, - /* SL*/ { Flt, Dbl, LDbl, SL, SL, SLL, Dep, UL, ULL }, - /* SLL*/ { Flt, Dbl, LDbl, SLL, SLL, SLL, Dep, Dep, ULL }, - /* UI*/ { Flt, Dbl, LDbl, UI, Dep, Dep, UI, UL, ULL }, - /* UL*/ { Flt, Dbl, LDbl, UL, UL, Dep, UL, UL, ULL }, - /* ULL*/ { Flt, Dbl, LDbl, ULL, ULL, ULL, ULL, ULL, ULL }, +/* Flt*/ { Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt, Flt, Flt }, +/* Dbl*/ { Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl }, +/*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl }, +/* SI*/ { Flt, Dbl, LDbl, SI, SL, SLL, S128, UI, UL, ULL, U128 }, +/* SL*/ { Flt, Dbl, LDbl, SL, SL, SLL, S128, Dep, UL, ULL, U128 }, +/* SLL*/ { Flt, Dbl, LDbl, SLL, SLL, SLL, S128, Dep, Dep, ULL, U128 }, +/*S128*/ { Flt, Dbl, LDbl, S128, S128, S128, S128, S128, S128, S128, U128 }, +/* UI*/ { Flt, Dbl, LDbl, UI, Dep, Dep, S128, UI, UL, ULL, U128 }, +/* UL*/ { Flt, Dbl, LDbl, UL, UL, Dep, S128, UL, UL, ULL, U128 }, +/* ULL*/ { Flt, Dbl, LDbl, ULL, ULL, ULL, S128, ULL, ULL, ULL, U128 }, +/*U128*/ { Flt, Dbl, LDbl, U128, U128, U128, U128, U128, U128, U128, U128 }, }; assert(L < LastPromotedArithmeticType); @@ -6466,7 +6499,8 @@ class BuiltinOperatorOverloadBuilder { /// \brief Helper method to factor out the common pattern of adding overloads /// for '++' and '--' builtin operators. void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy, - bool HasVolatile) { + bool HasVolatile, + bool HasRestrict) { QualType ParamTypes[2] = { S.Context.getLValueReferenceType(CandidateTy), S.Context.IntTy @@ -6489,6 +6523,33 @@ class BuiltinOperatorOverloadBuilder { else S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet); } + + // Add restrict version only if there are conversions to a restrict type + // and our candidate type is a non-restrict-qualified pointer. + if (HasRestrict && CandidateTy->isAnyPointerType() && + !CandidateTy.isRestrictQualified()) { + ParamTypes[0] + = S.Context.getLValueReferenceType( + S.Context.getCVRQualifiedType(CandidateTy, Qualifiers::Restrict)); + if (NumArgs == 1) + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); + else + S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet); + + if (HasVolatile) { + ParamTypes[0] + = S.Context.getLValueReferenceType( + S.Context.getCVRQualifiedType(CandidateTy, + (Qualifiers::Volatile | + Qualifiers::Restrict))); + if (NumArgs == 1) + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, + CandidateSet); + else + S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet); + } + } + } public: @@ -6508,13 +6569,13 @@ public: assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy && "Invalid first promoted integral type"); assert(getArithmeticType(LastPromotedIntegralType - 1) - == S.Context.UnsignedLongLongTy && + == S.Context.UnsignedInt128Ty && "Invalid last promoted integral type"); assert(getArithmeticType(FirstPromotedArithmeticType) == S.Context.FloatTy && "Invalid first promoted arithmetic type"); assert(getArithmeticType(LastPromotedArithmeticType - 1) - == S.Context.UnsignedLongLongTy && + == S.Context.UnsignedInt128Ty && "Invalid last promoted arithmetic type"); } @@ -6543,7 +6604,8 @@ public: Arith < NumArithmeticTypes; ++Arith) { addPlusPlusMinusMinusStyleOverloads( getArithmeticType(Arith), - VisibleTypeConversionsQuals.hasVolatile()); + VisibleTypeConversionsQuals.hasVolatile(), + VisibleTypeConversionsQuals.hasRestrict()); } } @@ -6567,8 +6629,10 @@ public: continue; addPlusPlusMinusMinusStyleOverloads(*Ptr, - (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && - VisibleTypeConversionsQuals.hasVolatile())); + (!(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile()), + (!(*Ptr).isRestrictQualified() && + VisibleTypeConversionsQuals.hasRestrict())); } } @@ -7026,14 +7090,36 @@ public: S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, /*IsAssigmentOperator=*/ isEqualOp); - if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && - VisibleTypeConversionsQuals.hasVolatile()) { + bool NeedVolatile = !(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile(); + if (NeedVolatile) { // volatile version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } + + if (!(*Ptr).isRestrictQualified() && + VisibleTypeConversionsQuals.hasRestrict()) { + // restrict version + ParamTypes[0] + = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + + if (NeedVolatile) { + // volatile restrict version + ParamTypes[0] + = S.Context.getLValueReferenceType( + S.Context.getCVRQualifiedType(*Ptr, + (Qualifiers::Volatile | + Qualifiers::Restrict))); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + } + } } if (isEqualOp) { @@ -7054,14 +7140,36 @@ public: S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, /*IsAssigmentOperator=*/true); - if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && - VisibleTypeConversionsQuals.hasVolatile()) { + bool NeedVolatile = !(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile(); + if (NeedVolatile) { // volatile version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, /*IsAssigmentOperator=*/true); } + + if (!(*Ptr).isRestrictQualified() && + VisibleTypeConversionsQuals.hasRestrict()) { + // restrict version + ParamTypes[0] + = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, /*IsAssigmentOperator=*/true); + + if (NeedVolatile) { + // volatile restrict version + ParamTypes[0] + = S.Context.getLValueReferenceType( + S.Context.getCVRQualifiedType(*Ptr, + (Qualifiers::Volatile | + Qualifiers::Restrict))); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, /*IsAssigmentOperator=*/true); + + } + } } } } @@ -7705,13 +7813,11 @@ isBetterOverloadCandidate(Sema &S, /// \brief Computes the best viable function (C++ 13.3.3) /// within an overload candidate set. /// -/// \param CandidateSet the set of candidate functions. -/// -/// \param Loc the location of the function name (or operator symbol) for +/// \param Loc The location of the function name (or operator symbol) for /// which overload resolution occurs. /// -/// \param Best f overload resolution was successful or found a deleted -/// function, Best points to the candidate function found. +/// \param Best If overload resolution was successful or found a deleted +/// function, \p Best points to the candidate function found. /// /// \returns The result of overload resolution. OverloadingResult @@ -8035,12 +8141,22 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { FromIface->isSuperClassOf(ToIface)) BaseToDerivedConversion = 2; } else if (const ReferenceType *ToRefTy = ToTy->getAs<ReferenceType>()) { - if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) && - !FromTy->isIncompleteType() && - !ToRefTy->getPointeeType()->isIncompleteType() && - S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) - BaseToDerivedConversion = 3; + if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) && + !FromTy->isIncompleteType() && + !ToRefTy->getPointeeType()->isIncompleteType() && + S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) { + BaseToDerivedConversion = 3; + } else if (ToTy->isLValueReferenceType() && !FromExpr->isLValue() && + 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; + MaybeEmitInheritedConstructorNote(S, Fn); + return; } + } if (BaseToDerivedConversion) { S.Diag(Fn->getLocation(), @@ -8127,9 +8243,14 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, std::string Description; OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description); - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity) - << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode - << modeCount << NumFormalArgs; + if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName()) + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one) + << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode + << Fn->getParamDecl(0) << NumFormalArgs; + else + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity) + << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode + << modeCount << NumFormalArgs; MaybeEmitInheritedConstructorNote(S, Fn); } @@ -8232,14 +8353,39 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, return; case Sema::TDK_SubstitutionFailure: { - std::string ArgString; - if (TemplateArgumentList *Args - = Cand->DeductionFailure.getTemplateArgumentList()) - ArgString = S.getTemplateArgumentBindingsText( - Fn->getDescribedFunctionTemplate()->getTemplateParameters(), - *Args); + // Format the template argument list into the argument string. + llvm::SmallString<128> TemplateArgString; + if (TemplateArgumentList *Args = + Cand->DeductionFailure.getTemplateArgumentList()) { + TemplateArgString = " "; + TemplateArgString += S.getTemplateArgumentBindingsText( + Fn->getDescribedFunctionTemplate()->getTemplateParameters(), *Args); + } + + // If this candidate was disabled by enable_if, say so. + PartialDiagnosticAt *PDiag = Cand->DeductionFailure.getSFINAEDiagnostic(); + if (PDiag && PDiag->second.getDiagID() == + diag::err_typename_nested_not_found_enable_if) { + // FIXME: Use the source range of the condition, and the fully-qualified + // name of the enable_if template. These are both present in PDiag. + S.Diag(PDiag->first, diag::note_ovl_candidate_disabled_by_enable_if) + << "'enable_if'" << TemplateArgString; + return; + } + + // Format the SFINAE diagnostic into the argument string. + // FIXME: Add a general mechanism to include a PartialDiagnostic *'s + // formatted message in another diagnostic. + llvm::SmallString<128> SFINAEArgString; + SourceRange R; + if (PDiag) { + SFINAEArgString = ": "; + R = SourceRange(PDiag->first, PDiag->first); + PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString); + } + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure) - << ArgString; + << TemplateArgString << SFINAEArgString << R; MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -9190,7 +9336,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( return true; } - // Fix the expresion to refer to 'fn'. + // Fix the expression to refer to 'fn'. SingleFunctionExpression = Owned(FixOverloadedFunctionReference(SrcExpr.take(), found, fn)); @@ -9692,14 +9838,14 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) { /// \param OpcIn The UnaryOperator::Opcode that describes this /// operator. /// -/// \param Functions The set of non-member functions that will be +/// \param Fns The set of non-member functions that will be /// considered by overload resolution. The caller needs to build this /// set based on the context using, e.g., /// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This /// set should not contain any member functions; those will be added /// by CreateOverloadedUnaryOp(). /// -/// \param input The input argument. +/// \param Input The input argument. ExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, const UnresolvedSetImpl &Fns, @@ -9892,7 +10038,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, /// \param OpcIn The BinaryOperator::Opcode that describes this /// operator. /// -/// \param Functions The set of non-member functions that will be +/// \param Fns The set of non-member functions that will be /// considered by overload resolution. The caller needs to build this /// set based on the context using, e.g., /// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This @@ -10559,7 +10705,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs); - if (CheckFunctionCall(Method, TheCall)) + if (CheckFunctionCall(Method, TheCall, Proto)) return ExprError(); if ((isa<CXXConstructorDecl>(CurContext) || @@ -10610,8 +10756,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); if (RequireCompleteType(LParenLoc, Object.get()->getType(), - PDiag(diag::err_incomplete_object_call) - << Object.get()->getSourceRange())) + diag::err_incomplete_object_call, Object.get())) return true; LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName); @@ -10857,7 +11002,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // If this is a variadic call, handle args passed through "...". if (Proto->isVariadic()) { // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = NumArgsInProto; i != NumArgs; i++) { + for (unsigned i = NumArgsInProto; i < NumArgs; i++) { ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); IsError |= Arg.isInvalid(); TheCall->setArg(i + 1, Arg.take()); @@ -10868,7 +11013,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs); - if (CheckFunctionCall(Method, TheCall)) + if (CheckFunctionCall(Method, TheCall, Proto)) return true; return MaybeBindToTemporary(TheCall); @@ -10899,8 +11044,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { const RecordType *BaseRecord = Base->getType()->getAs<RecordType>(); if (RequireCompleteType(Loc, Base->getType(), - PDiag(diag::err_typecheck_incomplete_tag) - << Base->getSourceRange())) + diag::err_typecheck_incomplete_tag, Base)) return ExprError(); LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName); @@ -11049,7 +11193,7 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD)) return ExprError(); - if (CheckFunctionCall(FD, UDL)) + if (CheckFunctionCall(FD, UDL, NULL)) return ExprError(); return MaybeBindToTemporary(UDL); |