| //===--- SemaOverload.cpp - C++ Overloading -------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file provides Sema routines for C++ overloading. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/CXXInheritance.h" |
| #include "clang/AST/DeclObjC.h" |
| #include "clang/AST/DependenceFlags.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/ExprObjC.h" |
| #include "clang/AST/TypeOrdering.h" |
| #include "clang/Basic/Diagnostic.h" |
| #include "clang/Basic/DiagnosticOptions.h" |
| #include "clang/Basic/PartialDiagnostic.h" |
| #include "clang/Basic/SourceManager.h" |
| #include "clang/Basic/TargetInfo.h" |
| #include "clang/Sema/Initialization.h" |
| #include "clang/Sema/Lookup.h" |
| #include "clang/Sema/Overload.h" |
| #include "clang/Sema/SemaInternal.h" |
| #include "clang/Sema/Template.h" |
| #include "clang/Sema/TemplateDeduction.h" |
| #include "llvm/ADT/DenseSet.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/SmallPtrSet.h" |
| #include "llvm/ADT/SmallString.h" |
| #include <algorithm> |
| #include <cstdlib> |
| |
| using namespace clang; |
| using namespace sema; |
| |
| using AllowedExplicit = Sema::AllowedExplicit; |
| |
| static bool functionHasPassObjectSizeParams(const FunctionDecl *FD) { |
| return llvm::any_of(FD->parameters(), [](const ParmVarDecl *P) { |
| return P->hasAttr<PassObjectSizeAttr>(); |
| }); |
| } |
| |
| /// A convenience routine for creating a decayed reference to a function. |
| static ExprResult |
| CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, |
| const Expr *Base, bool HadMultipleCandidates, |
| SourceLocation Loc = SourceLocation(), |
| const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){ |
| if (S.DiagnoseUseOfDecl(FoundDecl, Loc)) |
| return ExprError(); |
| // If FoundDecl is different from Fn (such as if one is a template |
| // and the other a specialization), make sure DiagnoseUseOfDecl is |
| // called on both. |
| // FIXME: This would be more comprehensively addressed by modifying |
| // DiagnoseUseOfDecl to accept both the FoundDecl and the decl |
| // being used. |
| if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc)) |
| return ExprError(); |
| DeclRefExpr *DRE = new (S.Context) |
| DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); |
| if (HadMultipleCandidates) |
| DRE->setHadMultipleCandidates(true); |
| |
| S.MarkDeclRefReferenced(DRE, Base); |
| if (auto *FPT = DRE->getType()->getAs<FunctionProtoType>()) { |
| if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) { |
| S.ResolveExceptionSpec(Loc, FPT); |
| DRE->setType(Fn->getType()); |
| } |
| } |
| return S.ImpCastExprToType(DRE, S.Context.getPointerType(DRE->getType()), |
| CK_FunctionToPointerDecay); |
| } |
| |
| static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, |
| bool InOverloadResolution, |
| StandardConversionSequence &SCS, |
| bool CStyle, |
| bool AllowObjCWritebackConversion); |
| |
| static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From, |
| QualType &ToType, |
| bool InOverloadResolution, |
| StandardConversionSequence &SCS, |
| bool CStyle); |
| static OverloadingResult |
| IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, |
| UserDefinedConversionSequence& User, |
| OverloadCandidateSet& Conversions, |
| AllowedExplicit AllowExplicit, |
| bool AllowObjCConversionOnExplicit); |
| |
| static ImplicitConversionSequence::CompareKind |
| CompareStandardConversionSequences(Sema &S, SourceLocation Loc, |
| const StandardConversionSequence& SCS1, |
| const StandardConversionSequence& SCS2); |
| |
| static ImplicitConversionSequence::CompareKind |
| CompareQualificationConversions(Sema &S, |
| const StandardConversionSequence& SCS1, |
| const StandardConversionSequence& SCS2); |
| |
| static ImplicitConversionSequence::CompareKind |
| CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, |
| const StandardConversionSequence& SCS1, |
| const StandardConversionSequence& SCS2); |
| |
| /// GetConversionRank - Retrieve the implicit conversion rank |
| /// corresponding to the given implicit conversion kind. |
| ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { |
| static const ImplicitConversionRank |
| Rank[(int)ICK_Num_Conversion_Kinds] = { |
| ICR_Exact_Match, |
| ICR_Exact_Match, |
| ICR_Exact_Match, |
| ICR_Exact_Match, |
| ICR_Exact_Match, |
| ICR_Exact_Match, |
| ICR_Promotion, |
| ICR_Promotion, |
| ICR_Promotion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_OCL_Scalar_Widening, |
| ICR_Complex_Real_Conversion, |
| ICR_Conversion, |
| ICR_Conversion, |
| ICR_Writeback_Conversion, |
| ICR_Exact_Match, // NOTE(gbiv): This may not be completely right -- |
| // it was omitted by the patch that added |
| // ICK_Zero_Event_Conversion |
| ICR_C_Conversion, |
| ICR_C_Conversion_Extension |
| }; |
| return Rank[(int)Kind]; |
| } |
| |
| /// GetImplicitConversionName - Return the name of this kind of |
| /// implicit conversion. |
| static const char* GetImplicitConversionName(ImplicitConversionKind Kind) { |
| static const char* const Name[(int)ICK_Num_Conversion_Kinds] = { |
| "No conversion", |
| "Lvalue-to-rvalue", |
| "Array-to-pointer", |
| "Function-to-pointer", |
| "Function pointer conversion", |
| "Qualification", |
| "Integral promotion", |
| "Floating point promotion", |
| "Complex promotion", |
| "Integral conversion", |
| "Floating conversion", |
| "Complex conversion", |
| "Floating-integral conversion", |
| "Pointer conversion", |
| "Pointer-to-member conversion", |
| "Boolean conversion", |
| "Compatible-types conversion", |
| "Derived-to-base conversion", |
| "Vector conversion", |
| "SVE Vector conversion", |
| "Vector splat", |
| "Complex-real conversion", |
| "Block Pointer conversion", |
| "Transparent Union Conversion", |
| "Writeback conversion", |
| "OpenCL Zero Event Conversion", |
| "C specific type conversion", |
| "Incompatible pointer conversion" |
| }; |
| return Name[Kind]; |
| } |
| |
| /// StandardConversionSequence - Set the standard conversion |
| /// sequence to the identity conversion. |
| void StandardConversionSequence::setAsIdentityConversion() { |
| First = ICK_Identity; |
| Second = ICK_Identity; |
| Third = ICK_Identity; |
| DeprecatedStringLiteralToCharPtr = false; |
| QualificationIncludesObjCLifetime = false; |
| ReferenceBinding = false; |
| DirectBinding = false; |
| IsLvalueReference = true; |
| BindsToFunctionLvalue = false; |
| BindsToRvalue = false; |
| BindsImplicitObjectArgumentWithoutRefQualifier = false; |
| ObjCLifetimeConversionBinding = false; |
| CopyConstructor = nullptr; |
| } |
| |
| /// getRank - Retrieve the rank of this standard conversion sequence |
| /// (C++ 13.3.3.1.1p3). The rank is the largest rank of each of the |
| /// implicit conversions. |
| ImplicitConversionRank StandardConversionSequence::getRank() const { |
| ImplicitConversionRank Rank = ICR_Exact_Match; |
| if (GetConversionRank(First) > Rank) |
| Rank = GetConversionRank(First); |
| if (GetConversionRank(Second) > Rank) |
| Rank = GetConversionRank(Second); |
| if (GetConversionRank(Third) > Rank) |
| Rank = GetConversionRank(Third); |
| return Rank; |
| } |
| |
| /// isPointerConversionToBool - Determines whether this conversion is |
| /// a conversion of a pointer or pointer-to-member to bool. This is |
| /// used as part of the ranking of standard conversion sequences |
| /// (C++ 13.3.3.2p4). |
| bool StandardConversionSequence::isPointerConversionToBool() const { |
| // Note that FromType has not necessarily been transformed by the |
| // array-to-pointer or function-to-pointer implicit conversions, so |
| // check for their presence as well as checking whether FromType is |
| // a pointer. |
| if (getToType(1)->isBooleanType() && |
| (getFromType()->isPointerType() || |
| getFromType()->isMemberPointerType() || |
| getFromType()->isObjCObjectPointerType() || |
| getFromType()->isBlockPointerType() || |
| First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer)) |
| return true; |
| |
| return false; |
| } |
| |
| /// isPointerConversionToVoidPointer - Determines whether this |
| /// conversion is a conversion of a pointer to a void pointer. This is |
| /// used as part of the ranking of standard conversion sequences (C++ |
| /// 13.3.3.2p4). |
| bool |
| StandardConversionSequence:: |
| isPointerConversionToVoidPointer(ASTContext& Context) const { |
| QualType FromType = getFromType(); |
| QualType ToType = getToType(1); |
| |
| // Note that FromType has not necessarily been transformed by the |
| // array-to-pointer implicit conversion, so check for its presence |
| // and redo the conversion to get a pointer. |
| if (First == ICK_Array_To_Pointer) |
| FromType = Context.getArrayDecayedType(FromType); |
| |
| if (Second == ICK_Pointer_Conversion && FromType->isAnyPointerType()) |
| if (const PointerType* ToPtrType = ToType->getAs<PointerType>()) |
| return ToPtrType->getPointeeType()->isVoidType(); |
| |
| return false; |
| } |
| |
| /// Skip any implicit casts which could be either part of a narrowing conversion |
| /// or after one in an implicit conversion. |
| static const Expr *IgnoreNarrowingConversion(ASTContext &Ctx, |
| const Expr *Converted) { |
| // We can have cleanups wrapping the converted expression; these need to be |
| // preserved so that destructors run if necessary. |
| if (auto *EWC = dyn_cast<ExprWithCleanups>(Converted)) { |
| Expr *Inner = |
| const_cast<Expr *>(IgnoreNarrowingConversion(Ctx, EWC->getSubExpr())); |
| return ExprWithCleanups::Create(Ctx, Inner, EWC->cleanupsHaveSideEffects(), |
| EWC->getObjects()); |
| } |
| |
| while (auto *ICE = dyn_cast<ImplicitCastExpr>(Converted)) { |
| switch (ICE->getCastKind()) { |
| case CK_NoOp: |
| case CK_IntegralCast: |
| case CK_IntegralToBoolean: |
| case CK_IntegralToFloating: |
| case CK_BooleanToSignedIntegral: |
| case CK_FloatingToIntegral: |
| case CK_FloatingToBoolean: |
| case CK_FloatingCast: |
| Converted = ICE->getSubExpr(); |
| continue; |
| |
| default: |
| return Converted; |
| } |
| } |
| |
| return Converted; |
| } |
| |
| /// Check if this standard conversion sequence represents a narrowing |
| /// conversion, according to C++11 [dcl.init.list]p7. |
| /// |
| /// \param Ctx The AST context. |
| /// \param Converted The result of applying this standard conversion sequence. |
| /// \param ConstantValue If this is an NK_Constant_Narrowing conversion, the |
| /// 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. |
| /// \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: |
| // A narrowing conversion is an implicit conversion ... |
| QualType FromType = getToType(0); |
| QualType ToType = getToType(1); |
| |
| // A conversion to an enumeration type is narrowing if the conversion to |
| // the underlying type is narrowing. This only arises for expressions of |
| // the form 'Enum{init}'. |
| if (auto *ET = ToType->getAs<EnumType>()) |
| ToType = ET->getDecl()->getIntegerType(); |
| |
| switch (Second) { |
| // 'bool' is an integral type; dispatch to the right place to handle it. |
| case ICK_Boolean_Conversion: |
| if (FromType->isRealFloatingType()) |
| goto FloatingIntegralConversion; |
| if (FromType->isIntegralOrUnscopedEnumerationType()) |
| goto IntegralConversion; |
| // -- from a pointer type or pointer-to-member type to bool, or |
| return NK_Type_Narrowing; |
| |
| // -- from a floating-point type to an integer type, or |
| // |
| // -- from an integer type or unscoped enumeration type to a floating-point |
| // type, except where the source is a constant expression and the actual |
| // value after conversion will fit into the target type and will produce |
| // the original value when converted back to the original type, or |
| case ICK_Floating_Integral: |
| FloatingIntegralConversion: |
| if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) { |
| return NK_Type_Narrowing; |
| } else if (FromType->isIntegralOrUnscopedEnumerationType() && |
| ToType->isRealFloatingType()) { |
| if (IgnoreFloatToIntegralConversion) |
| return NK_Not_Narrowing; |
| const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); |
| assert(Initializer && "Unknown conversion expression"); |
| |
| // If it's value-dependent, we can't tell whether it's narrowing. |
| if (Initializer->isValueDependent()) |
| return NK_Dependent_Narrowing; |
| |
| if (Optional<llvm::APSInt> IntConstantValue = |
| Initializer->getIntegerConstantExpr(Ctx)) { |
| // Convert the integer to the floating type. |
| llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType)); |
| Result.convertFromAPInt(*IntConstantValue, IntConstantValue->isSigned(), |
| llvm::APFloat::rmNearestTiesToEven); |
| // And back. |
| llvm::APSInt ConvertedValue = *IntConstantValue; |
| bool ignored; |
| Result.convertToInteger(ConvertedValue, |
| llvm::APFloat::rmTowardZero, &ignored); |
| // If the resulting value is different, this was a narrowing conversion. |
| if (*IntConstantValue != ConvertedValue) { |
| ConstantValue = APValue(*IntConstantValue); |
| ConstantType = Initializer->getType(); |
| return NK_Constant_Narrowing; |
| } |
| } else { |
| // Variables are always narrowings. |
| return NK_Variable_Narrowing; |
| } |
| } |
| return NK_Not_Narrowing; |
| |
| // -- from long double to double or float, or from double to float, except |
| // where the source is a constant expression and the actual value after |
| // conversion is within the range of values that can be represented (even |
| // if it cannot be represented exactly), or |
| case ICK_Floating_Conversion: |
| if (FromType->isRealFloatingType() && ToType->isRealFloatingType() && |
| Ctx.getFloatingTypeOrder(FromType, ToType) == 1) { |
| // FromType is larger than ToType. |
| const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); |
| |
| // If it's value-dependent, we can't tell whether it's narrowing. |
| if (Initializer->isValueDependent()) |
| return NK_Dependent_Narrowing; |
| |
| if (Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) { |
| // Constant! |
| assert(ConstantValue.isFloat()); |
| llvm::APFloat FloatVal = ConstantValue.getFloat(); |
| // Convert the source value into the target type. |
| bool ignored; |
| llvm::APFloat::opStatus ConvertStatus = FloatVal.convert( |
| Ctx.getFloatTypeSemantics(ToType), |
| llvm::APFloat::rmNearestTiesToEven, &ignored); |
| // If there was no overflow, the source value is within the range of |
| // values that can be represented. |
| if (ConvertStatus & llvm::APFloat::opOverflow) { |
| ConstantType = Initializer->getType(); |
| return NK_Constant_Narrowing; |
| } |
| } else { |
| return NK_Variable_Narrowing; |
| } |
| } |
| return NK_Not_Narrowing; |
| |
| // -- from an integer type or unscoped enumeration type to an integer type |
| // that cannot represent all the values of the original type, except where |
| // the source is a constant expression and the actual value after |
| // conversion will fit into the target type and will produce the original |
| // value when converted back to the original type. |
| case ICK_Integral_Conversion: |
| IntegralConversion: { |
| assert(FromType->isIntegralOrUnscopedEnumerationType()); |
| assert(ToType->isIntegralOrUnscopedEnumerationType()); |
| const bool FromSigned = FromType->isSignedIntegerOrEnumerationType(); |
| const unsigned FromWidth = Ctx.getIntWidth(FromType); |
| const bool ToSigned = ToType->isSignedIntegerOrEnumerationType(); |
| const unsigned ToWidth = Ctx.getIntWidth(ToType); |
| |
| if (FromWidth > ToWidth || |
| (FromWidth == ToWidth && FromSigned != ToSigned) || |
| (FromSigned && !ToSigned)) { |
| // Not all values of FromType can be represented in ToType. |
| const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); |
| |
| // If it's value-dependent, we can't tell whether it's narrowing. |
| if (Initializer->isValueDependent()) |
| return NK_Dependent_Narrowing; |
| |
| Optional<llvm::APSInt> OptInitializerValue; |
| if (!(OptInitializerValue = Initializer->getIntegerConstantExpr(Ctx))) { |
| // Such conversions on variables are always narrowing. |
| return NK_Variable_Narrowing; |
| } |
| llvm::APSInt &InitializerValue = *OptInitializerValue; |
| 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( |
| InitializerValue.getBitWidth() + 1); |
| // Convert the initializer to and from the target width and signed-ness. |
| llvm::APSInt ConvertedValue = InitializerValue; |
| ConvertedValue = ConvertedValue.trunc(ToWidth); |
| ConvertedValue.setIsSigned(ToSigned); |
| ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth()); |
| ConvertedValue.setIsSigned(InitializerValue.isSigned()); |
| // If the result is different, this was a narrowing conversion. |
| if (ConvertedValue != InitializerValue) |
| Narrowing = true; |
| } |
| if (Narrowing) { |
| ConstantType = Initializer->getType(); |
| ConstantValue = APValue(InitializerValue); |
| return NK_Constant_Narrowing; |
| } |
| } |
| return NK_Not_Narrowing; |
| } |
| |
| default: |
| // Other kinds of conversions are not narrowings. |
| return NK_Not_Narrowing; |
| } |
| } |
| |
| /// dump - Print this standard conversion sequence to standard |
| /// error. Useful for debugging overloading issues. |
| LLVM_DUMP_METHOD void StandardConversionSequence::dump() const { |
| raw_ostream &OS = llvm::errs(); |
| bool PrintedSomething = false; |
| if (First != ICK_Identity) { |
| OS << GetImplicitConversionName(First); |
| PrintedSomething = true; |
| } |
| |
| if (Second != ICK_Identity) { |
| if (PrintedSomething) { |
| OS << " -> "; |
| } |
| OS << GetImplicitConversionName(Second); |
| |
| if (CopyConstructor) { |
| OS << " (by copy constructor)"; |
| } else if (DirectBinding) { |
| OS << " (direct reference binding)"; |
| } else if (ReferenceBinding) { |
| OS << " (reference binding)"; |
| } |
| PrintedSomething = true; |
| } |
| |
| if (Third != ICK_Identity) { |
| if (PrintedSomething) { |
| OS << " -> "; |
| } |
| OS << GetImplicitConversionName(Third); |
| PrintedSomething = true; |
| } |
| |
| if (!PrintedSomething) { |
| OS << "No conversions required"; |
| } |
| } |
| |
| /// dump - Print this user-defined conversion sequence to standard |
| /// error. Useful for debugging overloading issues. |
| void UserDefinedConversionSequence::dump() const { |
| raw_ostream &OS = llvm::errs(); |
| if (Before.First || Before.Second || Before.Third) { |
| Before.dump(); |
| OS << " -> "; |
| } |
| if (ConversionFunction) |
| OS << '\'' << *ConversionFunction << '\''; |
| else |
| OS << "aggregate initialization"; |
| if (After.First || After.Second || After.Third) { |
| OS << " -> "; |
| After.dump(); |
| } |
| } |
| |
| /// dump - Print this implicit conversion sequence to standard |
| /// error. Useful for debugging overloading issues. |
| void ImplicitConversionSequence::dump() const { |
| raw_ostream &OS = llvm::errs(); |
| if (hasInitializerListContainerType()) |
| OS << "Worst list element conversion: "; |
| switch (ConversionKind) { |
| case StandardConversion: |
| OS << "Standard conversion: "; |
| Standard.dump(); |
| break; |
| case UserDefinedConversion: |
| OS << "User-defined conversion: "; |
| UserDefined.dump(); |
| break; |
| case EllipsisConversion: |
| OS << "Ellipsis conversion"; |
| break; |
| case AmbiguousConversion: |
| OS << "Ambiguous conversion"; |
| break; |
| case BadConversion: |
| OS << "Bad conversion"; |
| break; |
| } |
| |
| OS << "\n"; |
| } |
| |
| void AmbiguousConversionSequence::construct() { |
| new (&conversions()) ConversionSet(); |
| } |
| |
| void AmbiguousConversionSequence::destruct() { |
| conversions().~ConversionSet(); |
| } |
| |
| void |
| AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) { |
| FromTypePtr = O.FromTypePtr; |
| ToTypePtr = O.ToTypePtr; |
| new (&conversions()) ConversionSet(O.conversions()); |
| } |
| |
| namespace { |
| // Structure used by DeductionFailureInfo to store |
| // template argument information. |
| struct DFIArguments { |
| TemplateArgument FirstArg; |
| TemplateArgument SecondArg; |
| }; |
| // Structure used by DeductionFailureInfo to store |
| // template parameter and template argument information. |
| struct DFIParamWithArguments : DFIArguments { |
| TemplateParameter Param; |
| }; |
| // Structure used by DeductionFailureInfo to store template argument |
| // information and the index of the problematic call argument. |
| struct DFIDeducedMismatchArgs : DFIArguments { |
| TemplateArgumentList *TemplateArgs; |
| unsigned CallArgIndex; |
| }; |
| // Structure used by DeductionFailureInfo to store information about |
| // unsatisfied constraints. |
| struct CNSInfo { |
| TemplateArgumentList *TemplateArgs; |
| ConstraintSatisfaction Satisfaction; |
| }; |
| } |
| |
| /// Convert from Sema's representation of template deduction information |
| /// to the form used in overload-candidate information. |
| DeductionFailureInfo |
| clang::MakeDeductionFailureInfo(ASTContext &Context, |
| Sema::TemplateDeductionResult TDK, |
| TemplateDeductionInfo &Info) { |
| DeductionFailureInfo Result; |
| Result.Result = static_cast<unsigned>(TDK); |
| Result.HasDiagnostic = false; |
| switch (TDK) { |
| case Sema::TDK_Invalid: |
| case Sema::TDK_InstantiationDepth: |
| case Sema::TDK_TooManyArguments: |
| case Sema::TDK_TooFewArguments: |
| case Sema::TDK_MiscellaneousDeductionFailure: |
| case Sema::TDK_CUDATargetMismatch: |
| Result.Data = nullptr; |
| break; |
| |
| case Sema::TDK_Incomplete: |
| case Sema::TDK_InvalidExplicitArguments: |
| Result.Data = Info.Param.getOpaqueValue(); |
| break; |
| |
| case Sema::TDK_DeducedMismatch: |
| case Sema::TDK_DeducedMismatchNested: { |
| // FIXME: Should allocate from normal heap so that we can free this later. |
| auto *Saved = new (Context) DFIDeducedMismatchArgs; |
| Saved->FirstArg = Info.FirstArg; |
| Saved->SecondArg = Info.SecondArg; |
| Saved->TemplateArgs = Info.take(); |
| Saved->CallArgIndex = Info.CallArgIndex; |
| Result.Data = Saved; |
| break; |
| } |
| |
| case Sema::TDK_NonDeducedMismatch: { |
| // FIXME: Should allocate from normal heap so that we can free this later. |
| DFIArguments *Saved = new (Context) DFIArguments; |
| Saved->FirstArg = Info.FirstArg; |
| Saved->SecondArg = Info.SecondArg; |
| Result.Data = Saved; |
| 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. |
| DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments; |
| Saved->Param = Info.Param; |
| Saved->FirstArg = Info.FirstArg; |
| Saved->SecondArg = Info.SecondArg; |
| Result.Data = Saved; |
| break; |
| } |
| |
| 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_ConstraintsNotSatisfied: { |
| CNSInfo *Saved = new (Context) CNSInfo; |
| Saved->TemplateArgs = Info.take(); |
| Saved->Satisfaction = Info.AssociatedConstraintsSatisfaction; |
| Result.Data = Saved; |
| break; |
| } |
| |
| case Sema::TDK_Success: |
| case Sema::TDK_NonDependentConversionFailure: |
| llvm_unreachable("not a deduction failure"); |
| } |
| |
| return Result; |
| } |
| |
| void DeductionFailureInfo::Destroy() { |
| switch (static_cast<Sema::TemplateDeductionResult>(Result)) { |
| case Sema::TDK_Success: |
| case Sema::TDK_Invalid: |
| case Sema::TDK_InstantiationDepth: |
| case Sema::TDK_Incomplete: |
| case Sema::TDK_TooManyArguments: |
| case Sema::TDK_TooFewArguments: |
| case Sema::TDK_InvalidExplicitArguments: |
| case Sema::TDK_CUDATargetMismatch: |
| case Sema::TDK_NonDependentConversionFailure: |
| break; |
| |
| case Sema::TDK_IncompletePack: |
| case Sema::TDK_Inconsistent: |
| case Sema::TDK_Underqualified: |
| case Sema::TDK_DeducedMismatch: |
| case Sema::TDK_DeducedMismatchNested: |
| case Sema::TDK_NonDeducedMismatch: |
| // FIXME: Destroy the data? |
| Data = nullptr; |
| break; |
| |
| case Sema::TDK_SubstitutionFailure: |
| // FIXME: Destroy the template argument list? |
| Data = nullptr; |
| if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) { |
| Diag->~PartialDiagnosticAt(); |
| HasDiagnostic = false; |
| } |
| break; |
| |
| case Sema::TDK_ConstraintsNotSatisfied: |
| // FIXME: Destroy the template argument list? |
| Data = nullptr; |
| if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) { |
| Diag->~PartialDiagnosticAt(); |
| HasDiagnostic = false; |
| } |
| break; |
| |
| // Unhandled |
| case Sema::TDK_MiscellaneousDeductionFailure: |
| break; |
| } |
| } |
| |
| PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() { |
| if (HasDiagnostic) |
| return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic)); |
| return nullptr; |
| } |
| |
| TemplateParameter DeductionFailureInfo::getTemplateParameter() { |
| switch (static_cast<Sema::TemplateDeductionResult>(Result)) { |
| case Sema::TDK_Success: |
| case Sema::TDK_Invalid: |
| case Sema::TDK_InstantiationDepth: |
| case Sema::TDK_TooManyArguments: |
| case Sema::TDK_TooFewArguments: |
| case Sema::TDK_SubstitutionFailure: |
| case Sema::TDK_DeducedMismatch: |
| case Sema::TDK_DeducedMismatchNested: |
| case Sema::TDK_NonDeducedMismatch: |
| case Sema::TDK_CUDATargetMismatch: |
| case Sema::TDK_NonDependentConversionFailure: |
| case Sema::TDK_ConstraintsNotSatisfied: |
| return TemplateParameter(); |
| |
| case Sema::TDK_Incomplete: |
| 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; |
| |
| // Unhandled |
| case Sema::TDK_MiscellaneousDeductionFailure: |
| break; |
| } |
| |
| return TemplateParameter(); |
| } |
| |
| TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { |
| switch (static_cast<Sema::TemplateDeductionResult>(Result)) { |
| case Sema::TDK_Success: |
| case Sema::TDK_Invalid: |
| case Sema::TDK_InstantiationDepth: |
| 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: |
| case Sema::TDK_NonDeducedMismatch: |
| case Sema::TDK_CUDATargetMismatch: |
| case Sema::TDK_NonDependentConversionFailure: |
| return nullptr; |
| |
| case Sema::TDK_DeducedMismatch: |
| case Sema::TDK_DeducedMismatchNested: |
| return static_cast<DFIDeducedMismatchArgs*>(Data)->TemplateArgs; |
| |
| case Sema::TDK_SubstitutionFailure: |
| return static_cast<TemplateArgumentList*>(Data); |
| |
| case Sema::TDK_ConstraintsNotSatisfied: |
| return static_cast<CNSInfo*>(Data)->TemplateArgs; |
| |
| // Unhandled |
| case Sema::TDK_MiscellaneousDeductionFailure: |
| break; |
| } |
| |
| return nullptr; |
| } |
| |
| const TemplateArgument *DeductionFailureInfo::getFirstArg() { |
| switch (static_cast<Sema::TemplateDeductionResult>(Result)) { |
| case Sema::TDK_Success: |
| case Sema::TDK_Invalid: |
| case Sema::TDK_InstantiationDepth: |
| case Sema::TDK_Incomplete: |
| case Sema::TDK_TooManyArguments: |
| case Sema::TDK_TooFewArguments: |
| case Sema::TDK_InvalidExplicitArguments: |
| case Sema::TDK_SubstitutionFailure: |
| case Sema::TDK_CUDATargetMismatch: |
| case Sema::TDK_NonDependentConversionFailure: |
| case Sema::TDK_ConstraintsNotSatisfied: |
| return nullptr; |
| |
| case Sema::TDK_IncompletePack: |
| case Sema::TDK_Inconsistent: |
| case Sema::TDK_Underqualified: |
| case Sema::TDK_DeducedMismatch: |
| case Sema::TDK_DeducedMismatchNested: |
| case Sema::TDK_NonDeducedMismatch: |
| return &static_cast<DFIArguments*>(Data)->FirstArg; |
| |
| // Unhandled |
| case Sema::TDK_MiscellaneousDeductionFailure: |
| break; |
| } |
| |
| return nullptr; |
| } |
| |
| const TemplateArgument *DeductionFailureInfo::getSecondArg() { |
| switch (static_cast<Sema::TemplateDeductionResult>(Result)) { |
| case Sema::TDK_Success: |
| 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: |
| case Sema::TDK_SubstitutionFailure: |
| case Sema::TDK_CUDATargetMismatch: |
| case Sema::TDK_NonDependentConversionFailure: |
| case Sema::TDK_ConstraintsNotSatisfied: |
| return nullptr; |
| |
| case Sema::TDK_Inconsistent: |
| case Sema::TDK_Underqualified: |
| case Sema::TDK_DeducedMismatch: |
| case Sema::TDK_DeducedMismatchNested: |
| case Sema::TDK_NonDeducedMismatch: |
| return &static_cast<DFIArguments*>(Data)->SecondArg; |
| |
| // Unhandled |
| case Sema::TDK_MiscellaneousDeductionFailure: |
| break; |
| } |
| |
| return nullptr; |
| } |
| |
| llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() { |
| switch (static_cast<Sema::TemplateDeductionResult>(Result)) { |
| case Sema::TDK_DeducedMismatch: |
| case Sema::TDK_DeducedMismatchNested: |
| return static_cast<DFIDeducedMismatchArgs*>(Data)->CallArgIndex; |
| |
| default: |
| return llvm::None; |
| } |
| } |
| |
| bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed( |
| OverloadedOperatorKind Op) { |
| if (!AllowRewrittenCandidates) |
| return false; |
| return Op == OO_EqualEqual || Op == OO_Spaceship; |
| } |
| |
| bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed( |
| ASTContext &Ctx, const FunctionDecl *FD) { |
| if (!shouldAddReversed(FD->getDeclName().getCXXOverloadedOperator())) |
| return false; |
| // Don't bother adding a reversed candidate that can never be a better |
| // match than the non-reversed version. |
| return FD->getNumParams() != 2 || |
| !Ctx.hasSameUnqualifiedType(FD->getParamDecl(0)->getType(), |
| FD->getParamDecl(1)->getType()) || |
| FD->hasAttr<EnableIfAttr>(); |
| } |
| |
| void OverloadCandidateSet::destroyCandidates() { |
| for (iterator i = begin(), e = end(); i != e; ++i) { |
| for (auto &C : i->Conversions) |
| C.~ImplicitConversionSequence(); |
| if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction) |
| i->DeductionFailure.Destroy(); |
| } |
| } |
| |
| void OverloadCandidateSet::clear(CandidateSetKind CSK) { |
| destroyCandidates(); |
| SlabAllocator.Reset(); |
| NumInlineBytesUsed = 0; |
| Candidates.clear(); |
| Functions.clear(); |
| Kind = CSK; |
| } |
| |
| namespace { |
| class UnbridgedCastsSet { |
| struct Entry { |
| Expr **Addr; |
| Expr *Saved; |
| }; |
| SmallVector<Entry, 2> Entries; |
| |
| public: |
| void save(Sema &S, Expr *&E) { |
| assert(E->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); |
| Entry entry = { &E, E }; |
| Entries.push_back(entry); |
| E = S.stripARCUnbridgedCast(E); |
| } |
| |
| void restore() { |
| for (SmallVectorImpl<Entry>::iterator |
| i = Entries.begin(), e = Entries.end(); i != e; ++i) |
| *i->Addr = i->Saved; |
| } |
| }; |
| } |
| |
| /// checkPlaceholderForOverload - Do any interesting placeholder-like |
| /// preprocessing on the given expression. |
| /// |
| /// \param unbridgedCasts a collection to which to add unbridged casts; |
| /// without this, they will be immediately diagnosed as errors |
| /// |
| /// Return true on unrecoverable error. |
| static bool |
| checkPlaceholderForOverload(Sema &S, Expr *&E, |
| UnbridgedCastsSet *unbridgedCasts = nullptr) { |
| if (const BuiltinType *placeholder = E->getType()->getAsPlaceholderType()) { |
| // We can't handle overloaded expressions here because overload |
| // resolution might reasonably tweak them. |
| if (placeholder->getKind() == BuiltinType::Overload) return false; |
| |
| // If the context potentially accepts unbridged ARC casts, strip |
| // the unbridged cast and add it to the collection for later restoration. |
| if (placeholder->getKind() == BuiltinType::ARCUnbridgedCast && |
| unbridgedCasts) { |
| unbridgedCasts->save(S, E); |
| return false; |
| } |
| |
| // Go ahead and check everything else. |
| ExprResult result = S.CheckPlaceholderExpr(E); |
| if (result.isInvalid()) |
| return true; |
| |
| E = result.get(); |
| return false; |
| } |
| |
| // Nothing to do. |
| return false; |
| } |
| |
| /// checkArgPlaceholdersForOverload - Check a set of call operands for |
| /// placeholders. |
| static bool checkArgPlaceholdersForOverload(Sema &S, |
| MultiExprArg Args, |
| UnbridgedCastsSet &unbridged) { |
| for (unsigned i = 0, e = Args.size(); i != e; ++i) |
| if (checkPlaceholderForOverload(S, Args[i], &unbridged)) |
| return true; |
| |
| return false; |
| } |
| |
| /// Determine whether the given New declaration is an overload of the |
| /// declarations in Old. This routine returns Ovl_Match or Ovl_NonFunction if |
| /// New and Old cannot be overloaded, e.g., if New has the same signature as |
| /// some function in Old (C++ 1.3.10) or if the Old declarations aren't |
| /// functions (or function templates) at all. When it does return Ovl_Match or |
| /// Ovl_NonFunction, MatchedDecl will point to the decl that New cannot be |
| /// overloaded with. This decl may be a UsingShadowDecl on top of the underlying |
| /// declaration. |
| /// |
| /// Example: Given the following input: |
| /// |
| /// void f(int, float); // #1 |
| /// void f(int, int); // #2 |
| /// int f(int, int); // #3 |
| /// |
| /// When we process #1, there is no previous declaration of "f", so IsOverload |
| /// will not be used. |
| /// |
| /// When we process #2, Old contains only the FunctionDecl for #1. By comparing |
| /// the parameter types, we see that #1 and #2 are overloaded (since they have |
| /// different signatures), so this routine returns Ovl_Overload; MatchedDecl is |
| /// unchanged. |
| /// |
| /// When we process #3, Old is an overload set containing #1 and #2. We compare |
| /// the signatures of #3 to #1 (they're overloaded, so we do nothing) and then |
| /// #3 to #2. Since the signatures of #3 and #2 are identical (return types of |
| /// functions are not part of the signature), IsOverload returns Ovl_Match and |
| /// MatchedDecl will be set to point to the FunctionDecl for #2. |
| /// |
| /// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced into a class |
| /// by a using declaration. The rules for whether to hide shadow declarations |
| /// ignore some properties which otherwise figure into a function template's |
| /// signature. |
| Sema::OverloadKind |
| Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, |
| NamedDecl *&Match, bool NewIsUsingDecl) { |
| for (LookupResult::iterator I = Old.begin(), E = Old.end(); |
| I != E; ++I) { |
| NamedDecl *OldD = *I; |
| |
| bool OldIsUsingDecl = false; |
| if (isa<UsingShadowDecl>(OldD)) { |
| OldIsUsingDecl = true; |
| |
| // We can always introduce two using declarations into the same |
| // context, even if they have identical signatures. |
| if (NewIsUsingDecl) continue; |
| |
| OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl(); |
| } |
| |
| // A using-declaration does not conflict with another declaration |
| // if one of them is hidden. |
| if ((OldIsUsingDecl || NewIsUsingDecl) && !isVisible(*I)) |
| continue; |
| |
| // If either declaration was introduced by a using declaration, |
| // we'll need to use slightly different rules for matching. |
| // Essentially, these rules are the normal rules, except that |
| // function templates hide function templates with different |
| // return types or template parameter lists. |
| bool UseMemberUsingDeclRules = |
| (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() && |
| !New->getFriendObjectKind(); |
| |
| if (FunctionDecl *OldF = OldD->getAsFunction()) { |
| if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) { |
| if (UseMemberUsingDeclRules && OldIsUsingDecl) { |
| HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I)); |
| continue; |
| } |
| |
| if (!isa<FunctionTemplateDecl>(OldD) && |
| !shouldLinkPossiblyHiddenDecl(*I, New)) |
| continue; |
| |
| 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. |
| assert(Old.getLookupKind() == LookupUsingDeclName); |
| } else if (isa<TagDecl>(OldD)) { |
| // We can always overload with tags by hiding them. |
| } else if (auto *UUD = dyn_cast<UnresolvedUsingValueDecl>(OldD)) { |
| // Optimistically assume that an unresolved using decl will |
| // overload; if it doesn't, we'll have to diagnose during |
| // template instantiation. |
| // |
| // Exception: if the scope is dependent and this is not a class |
| // member, the using declaration can only introduce an enumerator. |
| if (UUD->getQualifier()->isDependent() && !UUD->isCXXClassMember()) { |
| Match = *I; |
| return Ovl_NonFunction; |
| } |
| } else { |
| // (C++ 13p1): |
| // Only function declarations can be overloaded; object and type |
| // declarations cannot be overloaded. |
| Match = *I; |
| return Ovl_NonFunction; |
| } |
| } |
| |
| // C++ [temp.friend]p1: |
| // For a friend function declaration that is not a template declaration: |
| // -- if the name of the friend is a qualified or unqualified template-id, |
| // [...], otherwise |
| // -- if the name of the friend is a qualified-id and a matching |
| // non-template function is found in the specified class or namespace, |
| // the friend declaration refers to that function, otherwise, |
| // -- if the name of the friend is a qualified-id and a matching function |
| // template is found in the specified class or namespace, the friend |
| // declaration refers to the deduced specialization of that function |
| // template, otherwise |
| // -- the name shall be an unqualified-id [...] |
| // If we get here for a qualified friend declaration, we've just reached the |
| // third bullet. If the type of the friend is dependent, skip this lookup |
| // until instantiation. |
| if (New->getFriendObjectKind() && New->getQualifier() && |
| !New->getDescribedFunctionTemplate() && |
| !New->getDependentSpecializationInfo() && |
| !New->getType()->isDependentType()) { |
| LookupResult TemplateSpecResult(LookupResult::Temporary, Old); |
| TemplateSpecResult.addAllDecls(Old); |
| if (CheckFunctionTemplateSpecialization(New, nullptr, TemplateSpecResult, |
| /*QualifiedFriend*/true)) { |
| New->setInvalidDecl(); |
| return Ovl_Overload; |
| } |
| |
| Match = TemplateSpecResult.getAsSingle<FunctionDecl>(); |
| return Ovl_Match; |
| } |
| |
| return Ovl_Overload; |
| } |
| |
| bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, |
| bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs, |
| bool ConsiderRequiresClauses) { |
| // C++ [basic.start.main]p2: This function shall not be overloaded. |
| if (New->isMain()) |
| return false; |
| |
| // MSVCRT user defined entry points cannot be overloaded. |
| if (New->isMSVCRTEntryPoint()) |
| return false; |
| |
| FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); |
| FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); |
| |
| // C++ [temp.fct]p2: |
| // A function template can be overloaded with other function templates |
| // and with normal (non-template) functions. |
| if ((OldTemplate == nullptr) != (NewTemplate == nullptr)) |
| return true; |
| |
| // Is the function New an overload of the function Old? |
| QualType OldQType = Context.getCanonicalType(Old->getType()); |
| QualType NewQType = Context.getCanonicalType(New->getType()); |
| |
| // Compare the signatures (C++ 1.3.10) of the two functions to |
| // determine whether they are overloads. If we find any mismatch |
| // in the signature, they are overloads. |
| |
| // If either of these functions is a K&R-style function (no |
| // prototype), then we consider them to have matching signatures. |
| if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) || |
| isa<FunctionNoProtoType>(NewQType.getTypePtr())) |
| return false; |
| |
| const FunctionProtoType *OldType = cast<FunctionProtoType>(OldQType); |
| const FunctionProtoType *NewType = cast<FunctionProtoType>(NewQType); |
| |
| // The signature of a function includes the types of its |
| // parameters (C++ 1.3.10), which includes the presence or absence |
| // of the ellipsis; see C++ DR 357). |
| if (OldQType != NewQType && |
| (OldType->getNumParams() != NewType->getNumParams() || |
| OldType->isVariadic() != NewType->isVariadic() || |
| !FunctionParamTypesAreEqual(OldType, NewType))) |
| return true; |
| |
| // C++ [temp.over.link]p4: |
| // The signature of a function template consists of its function |
| // signature, its return type and its template parameter list. The names |
| // of the template parameters are significant only for establishing the |
| // relationship between the template parameters and the rest of the |
| // signature. |
| // |
| // We check the return type and template parameter lists for function |
| // templates first; the remaining checks follow. |
| // |
| // However, we don't consider either of these when deciding whether |
| // a member introduced by a shadow declaration is hidden. |
| if (!UseMemberUsingDeclRules && NewTemplate && |
| (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), |
| OldTemplate->getTemplateParameters(), |
| false, TPL_TemplateMatch) || |
| !Context.hasSameType(Old->getDeclaredReturnType(), |
| New->getDeclaredReturnType()))) |
| return true; |
| |
| // If the function is a class member, its signature includes the |
| // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself. |
| // |
| // As part of this, also check whether one of the member functions |
| // is static, in which case they are not overloads (C++ |
| // 13.1p2). While not part of the definition of the signature, |
| // this check is important to determine whether these functions |
| // can be overloaded. |
| CXXMethodDecl *OldMethod = dyn_cast<CXXMethodDecl>(Old); |
| CXXMethodDecl *NewMethod = dyn_cast<CXXMethodDecl>(New); |
| if (OldMethod && NewMethod && |
| !OldMethod->isStatic() && !NewMethod->isStatic()) { |
| if (OldMethod->getRefQualifier() != NewMethod->getRefQualifier()) { |
| if (!UseMemberUsingDeclRules && |
| (OldMethod->getRefQualifier() == RQ_None || |
| NewMethod->getRefQualifier() == RQ_None)) { |
| // C++0x [over.load]p2: |
| // - Member function declarations with the same name and the same |
| // parameter-type-list as well as member function template |
| // declarations with the same name, the same parameter-type-list, and |
| // the same template parameter lists cannot be overloaded if any of |
| // them, but not all, have a ref-qualifier (8.3.5). |
| Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) |
| << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); |
| Diag(OldMethod->getLocation(), diag::note_previous_declaration); |
| } |
| return true; |
| } |
| |
| // We may not have applied the implicit const for a constexpr member |
| // function yet (because we haven't yet resolved whether this is a static |
| // or non-static member function). Add it now, on the assumption that this |
| // is a redeclaration of OldMethod. |
| auto OldQuals = OldMethod->getMethodQualifiers(); |
| auto NewQuals = NewMethod->getMethodQualifiers(); |
| if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() && |
| !isa<CXXConstructorDecl>(NewMethod)) |
| NewQuals.addConst(); |
| // We do not allow overloading based off of '__restrict'. |
| OldQuals.removeRestrict(); |
| NewQuals.removeRestrict(); |
| if (OldQuals != NewQuals) |
| return true; |
| } |
| |
| // Though pass_object_size is placed on parameters and takes an argument, we |
| // consider it to be a function-level modifier for the sake of function |
| // identity. Either the function has one or more parameters with |
| // pass_object_size or it doesn't. |
| if (functionHasPassObjectSizeParams(New) != |
| functionHasPassObjectSizeParams(Old)) |
| return true; |
| |
| // enable_if attributes are an order-sensitive part of the signature. |
| for (specific_attr_iterator<EnableIfAttr> |
| NewI = New->specific_attr_begin<EnableIfAttr>(), |
| NewE = New->specific_attr_end<EnableIfAttr>(), |
| OldI = Old->specific_attr_begin<EnableIfAttr>(), |
| OldE = Old->specific_attr_end<EnableIfAttr>(); |
| NewI != NewE || OldI != OldE; ++NewI, ++OldI) { |
| if (NewI == NewE || OldI == OldE) |
| return true; |
| llvm::FoldingSetNodeID NewID, OldID; |
| NewI->getCond()->Profile(NewID, Context, true); |
| OldI->getCond()->Profile(OldID, Context, true); |
| if (NewID != OldID) |
| return true; |
| } |
| |
| if (getLangOpts().CUDA && ConsiderCudaAttrs) { |
| // Don't allow overloading of destructors. (In theory we could, but it |
| // would be a giant change to clang.) |
| if (!isa<CXXDestructorDecl>(New)) { |
| CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New), |
| OldTarget = IdentifyCUDATarget(Old); |
| if (NewTarget != CFT_InvalidTarget) { |
| assert((OldTarget != CFT_InvalidTarget) && |
| "Unexpected invalid target."); |
| |
| // Allow overloading of functions with same signature and different CUDA |
| // target attributes. |
| if (NewTarget != OldTarget) |
| return true; |
| } |
| } |
| } |
| |
| if (ConsiderRequiresClauses) { |
| Expr *NewRC = New->getTrailingRequiresClause(), |
| *OldRC = Old->getTrailingRequiresClause(); |
| if ((NewRC != nullptr) != (OldRC != nullptr)) |
| // RC are most certainly different - these are overloads. |
| return true; |
| |
| if (NewRC) { |
| llvm::FoldingSetNodeID NewID, OldID; |
| NewRC->Profile(NewID, Context, /*Canonical=*/true); |
| OldRC->Profile(OldID, Context, /*Canonical=*/true); |
| if (NewID != OldID) |
| // RCs are not equivalent - these are overloads. |
| return true; |
| } |
| } |
| |
| // The signatures match; this is not an overload. |
| return false; |
| } |
| |
| /// 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. |
| static ImplicitConversionSequence |
| TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, |
| bool SuppressUserConversions, |
| AllowedExplicit AllowExplicit, |
| bool InOverloadResolution, |
| bool CStyle, |
| bool AllowObjCWritebackConversion, |
| bool AllowObjCConversionOnExplicit) { |
| ImplicitConversionSequence ICS; |
| |
| if (SuppressUserConversions) { |
| // We're not in the case above, so there is no conversion that |
| // we can perform. |
| ICS.setBad(BadConversionSequence::no_conversion, From, ToType); |
| return ICS; |
| } |
| |
| // Attempt user-defined conversion. |
| OverloadCandidateSet Conversions(From->getExprLoc(), |
| OverloadCandidateSet::CSK_Normal); |
| switch (IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, |
| Conversions, AllowExplicit, |
| AllowObjCConversionOnExplicit)) { |
| case OR_Success: |
| case OR_Deleted: |
| ICS.setUserDefined(); |
| // C++ [over.ics.user]p4: |
| // A conversion of an expression of class type to the same class |
| // type is given Exact Match rank, and a conversion of an |
| // expression of class type to a base class of that type is |
| // given Conversion rank, in spite of the fact that a copy |
| // constructor (i.e., a user-defined conversion function) is |
| // called for those cases. |
| if (CXXConstructorDecl *Constructor |
| = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) { |
| QualType FromCanon |
| = S.Context.getCanonicalType(From->getType().getUnqualifiedType()); |
| QualType ToCanon |
| = S.Context.getCanonicalType(ToType).getUnqualifiedType(); |
| if (Constructor->isCopyConstructor() && |
| (FromCanon == ToCanon || |
| S.IsDerivedFrom(From->getBeginLoc(), FromCanon, ToCanon))) { |
| // Turn this into a "standard" conversion sequence, so that it |
| // gets ranked with standard conversion sequences. |
| DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction; |
| ICS.setStandard(); |
| ICS.Standard.setAsIdentityConversion(); |
| ICS.Standard.setFromType(From->getType()); |
| ICS.Standard.setAllToTypes(ToType); |
| ICS.Standard.CopyConstructor = Constructor; |
| ICS.Standard.FoundCopyConstructor = Found; |
| if (ToCanon != FromCanon) |
| ICS.Standard.Second = ICK_Derived_To_Base; |
| } |
| } |
| break; |
| |
| case OR_Ambiguous: |
| ICS.setAmbiguous(); |
| ICS.Ambiguous.setFromType(From->getType()); |
| ICS.Ambiguous.setToType(ToType); |
| for (OverloadCandidateSet::iterator Cand = Conversions.begin(); |
| Cand != Conversions.end(); ++Cand) |
| if (Cand->Best) |
| ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function); |
| break; |
| |
| // Fall through. |
| case OR_No_Viable_Function: |
| ICS.setBad(BadConversionSequence::no_conversion, From, ToType); |
| break; |
| } |
| |
| return ICS; |
| } |
| |
| /// TryImplicitConversion - Attempt to perform an implicit conversion |
| /// from the given expression (Expr) to the given type (ToType). This |
| /// function returns an implicit conversion sequence that can be used |
| /// to perform the initialization. Given |
| /// |
| /// void f(float f); |
| /// void g(int i) { f(i); } |
| /// |
| /// this routine would produce an implicit conversion sequence to |
| /// describe the initialization of f from i, which will be a standard |
| /// conversion sequence containing an lvalue-to-rvalue conversion (C++ |
| /// 4.1) followed by a floating-integral conversion (C++ 4.9). |
| // |
| /// Note that this routine only determines how the conversion can be |
| /// performed; it does not actually perform the conversion. As such, |
| /// it will not produce any diagnostics if no conversion is available, |
| /// but will instead return an implicit conversion sequence of kind |
| /// "BadConversion". |
| /// |
| /// If @p SuppressUserConversions, then user-defined conversions are |
| /// not permitted. |
| /// If @p AllowExplicit, then explicit user-defined conversions are |
| /// permitted. |
| /// |
| /// \param AllowObjCWritebackConversion Whether we allow the Objective-C |
| /// writeback conversion, which allows __autoreleasing id* parameters to |
| /// be initialized with __strong id* or __weak id* arguments. |
| static ImplicitConversionSequence |
| TryImplicitConversion(Sema &S, Expr *From, QualType ToType, |
| bool SuppressUserConversions, |
| AllowedExplicit AllowExplicit, |
| bool InOverloadResolution, |
| bool CStyle, |
| bool AllowObjCWritebackConversion, |
| bool AllowObjCConversionOnExplicit) { |
| ImplicitConversionSequence ICS; |
| if (IsStandardConversion(S, From, ToType, InOverloadResolution, |
| ICS.Standard, CStyle, AllowObjCWritebackConversion)){ |
| ICS.setStandard(); |
| return ICS; |
| } |
| |
| if (!S.getLangOpts().CPlusPlus) { |
| ICS.setBad(BadConversionSequence::no_conversion, From, ToType); |
| return ICS; |
| } |
| |
| // C++ [over.ics.user]p4: |
| // A conversion of an expression of class type to the same class |
| // type is given Exact Match rank, and a conversion of an |
| // expression of class type to a base class of that type is |
| // given Conversion rank, in spite of the fact that a copy/move |
| // constructor (i.e., a user-defined conversion function) is |
| // called for those cases. |
| QualType FromType = From->getType(); |
| if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() && |
| (S.Context.hasSameUnqualifiedType(FromType, ToType) || |
| S.IsDerivedFrom(From->getBeginLoc(), FromType, ToType))) { |
| ICS.setStandard(); |
| ICS.Standard.setAsIdentityConversion(); |
| ICS.Standard.setFromType(FromType); |
| ICS.Standard.setAllToTypes(ToType); |
| |
| // We don't actually check at this point whether there is a valid |
| // copy/move constructor, since overloading just assumes that it |
| // exists. When we actually perform initialization, we'll find the |
| // appropriate constructor to copy the returned object, if needed. |
| ICS.Standard.CopyConstructor = nullptr; |
| |
| // Determine whether this is considered a derived-to-base conversion. |
| if (!S.Context.hasSameUnqualifiedType(FromType, ToType)) |
| ICS.Standard.Second = ICK_Derived_To_Base; |
| |
| return ICS; |
| } |
| |
| return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions, |
| AllowExplicit, InOverloadResolution, CStyle, |
| AllowObjCWritebackConversion, |
| AllowObjCConversionOnExplicit); |
| } |
| |
| ImplicitConversionSequence |
| Sema::TryImplicitConversion(Expr *From, QualType ToType, |
| bool SuppressUserConversions, |
| AllowedExplicit AllowExplicit, |
| bool InOverloadResolution, |
| bool CStyle, |
| bool AllowObjCWritebackConversion) { |
| return ::TryImplicitConversion(*this, From, ToType, SuppressUserConversions, |
| AllowExplicit, InOverloadResolution, CStyle, |
| AllowObjCWritebackConversion, |
| /*AllowObjCConversionOnExplicit=*/false); |
| } |
| |
| /// PerformImplicitConversion - Perform an implicit conversion of the |
| /// expression From to the type ToType. Returns the |
| /// converted expression. Flavor is the kind of conversion we're |
| /// performing, used in the error message. If @p AllowExplicit, |
| /// explicit user-defined conversions are permitted. |
| ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, |
| AssignmentAction Action, |
| bool AllowExplicit) { |
| if (checkPlaceholderForOverload(*this, From)) |
| return ExprError(); |
| |
| // Objective-C ARC: Determine whether we will allow the writeback conversion. |
| bool AllowObjCWritebackConversion |
| = getLangOpts().ObjCAutoRefCount && |
| (Action == AA_Passing || Action == AA_Sending); |
| if (getLangOpts().ObjC) |
| CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType, |
| From->getType(), From); |
| ImplicitConversionSequence ICS = ::TryImplicitConversion( |
| *this, From, ToType, |
| /*SuppressUserConversions=*/false, |
| AllowExplicit ? AllowedExplicit::All : AllowedExplicit::None, |
| /*InOverloadResolution=*/false, |
| /*CStyle=*/false, AllowObjCWritebackConversion, |
| /*AllowObjCConversionOnExplicit=*/false); |
| return PerformImplicitConversion(From, ToType, ICS, Action); |
| } |
| |
| /// 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, |
| QualType &ResultTy) { |
| if (Context.hasSameUnqualifiedType(FromType, ToType)) |
| return false; |
| |
| // Permit the conversion F(t __attribute__((noreturn))) -> F(t) |
| // or F(t noexcept) -> F(t) |
| // where F adds one of the following at most once: |
| // - a pointer |
| // - a member pointer |
| // - a block pointer |
| // Changes here need matching changes in FindCompositePointerType. |
| CanQualType CanTo = Context.getCanonicalType(ToType); |
| CanQualType CanFrom = Context.getCanonicalType(FromType); |
| Type::TypeClass TyClass = CanTo->getTypeClass(); |
| if (TyClass != CanFrom->getTypeClass()) return false; |
| if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) { |
| if (TyClass == Type::Pointer) { |
| CanTo = CanTo.castAs<PointerType>()->getPointeeType(); |
| CanFrom = CanFrom.castAs<PointerType>()->getPointeeType(); |
| } else if (TyClass == Type::BlockPointer) { |
| CanTo = CanTo.castAs<BlockPointerType>()->getPointeeType(); |
| CanFrom = CanFrom.castAs<BlockPointerType>()->getPointeeType(); |
| } else if (TyClass == Type::MemberPointer) { |
| auto ToMPT = CanTo.castAs<MemberPointerType>(); |
| auto FromMPT = CanFrom.castAs<MemberPointerType>(); |
| // A function pointer conversion cannot change the class of the function. |
| if (ToMPT->getClass() != FromMPT->getClass()) |
| return false; |
| CanTo = ToMPT->getPointeeType(); |
| CanFrom = FromMPT->getPointeeType(); |
| } else { |
| return false; |
| } |
| |
| TyClass = CanTo->getTypeClass(); |
| if (TyClass != CanFrom->getTypeClass()) return false; |
| if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) |
| return false; |
| } |
| |
| const auto *FromFn = cast<FunctionType>(CanFrom); |
| FunctionType::ExtInfo FromEInfo = FromFn->getExtInfo(); |
| |
| const auto *ToFn = cast<FunctionType>(CanTo); |
| FunctionType::ExtInfo ToEInfo = ToFn->getExtInfo(); |
| |
| bool Changed = false; |
| |
| // Drop 'noreturn' if not present in target type. |
| if (FromEInfo.getNoReturn() && !ToEInfo.getNoReturn()) { |
| FromFn = Context.adjustFunctionType(FromFn, FromEInfo.withNoReturn(false)); |
| Changed = true; |
| } |
| |
| // 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() && !ToFPT->isNothrow()) { |
| FromFn = cast<FunctionType>( |
| Context.getFunctionTypeWithExceptionSpec(QualType(FromFPT, 0), |
| EST_None) |
| .getTypePtr()); |
| Changed = true; |
| } |
| |
| // Convert FromFPT's ExtParameterInfo if necessary. The conversion is valid |
| // only if the ExtParameterInfo lists of the two function prototypes can be |
| // merged and the merged list is identical to ToFPT's ExtParameterInfo list. |
| SmallVector<FunctionProtoType::ExtParameterInfo, 4> NewParamInfos; |
| bool CanUseToFPT, CanUseFromFPT; |
| if (Context.mergeExtParameterInfo(ToFPT, FromFPT, CanUseToFPT, |
| CanUseFromFPT, NewParamInfos) && |
| CanUseToFPT && !CanUseFromFPT) { |
| FunctionProtoType::ExtProtoInfo ExtInfo = FromFPT->getExtProtoInfo(); |
| ExtInfo.ExtParameterInfos = |
| NewParamInfos.empty() ? nullptr : NewParamInfos.data(); |
| QualType QT = Context.getFunctionType(FromFPT->getReturnType(), |
| FromFPT->getParamTypes(), ExtInfo); |
| FromFn = QT->getAs<FunctionType>(); |
| Changed = true; |
| } |
| } |
| |
| if (!Changed) |
| return false; |
| |
| assert(QualType(FromFn, 0).isCanonical()); |
| if (QualType(FromFn, 0) != CanTo) return false; |
| |
| ResultTy = ToType; |
| return true; |
| } |
| |
| /// 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 |
| /// conversion. |
| static bool IsVectorConversion(Sema &S, QualType FromType, |
| QualType ToType, ImplicitConversionKind &ICK) { |
| // We need at least one of these types to be a vector type to have a vector |
| // conversion. |
| if (!ToType->isVectorType() && !FromType->isVectorType()) |
| return false; |
| |
| // Identical types require no conversions. |
| if (S.Context.hasSameUnqualifiedType(FromType, ToType)) |
| return false; |
| |
| // There are no conversions between extended vector types, only identity. |
| if (ToType->isExtVectorType()) { |
| // There are no conversions between extended vector types other than the |
| // identity conversion. |
| if (FromType->isExtVectorType()) |
| return false; |
| |
| // Vector splat from any arithmetic type to a vector. |
| if (FromType->isArithmeticType()) { |
| ICK = ICK_Vector_Splat; |
| return true; |
| } |
| } |
| |
| if (ToType->isSizelessBuiltinType() || FromType->isSizelessBuiltinType()) |
| if (S.Context.areCompatibleSveTypes(FromType, ToType) || |
| S.Context.areLaxCompatibleSveTypes(FromType, ToType)) { |
| ICK = ICK_SVE_Vector_Conversion; |
| return true; |
| } |
| |
| // We can perform the conversion between vector types in the following cases: |
| // 1)vector types are equivalent AltiVec and GCC vector types |
| // 2)lax vector conversions are permitted and the vector types are of the |
| // same size |
| // 3)the destination type does not have the ARM MVE strict-polymorphism |
| // attribute, which inhibits lax vector conversion for overload resolution |
| // only |
| if (ToType->isVectorType() && FromType->isVectorType()) { |
| if (S.Context.areCompatibleVectorTypes(FromType, ToType) || |
| (S.isLaxVectorConversion(FromType, ToType) && |
| !ToType->hasAttr(attr::ArmMveStrictPolymorphism))) { |
| ICK = ICK_Vector_Conversion; |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType, |
| bool InOverloadResolution, |
| StandardConversionSequence &SCS, |
| bool CStyle); |
| |
| /// IsStandardConversion - Determines whether there is a standard |
| /// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the |
| /// expression From to the type ToType. Standard conversion sequences |
| /// only consider non-class types; for conversions that involve class |
| /// types, use TryImplicitConversion. If a conversion exists, SCS will |
| /// contain the standard conversion sequence required to perform this |
| /// conversion and this routine will return true. Otherwise, this |
| /// routine will return false and the value of SCS is unspecified. |
| static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, |
| bool InOverloadResolution, |
| StandardConversionSequence &SCS, |
| bool CStyle, |
| bool AllowObjCWritebackConversion) { |
| QualType FromType = From->getType(); |
| |
| // Standard conversions (C++ [conv]) |
| SCS.setAsIdentityConversion(); |
| SCS.IncompatibleObjC = false; |
| SCS.setFromType(FromType); |
| SCS.CopyConstructor = nullptr; |
| |
| // There are no standard conversions for class types in C++, so |
| // abort early. When overloading in C, however, we do permit them. |
| if (S.getLangOpts().CPlusPlus && |
| (FromType->isRecordType() || ToType->isRecordType())) |
| return false; |
| |
| // The first conversion can be an lvalue-to-rvalue conversion, |
| // array-to-pointer conversion, or function-to-pointer conversion |
| // (C++ 4p1). |
| |
| if (FromType == S.Context.OverloadTy) { |
| DeclAccessPair AccessPair; |
| if (FunctionDecl *Fn |
| = S.ResolveAddressOfOverloadedFunction(From, ToType, false, |
| AccessPair)) { |
| // We were able to resolve the address of the overloaded function, |
| // so we can convert to the type of that function. |
| FromType = Fn->getType(); |
| SCS.setFromType(FromType); |
| |
| // we can sometimes resolve &foo<int> regardless of ToType, so check |
| // if the type matches (identity) or we are converting to bool |
| if (!S.Context.hasSameUnqualifiedType( |
| S.ExtractUnqualifiedFunctionType(ToType), FromType)) { |
| QualType resultTy; |
| // if the function type matches except for [[noreturn]], it's ok |
| if (!S.IsFunctionConversion(FromType, |
| S.ExtractUnqualifiedFunctionType(ToType), resultTy)) |
| // otherwise, only a boolean conversion is standard |
| if (!ToType->isBooleanType()) |
| return false; |
| } |
| |
| // Check if the "from" expression is taking the address of an overloaded |
| // function and recompute the FromType accordingly. Take advantage of the |
| // fact that non-static member functions *must* have such an address-of |
| // expression. |
| CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn); |
| if (Method && !Method->isStatic()) { |
| assert(isa<UnaryOperator>(From->IgnoreParens()) && |
| "Non-unary operator on non-static member address"); |
| assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() |
| == UO_AddrOf && |
| "Non-address-of operator on non-static member address"); |
| const Type *ClassType |
| = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); |
| FromType = S.Context.getMemberPointerType(FromType, ClassType); |
| } else if (isa<UnaryOperator>(From->IgnoreParens())) { |
| assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() == |
| UO_AddrOf && |
| "Non-address-of operator for overloaded function expression"); |
| FromType = S.Context.getPointerType(FromType); |
| } |
| |
| // Check that we've computed the proper type after overload resolution. |
| // FIXME: FixOverloadedFunctionReference has side-effects; we shouldn't |
| // be calling it from within an NDEBUG block. |
| assert(S.Context.hasSameType( |
| FromType, |
| S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); |
| } else { |
| return false; |
| } |
| } |
| // Lvalue-to-rvalue conversion (C++11 4.1): |
| // A glvalue (3.10) of a non-function, non-array type T can |
| // be converted to a prvalue. |
| bool argIsLValue = From->isGLValue(); |
| if (argIsLValue && |
| !FromType->isFunctionType() && !FromType->isArrayType() && |
| S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { |
| SCS.First = ICK_Lvalue_To_Rvalue; |
| |
| // C11 6.3.2.1p2: |
| // ... if the lvalue has atomic type, the value has the non-atomic version |
| // of the type of the lvalue ... |
| if (const AtomicType *Atomic = FromType->getAs<AtomicType>()) |
| FromType = Atomic->getValueType(); |
| |
| // If T is a non-class type, the type of the rvalue is the |
| // cv-unqualified version of T. Otherwise, the type of the rvalue |
| // is T (C++ 4.1p1). C++ can't get here with class types; in C, we |
| // just strip the qualifiers because they don't matter. |
| FromType = FromType.getUnqualifiedType(); |
| } else if (FromType->isArrayType()) { |
| // Array-to-pointer conversion (C++ 4.2) |
| SCS.First = ICK_Array_To_Pointer; |
| |
| // An lvalue or rvalue of type "array of N T" or "array of unknown |
| // bound of T" can be converted to an rvalue of type "pointer to |
| // T" (C++ 4.2p1). |
| FromType = S.Context.getArrayDecayedType(FromType); |
| |
| if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) { |
| // This conversion is deprecated in C++03 (D.4) |
| SCS.DeprecatedStringLiteralToCharPtr = true; |
| |
| // For the purpose of ranking in overload resolution |
| // (13.3.3.1.1), this conversion is considered an |
| // array-to-pointer conversion followed by a qualification |
| // conversion (4.4). (C++ 4.2p2) |
| SCS.Second = ICK_Identity; |
| SCS.Third = ICK_Qualification; |
| SCS.QualificationIncludesObjCLifetime = false; |
| SCS.setAllToTypes(FromType); |
| return true; |
| } |
| } else if (FromType->isFunctionType() && argIsLValue) { |
| // Function-to-pointer conversion (C++ 4.3). |
| SCS.First = ICK_Function_To_Pointer; |
| |
| if (auto *DRE = dyn_cast<DeclRefExpr>(From->IgnoreParenCasts())) |
| if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) |
| if (!S.checkAddressOfFunctionIsAvailable(FD)) |
| return false; |
| |
| // An lvalue of function type T can be converted to an rvalue of |
| // type "pointer to T." The result is a pointer to the |
| // function. (C++ 4.3p1). |
| FromType = S.Context.getPointerType(FromType); |
| } else { |
| // We don't require any conversions for the first step. |
| SCS.First = ICK_Identity; |
| } |
| SCS.setToType(0, FromType); |
| |
| // The second conversion can be an integral promotion, floating |
| // point promotion, integral conversion, floating point conversion, |
| // floating-integral conversion, pointer conversion, |
| // pointer-to-member conversion, or boolean conversion (C++ 4p1). |
| // For overloading in C, this can also be a "compatible-type" |
| // conversion. |
| bool IncompatibleObjC = false; |
| ImplicitConversionKind SecondICK = ICK_Identity; |
| if (S.Context.hasSameUnqualifiedType(FromType, ToType)) { |
| // The unqualified versions of the types are the same: there's no |
| // conversion to do. |
| SCS.Second = ICK_Identity; |
| } else if (S.IsIntegralPromotion(From, FromType, ToType)) { |
| // Integral promotion (C++ 4.5). |
| SCS.Second = ICK_Integral_Promotion; |
| FromType = ToType.getUnqualifiedType(); |
| } else if (S.IsFloatingPointPromotion(FromType, ToType)) { |
| // Floating point promotion (C++ 4.6). |
| SCS.Second = ICK_Floating_Promotion; |
| FromType = ToType.getUnqualifiedType(); |
| } else if (S.IsComplexPromotion(FromType, ToType)) { |
| // Complex promotion (Clang extension) |
| SCS.Second = ICK_Complex_Promotion; |
| FromType = ToType.getUnqualifiedType(); |
| } else if (ToType->isBooleanType() && |
| (FromType->isArithmeticType() || |
| FromType->isAnyPointerType() || |
| FromType->isBlockPointerType() || |
| FromType->isMemberPointerType())) { |
| // Boolean conversions (C++ 4.12). |
| SCS.Second = ICK_Boolean_Conversion; |
| FromType = S.Context.BoolTy; |
| } else if (FromType->isIntegralOrUnscopedEnumerationType() && |
| ToType->isIntegralType(S.Context)) { |
| // Integral conversions (C++ 4.7). |
| SCS.Second = ICK_Integral_Conversion; |
| FromType = ToType.getUnqualifiedType(); |
| } else if (FromType->isAnyComplexType() && ToType->isAnyComplexType()) { |
| // Complex conversions (C99 6.3.1.6) |
| SCS.Second = ICK_Complex_Conversion; |
| FromType = ToType.getUnqualifiedType(); |
| } else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) || |
| (ToType->isAnyComplexType() && FromType->isArithmeticType())) { |
| // Complex-real conversions (C99 6.3.1.7) |
| SCS.Second = ICK_Complex_Real; |
| FromType = ToType.getUnqualifiedType(); |
| } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) { |
| // FIXME: disable conversions between long double, __ibm128 and __float128 |
| // if their representation is different until there is back end support |
| // We of course allow this conversion if long double is really double. |
| |
| // Conversions between bfloat and other floats are not permitted. |
| if (FromType == S.Context.BFloat16Ty || ToType == S.Context.BFloat16Ty) |
| return false; |
| |
| // Conversions between IEEE-quad and IBM-extended semantics are not |
| // permitted. |
| const llvm::fltSemantics &FromSem = |
| S.Context.getFloatTypeSemantics(FromType); |
| const llvm::fltSemantics &ToSem = S.Context.getFloatTypeSemantics(ToType); |
| if ((&FromSem == &llvm::APFloat::PPCDoubleDouble() && |
| &ToSem == &llvm::APFloat::IEEEquad()) || |
| (&FromSem == &llvm::APFloat::IEEEquad() && |
| &ToSem == &llvm::APFloat::PPCDoubleDouble())) |
| return false; |
| |
| // Floating point conversions (C++ 4.8). |
| SCS.Second = ICK_Floating_Conversion; |
| FromType = ToType.getUnqualifiedType(); |
| } else if ((FromType->isRealFloatingType() && |
| ToType->isIntegralType(S.Context)) || |
| (FromType->isIntegralOrUnscopedEnumerationType() && |
| ToType->isRealFloatingType())) { |
| // Conversions between bfloat and int are not permitted. |
| if (FromType->isBFloat16Type() || ToType->isBFloat16Type()) |
| return false; |
| |
| // Floating-integral conversions (C++ 4.9). |
| SCS.Second = ICK_Floating_Integral; |
| FromType = ToType.getUnqualifiedType(); |
| } else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) { |
| SCS.Second = ICK_Block_Pointer_Conversion; |
| } else if (AllowObjCWritebackConversion && |
| S.isObjCWritebackConversion(FromType, ToType, FromType)) { |
| SCS.Second = ICK_Writeback_Conversion; |
| } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution, |
| FromType, IncompatibleObjC)) { |
| // Pointer conversions (C++ 4.10). |
| SCS.Second = ICK_Pointer_Conversion; |
| SCS.IncompatibleObjC = IncompatibleObjC; |
| FromType = FromType.getUnqualifiedType(); |
| } else if (S.IsMemberPointerConversion(From, FromType, ToType, |
| InOverloadResolution, FromType)) { |
| // Pointer to member conversions (4.11). |
| SCS.Second = ICK_Pointer_Member; |
| } else if (IsVectorConversion(S, FromType, ToType, SecondICK)) { |
| SCS.Second = SecondICK; |
| FromType = ToType.getUnqualifiedType(); |
| } else if (!S.getLangOpts().CPlusPlus && |
| S.Context.typesAreCompatible(ToType, FromType)) { |
| // Compatible conversions (Clang extension for C function overloading) |
| SCS.Second = ICK_Compatible_Conversion; |
| FromType = ToType.getUnqualifiedType(); |
| } else if (IsTransparentUnionStandardConversion(S, From, ToType, |
| InOverloadResolution, |
| SCS, CStyle)) { |
| SCS.Second = ICK_TransparentUnionConversion; |
| FromType = ToType; |
| } else if (tryAtomicConversion(S, From, ToType, InOverloadResolution, SCS, |
| CStyle)) { |
| // tryAtomicConversion has updated the standard conversion sequence |
| // appropriately. |
| return true; |
| } else if (ToType->isEventT() && |
| From->isIntegerConstantExpr(S.getASTContext()) && |
| From->EvaluateKnownConstInt(S.getASTContext()) == 0) { |
| SCS.Second = ICK_Zero_Event_Conversion; |
| FromType = ToType; |
| } else if (ToType->isQueueT() && |
| From->isIntegerConstantExpr(S.getASTContext()) && |
| (From->EvaluateKnownConstInt(S.getASTContext()) == 0)) { |
| SCS.Second = ICK_Zero_Queue_Conversion; |
| FromType = ToType; |
| } else if (ToType->isSamplerT() && |
| From->isIntegerConstantExpr(S.getASTContext())) { |
| SCS.Second = ICK_Compatible_Conversion; |
| FromType = ToType; |
| } else { |
| // No second conversion required. |
| SCS.Second = ICK_Identity; |
| } |
| SCS.setToType(1, FromType); |
| |
| // The third conversion can be a function pointer conversion or a |
| // qualification conversion (C++ [conv.fctptr], [conv.qual]). |
| bool ObjCLifetimeConversion; |
| if (S.IsFunctionConversion(FromType, ToType, FromType)) { |
| // Function pointer conversions (removing 'noexcept') including removal of |
| // 'noreturn' (Clang extension). |
| SCS.Third = ICK_Function_Conversion; |
| } else if (S.IsQualificationConversion(FromType, ToType, CStyle, |
| ObjCLifetimeConversion)) { |
| SCS.Third = ICK_Qualification; |
| SCS.QualificationIncludesObjCLifetime = ObjCLifetimeConversion; |
| FromType = ToType; |
| } else { |
| // No conversion required |
| SCS.Third = ICK_Identity; |
| } |
| |
| // C++ [over.best.ics]p6: |
| // [...] Any difference in top-level cv-qualification is |
| // subsumed by the initialization itself and does not constitute |
| // a conversion. [...] |
| QualType CanonFrom = S.Context.getCanonicalType(FromType); |
| QualType CanonTo = S.Context.getCanonicalType(ToType); |
| if (CanonFrom.getLocalUnqualifiedType() |
| == CanonTo.getLocalUnqualifiedType() && |
| CanonFrom.getLocalQualifiers() != CanonTo.getLocalQualifiers()) { |
| FromType = ToType; |
| CanonFrom = CanonTo; |
| } |
| |
| SCS.setToType(2, FromType); |
| |
| if (CanonFrom == CanonTo) |
| return true; |
| |
| // If we have not converted the argument type to the parameter type, |
| // this is a bad conversion sequence, unless we're resolving an overload in C. |
| if (S.getLangOpts().CPlusPlus || !InOverloadResolution) |
| return false; |
| |
| ExprResult ER = ExprResult{From}; |
| Sema::AssignConvertType Conv = |
| S.CheckSingleAssignmentConstraints(ToType, ER, |
| /*Diagnose=*/false, |
| /*DiagnoseCFAudited=*/false, |
| /*ConvertRHS=*/false); |
| ImplicitConversionKind SecondConv; |
| switch (Conv) { |
| case Sema::Compatible: |
| SecondConv = ICK_C_Only_Conversion; |
| break; |
| // For our purposes, discarding qualifiers is just as bad as using an |
| // incompatible pointer. Note that an IncompatiblePointer conversion can drop |
| // qualifiers, as well. |
| case Sema::CompatiblePointerDiscardsQualifiers: |
| case Sema::IncompatiblePointer: |
| case Sema::IncompatiblePointerSign: |
| SecondConv = ICK_Incompatible_Pointer_Conversion; |
| break; |
| default: |
| return false; |
| } |
| |
| // First can only be an lvalue conversion, so we pretend that this was the |
| // second conversion. First should already be valid from earlier in the |
| // function. |
| SCS.Second = SecondConv; |
| SCS.setToType(1, ToType); |
| |
| // Third is Identity, because Second should rank us worse than any other |
| // conversion. This could also be ICK_Qualification, but it's simpler to just |
| // lump everything in with the second conversion, and we don't gain anything |
| // from making this ICK_Qualification. |
| SCS.Third = ICK_Identity; |
| SCS.setToType(2, ToType); |
| return true; |
| } |
| |
| static bool |
| IsTransparentUnionStandardConversion(Sema &S, Expr* From, |
| QualType &ToType, |
| bool InOverloadResolution, |
| StandardConversionSequence &SCS, |
| bool CStyle) { |
| |
| const RecordType *UT = ToType->getAsUnionType(); |
| if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) |
| return false; |
| // The field to initialize within the transparent union. |
| RecordDecl *UD = UT->getDecl(); |
| // It's compatible if the expression matches any of the fields. |
| for (const auto *it : UD->fields()) { |
| if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS, |
| CStyle, /*AllowObjCWritebackConversion=*/false)) { |
| ToType = it->getType(); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /// IsIntegralPromotion - Determines whether the conversion from the |
| /// expression From (whose potentially-adjusted type is FromType) to |
| /// ToType is an integral promotion (C++ 4.5). If so, returns true and |
| /// sets PromotedType to the promoted type. |
| bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { |
| const BuiltinType *To = ToType->getAs<BuiltinType>(); |
| // All integers are built-in. |
| if (!To) { |
| return false; |
| } |
| |
| // An rvalue of type char, signed char, unsigned char, short int, or |
| // unsigned short int can be converted to an rvalue of type int if |
| // int can represent all the values of the source type; otherwise, |
| // the source rvalue can be converted to an rvalue of type unsigned |
| // int (C++ 4.5p1). |
| if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() && |
| !FromType->isEnumeralType()) { |
| if (// We can promote any signed, promotable integer type to an int |
| (FromType->isSignedIntegerType() || |
| // We can promote any unsigned integer type whose size is |
| // less than int to an int. |
| Context.getTypeSize(FromType) < Context.getTypeSize(ToType))) { |
| return To->getKind() == BuiltinType::Int; |
| } |
| |
| return To->getKind() == BuiltinType::UInt; |
| } |
| |
| // C++11 [conv.prom]p3: |
| // A prvalue of an unscoped enumeration type whose underlying type is not |
| // fixed (7.2) can be converted to an rvalue a prvalue of the first of the |
| // following types that can represent all the values of the enumeration |
| // (i.e., the values in the range bmin to bmax as described in 7.2): int, |
| // unsigned int, long int, unsigned long int, long long int, or unsigned |
| // long long int. If none of the types in that list can represent all the |
| // values of the enumeration, an rvalue a prvalue of an unscoped enumeration |
| // type can be converted to an rvalue a prvalue of the extended integer type |
| // with lowest integer conversion rank (4.13) greater than the rank of long |
| // long in which all the values of the enumeration can be represented. If |
| // there are two such extended types, the signed one is chosen. |
| // C++11 [conv.prom]p4: |
| // A prvalue of an unscoped enumeration type whose underlying type is fixed |
| // can be converted to a prvalue of its underlying type. Moreover, if |
| // integral promotion can be applied to its underlying type, a prvalue of an |
| // unscoped enumeration type whose underlying type is fixed can also be |
| // converted to a prvalue of the promoted underlying type. |
| if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) { |
| // C++0x 7.2p9: Note that this implicit enum to int conversion is not |
| // provided for a scoped enumeration. |
| if (FromEnumType->getDecl()->isScoped()) |
| return false; |
| |
| // We can perform an integral promotion to the underlying type of the enum, |
| // even if that's not the promoted type. Note that the check for promoting |
| // the underlying type is based on the type alone, and does not consider |
| // the bitfield-ness of the actual source expression. |
| if (FromEnumType->getDecl()->isFixed()) { |
| QualType Underlying = FromEnumType->getDecl()->getIntegerType(); |
| return Context.hasSameUnqualifiedType(Underlying, ToType) || |
| IsIntegralPromotion(nullptr, Underlying, ToType); |
| } |
| |
| // We have already pre-calculated the promotion type, so this is trivial. |
| if (ToType->isIntegerType() && |
| isCompleteType(From->getBeginLoc(), 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: |
| // A prvalue of type char16_t, char32_t, or wchar_t (3.9.1) can be converted |
| // to an rvalue a prvalue of the first of the following types that can |
| // represent all the values of its underlying type: int, unsigned int, |
| // long int, unsigned long int, long long int, or unsigned long long int. |
| // If none of the types in that list can represent all the values of its |
| // underlying type, an rvalue a prvalue of type char16_t, char32_t, |
| // or wchar_t can be converted to an rvalue a prvalue of its underlying |
| // type. |
| if (FromType->isAnyCharacterType() && !FromType->isCharType() && |
| ToType->isIntegerType()) { |
| // Determine whether the type we're converting from is signed or |
| // unsigned. |
| bool FromIsSigned = FromType->isSignedIntegerType(); |
| uint64_t FromSize = Context.getTypeSize(FromType); |
| |
| // The types we'll try to promote to, in the appropriate |
| // order. Try each of these types. |
| QualType PromoteTypes[6] = { |
| Context.IntTy, Context.UnsignedIntTy, |
| Context.LongTy, Context.UnsignedLongTy , |
| Context.LongLongTy, Context.UnsignedLongLongTy |
| }; |
| for (int Idx = 0; Idx < 6; ++Idx) { |
| uint64_t ToSize = Context.getTypeSize(PromoteTypes[Idx]); |
| if (FromSize < ToSize || |
| (FromSize == ToSize && |
| FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType())) { |
| // We found the type that we can promote to. If this is the |
| // type we wanted, we have a promotion. Otherwise, no |
| // promotion. |
| return Context.hasSameUnqualifiedType(ToType, PromoteTypes[Idx]); |
| } |
| } |
| } |
| |
| // An rvalue for an integral bit-field (9.6) can be converted to an |
| // rvalue of type int if int can represent all the values of the |
| // bit-field; otherwise, it can be converted to unsigned int if |
| // unsigned int can represent all the values of the bit-field. If |
| // the bit-field is larger yet, no integral promotion applies to |
| // it. If the bit-field has an enumerated type, it is treated as any |
| // 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()) { |
| Optional<llvm::APSInt> BitWidth; |
| if (FromType->isIntegralType(Context) && |
| (BitWidth = |
| MemberDecl->getBitWidth()->getIntegerConstantExpr(Context))) { |
| llvm::APSInt ToSize(BitWidth->getBitWidth(), BitWidth->isUnsigned()); |
| ToSize = Context.getTypeSize(ToType); |
| |
| // Are we promoting to an int from a bitfield that fits in an int? |
| if (*BitWidth < ToSize || |
| (FromType->isSignedIntegerType() && *BitWidth <= ToSize)) { |
| return To->getKind() == BuiltinType::Int; |
| } |
| |
| // Are we promoting to an unsigned int from an unsigned bitfield |
| // that fits into an unsigned int? |
| if (FromType->isUnsignedIntegerType() && *BitWidth <= ToSize) { |
| return To->getKind() == BuiltinType::UInt; |
| } |
| |
| return false; |
| } |
| } |
| } |
| |
| // An rvalue of type bool can be converted to an rvalue of type int, |
| // with false becoming zero and true becoming one (C++ 4.5p4). |
| if (FromType->isBooleanType() && To->getKind() == BuiltinType::Int) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// IsFloatingPointPromotion - Determines whether the conversion from |
| /// FromType to ToType is a floating point promotion (C++ 4.6). If so, |
| /// returns true and sets PromotedType to the promoted type. |
| bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { |
| if (const BuiltinType *FromBuiltin = FromType->getAs<BuiltinType>()) |
| if (const BuiltinType *ToBuiltin = ToType->getAs<BuiltinType>()) { |
| /// An rvalue of type float can be converted to an rvalue of type |
| /// double. (C++ 4.6p1). |
| if (FromBuiltin->getKind() == BuiltinType::Float && |
| ToBuiltin->getKind() == BuiltinType::Double) |
| return true; |
| |
| // C99 6.3.1.5p1: |
| // When a float is promoted to double or long double, or a |
| // double is promoted to long double [...]. |
| if (!getLangOpts().CPlusPlus && |
| (FromBuiltin->getKind() == BuiltinType::Float || |
| FromBuiltin->getKind() == BuiltinType::Double) && |
| (ToBuiltin->getKind() == BuiltinType::LongDouble || |
| ToBuiltin->getKind() == BuiltinType::Float128 || |
| ToBuiltin->getKind() == BuiltinType::Ibm128)) |
| return true; |
| |
| // Half can be promoted to float. |
| if (!getLangOpts().NativeHalfType && |
| FromBuiltin->getKind() == BuiltinType::Half && |
| ToBuiltin->getKind() == BuiltinType::Float) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// 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 |
| /// floating-point or integral promotion. |
| bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) { |
| const ComplexType *FromComplex = FromType->getAs<ComplexType>(); |
| if (!FromComplex) |
| return false; |
| |
| const ComplexType *ToComplex = ToType->getAs<ComplexType>(); |
| if (!ToComplex) |
| return false; |
| |
| return IsFloatingPointPromotion(FromComplex->getElementType(), |
| ToComplex->getElementType()) || |
| IsIntegralPromotion(nullptr, FromComplex->getElementType(), |
| ToComplex->getElementType()); |
| } |
| |
| /// BuildSimilarlyQualifiedPointerType - In a pointer conversion from |
| /// the pointer type FromPtr to a pointer to type ToPointee, with the |
| /// same type qualifiers as FromPtr has on its pointee type. ToType, |
| /// if non-empty, will be a pointer to ToType that may or may not have |
| /// the right set of qualifiers on its pointee. |
| /// |
| static QualType |
| BuildSimilarlyQualifiedPointerType(const Type *FromPtr, |
| QualType ToPointee, QualType ToType, |
| ASTContext &Context, |
| bool StripObjCLifetime = false) { |
| assert((FromPtr->getTypeClass() == Type::Pointer || |
| FromPtr->getTypeClass() == Type::ObjCObjectPointer) && |
| "Invalid similarly-qualified pointer type"); |
| |
| /// Conversions to 'id' subsume cv-qualifier conversions. |
| if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType()) |
| return ToType.getUnqualifiedType(); |
| |
| QualType CanonFromPointee |
| = Context.getCanonicalType(FromPtr->getPointeeType()); |
| QualType CanonToPointee = Context.getCanonicalType(ToPointee); |
| Qualifiers Quals = CanonFromPointee.getQualifiers(); |
| |
| if (StripObjCLifetime) |
| Quals.removeObjCLifetime(); |
| |
| // Exact qualifier match -> return the pointer type we're converting to. |
| if (CanonToPointee.getLocalQualifiers() == Quals) { |
| // ToType is exactly what we need. Return it. |
| if (!ToType.isNull()) |
| return ToType.getUnqualifiedType(); |
| |
| // Build a pointer to ToPointee. It has the right qualifiers |
| // already. |
| if (isa<ObjCObjectPointerType>(ToType)) |
| return Context.getObjCObjectPointerType(ToPointee); |
| return Context.getPointerType(ToPointee); |
| } |
| |
| // Just build a canonical type that has the right qualifiers. |
| QualType QualifiedCanonToPointee |
| = Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), Quals); |
| |
| if (isa<ObjCObjectPointerType>(ToType)) |
| return Context.getObjCObjectPointerType(QualifiedCanonToPointee); |
| return Context.getPointerType(QualifiedCanonToPointee); |
| } |
| |
| static bool isNullPointerConstantForConversion(Expr *Expr, |
| bool InOverloadResolution, |
| ASTContext &Context) { |
| // Handle value-dependent integral null pointer constants correctly. |
| // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903 |
| if (Expr->isValueDependent() && !Expr->isTypeDependent() && |
| Expr->getType()->isIntegerType() && !Expr->getType()->isEnumeralType()) |
| return !InOverloadResolution; |
| |
| return Expr->isNullPointerConstant(Context, |
| InOverloadResolution? Expr::NPC_ValueDependentIsNotNull |
| : Expr::NPC_ValueDependentIsNull); |
| } |
| |
| /// IsPointerConversion - Determines whether the conversion of the |
| /// expression From, which has the (possibly adjusted) type FromType, |
| /// can be converted to the type ToType via a pointer conversion (C++ |
| /// 4.10). If so, returns true and places the converted type (that |
| /// might differ from ToType in its cv-qualifiers at some level) into |
| /// ConvertedType. |
| /// |
| /// This routine also supports conversions to and from block pointers |
| /// and conversions with Objective-C's 'id', 'id<protocols...>', and |
| /// pointers to interfaces. FIXME: Once we've determined the |
| /// appropriate overloading rules for Objective-C, we may want to |
| /// split the Objective-C checks into a different routine; however, |
| /// GCC seems to consider all of these conversions to be pointer |
| /// conversions, so for now they live here. IncompatibleObjC will be |
| /// set if the conversion is an allowed Objective-C conversion that |
| /// should result in a warning. |
| bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, |
| bool InOverloadResolution, |
| QualType& ConvertedType, |
| bool &IncompatibleObjC) { |
| IncompatibleObjC = false; |
| if (isObjCPointerConversion(FromType, ToType, ConvertedType, |
| IncompatibleObjC)) |
| return true; |
| |
| // Conversion from a null pointer constant to any Objective-C pointer type. |
| if (ToType->isObjCObjectPointerType() && |
| isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { |
| ConvertedType = ToType; |
| return true; |
| } |
| |
| // Blocks: Block pointers can be converted to void*. |
| if (FromType->isBlockPointerType() && ToType->isPointerType() && |
| ToType->castAs<PointerType>()->getPointeeType()->isVoidType()) { |
| ConvertedType = ToType; |
| return true; |
| } |
| // Blocks: A null pointer constant can be converted to a block |
| // pointer type. |
| if (ToType->isBlockPointerType() && |
| isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { |
| ConvertedType = ToType; |
| return true; |
| } |
| |
| // If the left-hand-side is nullptr_t, the right side can be a null |
| // pointer constant. |
| if (ToType->isNullPtrType() && |
| isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { |
| ConvertedType = ToType; |
| return true; |
| } |
| |
| const PointerType* ToTypePtr = ToType->getAs<PointerType>(); |
| if (!ToTypePtr) |
| return false; |
| |
| // A null pointer constant can be converted to a pointer type (C++ 4.10p1). |
| if (isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { |
| ConvertedType = ToType; |
| return true; |
| } |
| |
| // Beyond this point, both types need to be pointers |
| // , including objective-c pointers. |
| QualType ToPointeeType = ToTypePtr->getPointeeType(); |
| if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType() && |
| !getLangOpts().ObjCAutoRefCount) { |
| ConvertedType = BuildSimilarlyQualifiedPointerType( |
| FromType->getAs<ObjCObjectPointerType>(), |
| ToPointeeType, |
| ToType, Context); |
| return true; |
| } |
| const PointerType *FromTypePtr = FromType->getAs<PointerType>(); |
| if (!FromTypePtr) |
| return false; |
| |
| QualType FromPointeeType = FromTypePtr->getPointeeType(); |
| |
| // If the unqualified pointee types are the same, this can't be a |
| // pointer conversion, so don't do all of the work below. |
| if (Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) |
| return false; |
| |
| // An rvalue of type "pointer to cv T," where T is an object type, |
| // can be converted to an rvalue of type "pointer to cv void" (C++ |
| // 4.10p2). |
| if (FromPointeeType->isIncompleteOrObjectType() && |
| ToPointeeType->isVoidType()) { |
| ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, |
| ToPointeeType, |
| ToType, Context, |
| /*StripObjCLifetime=*/true); |
| return true; |
| } |
| |
| // MSVC allows implicit function to void* type conversion. |
| if (getLangOpts().MSVCCompat && FromPointeeType->isFunctionType() && |
| ToPointeeType->isVoidType()) { |
| ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, |
| ToPointeeType, |
| ToType, Context); |
| return true; |
| } |
| |
| // When we're overloading in C, we allow a special kind of pointer |
| // conversion for compatible-but-not-identical pointee types. |
| if (!getLangOpts().CPlusPlus && |
| Context.typesAreCompatible(FromPointeeType, ToPointeeType)) { |
| ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, |
| ToPointeeType, |
| ToType, Context); |
| return true; |
| } |
| |
| // C++ [conv.ptr]p3: |
| // |
| // An rvalue of type "pointer to cv D," where D is a class type, |
| // can be converted to an rvalue of type "pointer to cv B," where |
| // B is a base class (clause 10) of D. If B is an inaccessible |
| // (clause 11) or ambiguous (10.2) base class of D, a program that |
| // necessitates this conversion is ill-formed. The result of the |
| // conversion is a pointer to the base class sub-object of the |
| // derived class object. The null pointer value is converted to |
| // the null pointer value of the destination type. |
| // |
| // Note that we do not check for ambiguity or inaccessibility |
| // here. That is handled by CheckPointerConversion. |
| if (getLangOpts().CPlusPlus && FromPointeeType->isRecordType() && |
| ToPointeeType->isRecordType() && |
| !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) && |
| IsDerivedFrom(From->getBeginLoc(), FromPointeeType, ToPointeeType)) { |
| ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, |
| ToPointeeType, |
| ToType, Context); |
| return true; |
| } |
| |
| if (FromPointeeType->isVectorType() && ToPointeeType->isVectorType() && |
| Context.areCompatibleVectorTypes(FromPointeeType, ToPointeeType)) { |
| ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, |
| ToPointeeType, |
| ToType, Context); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// Adopt the given qualifiers for the given type. |
| static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ |
| Qualifiers TQs = T.getQualifiers(); |
| |
| // Check whether qualifiers already match. |
| if (TQs == Qs) |
| return T; |
| |
| if (Qs.compatiblyIncludes(TQs)) |
| return Context.getQualifiedType(T, Qs); |
| |
| return Context.getQualifiedType(T.getUnqualifiedType(), Qs); |
| } |
| |
| /// isObjCPointerConversion - Determines whether this is an |
| /// Objective-C pointer conversion. Subroutine of IsPointerConversion, |
| /// with the same arguments and return values. |
| bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, |
| QualType& ConvertedType, |
| bool &IncompatibleObjC) { |
| if (!getLangOpts().ObjC) |
| return false; |
| |
| // The set of qualifiers on the type we're converting from. |
| Qualifiers FromQualifiers = FromType.getQualifiers(); |
| |
| // First, we handle all conversions on ObjC object pointer types. |
| const ObjCObjectPointerType* ToObjCPtr = |
| ToType->getAs<ObjCObjectPointerType>(); |
| const ObjCObjectPointerType *FromObjCPtr = |
| FromType->getAs<ObjCObjectPointerType>(); |
| |
| if (ToObjCPtr && FromObjCPtr) { |
| // If the pointee types are the same (ignoring qualifications), |
| // then this is not a pointer conversion. |
| if (Context.hasSameUnqualifiedType(ToObjCPtr->getPointeeType(), |
| FromObjCPtr->getPointeeType())) |
| return false; |
| |
| // Conversion between Objective-C pointers. |
| if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) { |
| const ObjCInterfaceType* LHS = ToObjCPtr->getInterfaceType(); |
| const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType(); |
| if (getLangOpts().CPlusPlus && LHS && RHS && |
| !ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs( |
| FromObjCPtr->getPointeeType())) |
| return false; |
| ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, |
| ToObjCPtr->getPointeeType(), |
| ToType, Context); |
| ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); |
| return true; |
| } |
| |
| if (Context.canAssignObjCInterfaces(FromObjCPtr, ToObjCPtr)) { |
| // Okay: this is some kind of implicit downcast of Objective-C |
| // interfaces, which is permitted. However, we're going to |
| // complain about it. |
| IncompatibleObjC = true; |
| ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, |
| ToObjCPtr->getPointeeType(), |
| ToType, Context); |
| ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); |
| return true; |
| } |
| } |
| // Beyond this point, both types need to be C pointers or block pointers. |
| QualType ToPointeeType; |
| if (const PointerType *ToCPtr = ToType->getAs<PointerType>()) |
| ToPointeeType = ToCPtr->getPointeeType(); |
| else if (const BlockPointerType *ToBlockPtr = |
| ToType->getAs<BlockPointerType>()) { |
| // Objective C++: We're able to convert from a pointer to any object |
| // to a block pointer type. |
| if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) { |
| ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); |
| return true; |
| } |
| ToPointeeType = ToBlockPtr->getPointeeType(); |
| } |
| else if (FromType->getAs<BlockPointerType>() && |
| ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) { |
| // Objective C++: We're able to convert from a block pointer type to a |
| // pointer to any object. |
| ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); |
| return true; |
| } |
| else |
| return false; |
| |
| QualType FromPointeeType; |
| if (const PointerType *FromCPtr = FromType->getAs<PointerType>()) |
| FromPointeeType = FromCPtr->getPointeeType(); |
| else if (const BlockPointerType *FromBlockPtr = |
| FromType->getAs<BlockPointerType>()) |
| FromPointeeType = FromBlockPtr->getPointeeType(); |
| else |
| return false; |
| |
| // If we have pointers to pointers, recursively check whether this |
| // is an Objective-C conversion. |
| if (FromPointeeType->isPointerType() && ToPointeeType->isPointerType() && |
| isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, |
| IncompatibleObjC)) { |
| // We always complain about this conversion. |
| IncompatibleObjC = true; |
| ConvertedType = Context.getPointerType(ConvertedType); |
| ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); |
| return true; |
| } |
| // Allow conversion of pointee being objective-c pointer to another one; |
| // as in I* to id. |
| if (FromPointeeType->getAs<ObjCObjectPointerType>() && |
| ToPointeeType->getAs<ObjCObjectPointerType>() && |
| isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, |
| IncompatibleObjC)) { |
| |
| ConvertedType = Context.getPointerType(ConvertedType); |
| ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); |
| return true; |
| } |
| |
| // If we have pointers to functions or blocks, check whether the only |
| // differences in the argument and result types are in Objective-C |
| // pointer conversions. If so, we permit the conversion (but |
| // complain about it). |
| const FunctionProtoType *FromFunctionType |
| = FromPointeeType->getAs<FunctionProtoType>(); |
| const FunctionProtoType *ToFunctionType |
| = ToPointeeType->getAs<FunctionProtoType>(); |
| if (FromFunctionType && ToFunctionType) { |
| // If the function types are exactly the same, this isn't an |
| // Objective-C pointer conversion. |
| if (Context.getCanonicalType(FromPointeeType) |
| == Context.getCanonicalType(ToPointeeType)) |
| return false; |
| |
| // Perform the quick checks that will tell us whether these |
| // function types are obviously different. |
| if (FromFunctionType->getNumParams() != ToFunctionType->getNumParams() || |
| FromFunctionType->isVariadic() != ToFunctionType->isVariadic() || |
| FromFunctionType->getMethodQuals() != ToFunctionType->getMethodQuals()) |
| return false; |
| |
| bool HasObjCConversion = false; |
| if (Context.getCanonicalType(FromFunctionType->getReturnType()) == |
| Context.getCanonicalType(ToFunctionType->getReturnType())) { |
| // Okay, the types match exactly. Nothing to do. |
| } else if (isObjCPointerConversion(FromFunctionType->getReturnType(), |
| ToFunctionType->getReturnType(), |
| ConvertedType, IncompatibleObjC)) { |
| // Okay, we have an Objective-C pointer conversion. |
| HasObjCConversion = true; |
| } else { |
| // Function types are too different. Abort. |
| return false; |
| } |
| |
| // Check argument types. |
| for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumParams(); |
| ArgIdx != NumArgs; ++ArgIdx) { |
| QualType FromArgType = FromFunctionType->getParamType(ArgIdx); |
| QualType ToArgType = ToFunctionType->getParamType(ArgIdx); |
| if (Context.getCanonicalType(FromArgType) |
| == Context.getCanonicalType(ToArgType)) { |
| // Okay, the types match exactly. Nothing to do. |
| } else if (isObjCPointerConversion(FromArgType, ToArgType, |
| ConvertedType, IncompatibleObjC)) { |
| // Okay, we have an Objective-C pointer conversion. |
| HasObjCConversion = true; |
| } else { |
| // Argument types are too different. Abort. |
| return false; |
| } |
| } |
| |
| if (HasObjCConversion) { |
| // We had an Objective-C conversion. Allow this pointer |
| // conversion, but complain about it. |
| ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); |
| IncompatibleObjC = true; |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /// 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. |
| /// |
| /// \param ToType The type we're converting to. |
| /// |
| /// \param ConvertedType The type that will be produced after applying |
| /// this conversion. |
| bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType, |
| QualType &ConvertedType) { |
| if (!getLangOpts().ObjCAutoRefCount || |
| Context.hasSameUnqualifiedType(FromType, ToType)) |
| return false; |
| |
| // Parameter must be a pointer to __autoreleasing (with no other qualifiers). |
| QualType ToPointee; |
| if (const PointerType *ToPointer = ToType->getAs<PointerType>()) |
| ToPointee = ToPointer->getPointeeType(); |
| else |
| return false; |
| |
| Qualifiers ToQuals = ToPointee.getQualifiers(); |
| if (!ToPointee->isObjCLifetimeType() || |
| ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing || |
| !ToQuals.withoutObjCLifetime().empty()) |
| return false; |
| |
| // Argument must be a pointer to __strong to __weak. |
| QualType FromPointee; |
| if (const PointerType *FromPointer = FromType->getAs<PointerType>()) |
| FromPointee = FromPointer->getPointeeType(); |
| else |
| return false; |
| |
| Qualifiers FromQuals = FromPointee.getQualifiers(); |
| if (!FromPointee->isObjCLifetimeType() || |
| (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong && |
| FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak)) |
| return false; |
| |
| // Make sure that we have compatible qualifiers. |
| FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing); |
| if (!ToQuals.compatiblyIncludes(FromQuals)) |
| return false; |
| |
| // Remove qualifiers from the pointee type we're converting from; they |
| // aren't used in the compatibility check belong, and we'll be adding back |
| // qualifiers (with __autoreleasing) if the compatibility check succeeds. |
| FromPointee = FromPointee.getUnqualifiedType(); |
| |
| // The unqualified form of the pointee types must be compatible. |
| ToPointee = ToPointee.getUnqualifiedType(); |
| bool IncompatibleObjC; |
| if (Context.typesAreCompatible(FromPointee, ToPointee)) |
| FromPointee = ToPointee; |
| else if (!isObjCPointerConversion(FromPointee, ToPointee, FromPointee, |
| IncompatibleObjC)) |
| return false; |
| |
| /// Construct the type we're converting to, which is a pointer to |
| /// __autoreleasing pointee. |
| FromPointee = Context.getQualifiedType(FromPointee, FromQuals); |
| ConvertedType = Context.getPointerType(FromPointee); |
| return true; |
| } |
| |
| bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, |
| QualType& ConvertedType) { |
| QualType ToPointeeType; |
| if (const BlockPointerType *ToBlockPtr = |
| ToType->getAs<BlockPointerType>()) |
| ToPointeeType = ToBlockPtr->getPointeeType(); |
| else |
| return false; |
| |
| QualType FromPointeeType; |
| if (const BlockPointerType *FromBlockPtr = |
| FromType->getAs<BlockPointerType>()) |
| FromPointeeType = FromBlockPtr->getPointeeType(); |
| else |
| return false; |
| // We have pointer to blocks, check whether the only |
| // differences in the argument and result types are in Objective-C |
| // pointer conversions. If so, we permit the conversion. |
| |
| const FunctionProtoType *FromFunctionType |
| = FromPointeeType->getAs<FunctionProtoType>(); |
| const FunctionProtoType *ToFunctionType |
| = ToPointeeType->getAs<FunctionProtoType>(); |
| |
| if (!FromFunctionType || !ToFunctionType) |
| return false; |
| |
| if (Context.hasSameType(FromPointeeType, ToPointeeType)) |
| return true; |
| |
| // Perform the quick checks that will tell us whether these |
| // function types are obviously different. |
| if (FromFunctionType->getNumParams() != ToFunctionType->getNumParams() || |
| FromFunctionType->isVariadic() != ToFunctionType->isVariadic()) |
| return false; |
| |
| FunctionType::ExtInfo FromEInfo = FromFunctionType->getExtInfo(); |
| FunctionType::ExtInfo ToEInfo = ToFunctionType->getExtInfo(); |
| if (FromEInfo != ToEInfo) |
| return false; |
| |
| bool IncompatibleObjC = false; |
| if (Context.hasSameType(FromFunctionType->getReturnType(), |
| ToFunctionType->getReturnType())) { |
| // Okay, the types match exactly. Nothing to do. |
| } else { |
| QualType RHS = FromFunctionType->getReturnType(); |
| QualType LHS = ToFunctionType->getReturnType(); |
| if ((!getLangOpts().CPlusPlus || !RHS->isRecordType()) && |
| !RHS.hasQualifiers() && LHS.hasQualifiers()) |
| LHS = LHS.getUnqualifiedType(); |
| |
| if (Context.hasSameType(RHS,LHS)) { |
| // OK exact match. |
| } else if (isObjCPointerConversion(RHS, LHS, |
| ConvertedType, IncompatibleObjC)) { |
| if (IncompatibleObjC) |
| return false; |
| // Okay, we have an Objective-C pointer conversion. |
| } |
| else |
| return false; |
| } |
| |
| // Check argument types. |
| for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumParams(); |
| ArgIdx != NumArgs; ++ArgIdx) { |
| IncompatibleObjC = false; |
| QualType FromArgType = FromFunctionType->getParamType(ArgIdx); |
| QualType ToArgType = ToFunctionType->getParamType(ArgIdx); |
| if (Context.hasSameType(FromArgType, ToArgType)) { |
| // Okay, the types match exactly. Nothing to do. |
| } else if (isObjCPointerConversion(ToArgType, FromArgType, |
| ConvertedType, IncompatibleObjC)) { |
| if (IncompatibleObjC) |
| return false; |
| // Okay, we have an Objective-C pointer conversion. |
| } |