diff options
Diffstat (limited to 'lib/Sema/SemaOverload.h')
-rw-r--r-- | lib/Sema/SemaOverload.h | 184 |
1 files changed, 178 insertions, 6 deletions
diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h index 3613d60..20add00 100644 --- a/lib/Sema/SemaOverload.h +++ b/lib/Sema/SemaOverload.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_SEMA_OVERLOAD_H #include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -149,6 +150,15 @@ namespace clang { /// conversions. CXXConstructorDecl *CopyConstructor; + void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); } + void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); } + QualType getFromType() const { + return QualType::getFromOpaquePtr(FromTypePtr); + } + QualType getToType() const { + return QualType::getFromOpaquePtr(ToTypePtr); + } + void setAsIdentityConversion(); ImplicitConversionRank getRank() const; bool isPointerConversionToBool() const; @@ -190,6 +200,93 @@ namespace clang { void DebugPrint() const; }; + /// Represents an ambiguous user-defined conversion sequence. + struct AmbiguousConversionSequence { + typedef llvm::SmallVector<FunctionDecl*, 4> ConversionSet; + + void *FromTypePtr; + void *ToTypePtr; + char Buffer[sizeof(ConversionSet)]; + + QualType getFromType() const { + return QualType::getFromOpaquePtr(FromTypePtr); + } + QualType getToType() const { + return QualType::getFromOpaquePtr(ToTypePtr); + } + void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); } + void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); } + + ConversionSet &conversions() { + return *reinterpret_cast<ConversionSet*>(Buffer); + } + + const ConversionSet &conversions() const { + return *reinterpret_cast<const ConversionSet*>(Buffer); + } + + void addConversion(FunctionDecl *D) { + conversions().push_back(D); + } + + typedef ConversionSet::iterator iterator; + iterator begin() { return conversions().begin(); } + iterator end() { return conversions().end(); } + + typedef ConversionSet::const_iterator const_iterator; + const_iterator begin() const { return conversions().begin(); } + const_iterator end() const { return conversions().end(); } + + void construct(); + void destruct(); + void copyFrom(const AmbiguousConversionSequence &); + }; + + /// BadConversionSequence - Records information about an invalid + /// conversion sequence. + struct BadConversionSequence { + enum FailureKind { + no_conversion, + unrelated_class, + suppressed_user, + bad_qualifiers + }; + + // This can be null, e.g. for implicit object arguments. + Expr *FromExpr; + + FailureKind Kind; + + private: + // The type we're converting from (an opaque QualType). + void *FromTy; + + // The type we're converting to (an opaque QualType). + void *ToTy; + + public: + void init(FailureKind K, Expr *From, QualType To) { + init(K, From->getType(), To); + FromExpr = From; + } + void init(FailureKind K, QualType From, QualType To) { + Kind = K; + FromExpr = 0; + setFromType(From); + setToType(To); + } + + QualType getFromType() const { return QualType::getFromOpaquePtr(FromTy); } + QualType getToType() const { return QualType::getFromOpaquePtr(ToTy); } + + void setFromExpr(Expr *E) { + FromExpr = E; + setFromType(E->getType()); + } + void setFromType(QualType T) { FromTy = T.getAsOpaquePtr(); } + void setToType(QualType T) { ToTy = T.getAsOpaquePtr(); } + }; + /// ImplicitConversionSequence - Represents an implicit conversion /// sequence, which may be a standard conversion sequence /// (C++ 13.3.3.1.1), user-defined conversion sequence (C++ 13.3.3.1.2), @@ -197,18 +294,26 @@ namespace clang { struct ImplicitConversionSequence { /// Kind - The kind of implicit conversion sequence. BadConversion /// specifies that there is no conversion from the source type to - /// the target type. The enumerator values are ordered such that - /// better implicit conversions have smaller values. + /// the target type. AmbiguousConversion represents the unique + /// ambiguous conversion (C++0x [over.best.ics]p10). enum Kind { StandardConversion = 0, UserDefinedConversion, + AmbiguousConversion, EllipsisConversion, BadConversion }; + private: /// ConversionKind - The kind of implicit conversion sequence. Kind ConversionKind; + void setKind(Kind K) { + if (isAmbiguous()) Ambiguous.destruct(); + ConversionKind = K; + } + + public: union { /// When ConversionKind == StandardConversion, provides the /// details of the standard conversion sequence. @@ -217,12 +322,58 @@ namespace clang { /// When ConversionKind == UserDefinedConversion, provides the /// details of the user-defined conversion sequence. UserDefinedConversionSequence UserDefined; + + /// When ConversionKind == AmbiguousConversion, provides the + /// details of the ambiguous conversion. + AmbiguousConversionSequence Ambiguous; + + /// When ConversionKind == BadConversion, provides the details + /// of the bad conversion. + BadConversionSequence Bad; }; + + ImplicitConversionSequence() : ConversionKind(BadConversion) {} + ~ImplicitConversionSequence() { + if (isAmbiguous()) Ambiguous.destruct(); + } + ImplicitConversionSequence(const ImplicitConversionSequence &Other) + : ConversionKind(Other.ConversionKind) + { + switch (ConversionKind) { + case StandardConversion: Standard = Other.Standard; break; + case UserDefinedConversion: UserDefined = Other.UserDefined; break; + case AmbiguousConversion: Ambiguous.copyFrom(Other.Ambiguous); break; + case EllipsisConversion: break; + case BadConversion: Bad = Other.Bad; break; + } + } + + ImplicitConversionSequence & + operator=(const ImplicitConversionSequence &Other) { + if (isAmbiguous()) Ambiguous.destruct(); + new (this) ImplicitConversionSequence(Other); + return *this; + } - /// When ConversionKind == BadConversion due to multiple conversion - /// functions, this will list those functions. - llvm::SmallVector<FunctionDecl*, 4> ConversionFunctionSet; - + Kind getKind() const { return ConversionKind; } + bool isBad() const { return ConversionKind == BadConversion; } + bool isStandard() const { return ConversionKind == StandardConversion; } + bool isEllipsis() const { return ConversionKind == EllipsisConversion; } + bool isAmbiguous() const { return ConversionKind == AmbiguousConversion; } + bool isUserDefined() const { + return ConversionKind == UserDefinedConversion; + } + + void setBad() { setKind(BadConversion); } + void setStandard() { setKind(StandardConversion); } + void setEllipsis() { setKind(EllipsisConversion); } + void setUserDefined() { setKind(UserDefinedConversion); } + void setAmbiguous() { + if (isAmbiguous()) return; + ConversionKind = AmbiguousConversion; + Ambiguous.construct(); + } + // The result of a comparison between implicit conversion // sequences. Use Sema::CompareImplicitConversionSequences to // actually perform the comparison. @@ -235,6 +386,13 @@ namespace clang { void DebugPrint() const; }; + enum OverloadFailureKind { + ovl_fail_too_many_arguments, + ovl_fail_too_few_arguments, + ovl_fail_bad_conversion, + ovl_fail_bad_deduction + }; + /// OverloadCandidate - A single candidate in an overload set (C++ 13.3). struct OverloadCandidate { /// Function - The actual function that this candidate @@ -275,11 +433,25 @@ namespace clang { /// object argument. bool IgnoreObjectArgument; + /// FailureKind - The reason why this candidate is not viable. + /// Actually an OverloadFailureKind. + unsigned char FailureKind; + /// FinalConversion - For a conversion function (where Function is /// a CXXConversionDecl), the standard conversion that occurs /// after the call to the overload candidate to convert the result /// of calling the conversion function to the required type. StandardConversionSequence FinalConversion; + + /// hasAmbiguousConversion - Returns whether this overload + /// candidate requires an ambiguous conversion or not. + bool hasAmbiguousConversion() const { + for (llvm::SmallVectorImpl<ImplicitConversionSequence>::const_iterator + I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { + if (I->isAmbiguous()) return true; + } + return false; + } }; /// OverloadCandidateSet - A set of overload candidates, used in C++ |