diff options
author | John McCall <rjmccall@apple.com> | 2010-01-12 00:44:57 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-01-12 00:44:57 +0000 |
commit | 0d1da2298aaa8a01e7672cba6f4f2151640b5552 (patch) | |
tree | 3905bfcca99e5a4a48d53dec57244dec3f6c2495 /clang/lib/Sema/SemaOverload.h | |
parent | 87be3617e3bf6ce34a417d9064649f4b315177a7 (diff) | |
download | bcm5719-llvm-0d1da2298aaa8a01e7672cba6f4f2151640b5552.tar.gz bcm5719-llvm-0d1da2298aaa8a01e7672cba6f4f2151640b5552.zip |
Introduce a specific representation for the ambiguous implicit conversion
sequence. Lots of small relevant changes. Fixes some serious problems with
ambiguous conversions; also possibly improves associated diagnostics.
llvm-svn: 93214
Diffstat (limited to 'clang/lib/Sema/SemaOverload.h')
-rw-r--r-- | clang/lib/Sema/SemaOverload.h | 123 |
1 files changed, 117 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaOverload.h b/clang/lib/Sema/SemaOverload.h index 3613d608834..78fa05b24cf 100644 --- a/clang/lib/Sema/SemaOverload.h +++ b/clang/lib/Sema/SemaOverload.h @@ -149,6 +149,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 +199,48 @@ 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 &); + }; + /// 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 +248,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 +276,54 @@ 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; }; + + 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: 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. @@ -280,6 +381,16 @@ namespace clang { /// 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++ |