diff options
Diffstat (limited to 'include/clang/Sema/Overload.h')
-rw-r--r-- | include/clang/Sema/Overload.h | 145 |
1 files changed, 125 insertions, 20 deletions
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index dbc0926f03afa..d334447edc57a 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -24,6 +24,7 @@ #include "clang/Sema/SemaFixItUtils.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" namespace clang { class ASTContext; @@ -111,6 +112,23 @@ namespace clang { ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind); + /// NarrowingKind - The kind of narrowing conversion being performed by a + /// standard conversion sequence according to C++11 [dcl.init.list]p7. + enum NarrowingKind { + /// Not a narrowing conversion. + NK_Not_Narrowing, + + /// A narrowing conversion by virtue of the source and destination types. + NK_Type_Narrowing, + + /// A narrowing conversion, because a constant expression got narrowed. + NK_Constant_Narrowing, + + /// A narrowing conversion, because a non-constant-expression variable might + /// have got narrowed. + NK_Variable_Narrowing + }; + /// StandardConversionSequence - represents a standard conversion /// sequence (C++ 13.3.3.1.1). A standard conversion sequence /// contains between zero and three conversions. If a particular @@ -217,6 +235,9 @@ namespace clang { } ImplicitConversionRank getRank() const; + NarrowingKind getNarrowingKind(ASTContext &Context, const Expr *Converted, + APValue &ConstantValue, + QualType &ConstantType) const; bool isPointerConversionToBool() const; bool isPointerConversionToVoidPointer(ASTContext& Context) const; void DebugPrint() const; @@ -225,9 +246,10 @@ namespace clang { /// UserDefinedConversionSequence - Represents a user-defined /// conversion sequence (C++ 13.3.3.1.2). struct UserDefinedConversionSequence { - /// Before - Represents the standard conversion that occurs before - /// the actual user-defined conversion. (C++ 13.3.3.1.2p1): + /// \brief Represents the standard conversion that occurs before + /// the actual user-defined conversion. /// + /// C++11 13.3.3.1.2p1: /// If the user-defined conversion is specified by a constructor /// (12.3.1), the initial standard conversion sequence converts /// the source type to the type required by the argument of the @@ -255,14 +277,15 @@ namespace clang { StandardConversionSequence After; /// ConversionFunction - The function that will perform the - /// user-defined conversion. + /// user-defined conversion. Null if the conversion is an + /// aggregate initialization from an initializer list. FunctionDecl* ConversionFunction; /// \brief The declaration that we found via name lookup, which might be /// the same as \c ConversionFunction or it might be a using declaration /// that refers to \c ConversionFunction. DeclAccessPair FoundConversionFunction; - + void DebugPrint() const; }; @@ -379,7 +402,14 @@ namespace clang { }; /// ConversionKind - The kind of implicit conversion sequence. - unsigned ConversionKind; + unsigned ConversionKind : 30; + + /// \brief Whether the argument is an initializer list. + bool ListInitializationSequence : 1; + + /// \brief Whether the target is really a std::initializer_list, and the + /// sequence only represents the worst element conversion. + bool StdInitializerListElement : 1; void setKind(Kind K) { destruct(); @@ -409,12 +439,17 @@ namespace clang { BadConversionSequence Bad; }; - ImplicitConversionSequence() : ConversionKind(Uninitialized) {} + ImplicitConversionSequence() + : ConversionKind(Uninitialized), ListInitializationSequence(false), + StdInitializerListElement(false) + {} ~ImplicitConversionSequence() { destruct(); } ImplicitConversionSequence(const ImplicitConversionSequence &Other) - : ConversionKind(Other.ConversionKind) + : ConversionKind(Other.ConversionKind), + ListInitializationSequence(Other.ListInitializationSequence), + StdInitializerListElement(Other.StdInitializerListElement) { switch (ConversionKind) { case Uninitialized: break; @@ -461,7 +496,7 @@ namespace clang { return 3; } - return 3; + llvm_unreachable("Invalid ImplicitConversionSequence::Kind!"); } bool isBad() const { return getKind() == BadConversion; } @@ -499,6 +534,26 @@ namespace clang { Ambiguous.construct(); } + /// \brief Whether this sequence was created by the rules of + /// list-initialization sequences. + bool isListInitializationSequence() const { + return ListInitializationSequence; + } + + void setListInitializationSequence() { + ListInitializationSequence = true; + } + + /// \brief Whether the target is really a std::initializer_list, and the + /// sequence only represents the worst element conversion. + bool isStdInitializerListElement() const { + return StdInitializerListElement; + } + + void setStdInitializerListElement(bool V = true) { + StdInitializerListElement = V; + } + // The result of a comparison between implicit conversion // sequences. Use Sema::CompareImplicitConversionSequences to // actually perform the comparison. @@ -565,12 +620,17 @@ namespace clang { CXXConversionDecl *Surrogate; /// Conversions - The conversion sequences used to convert the - /// function arguments to the function parameters. - SmallVector<ImplicitConversionSequence, 4> Conversions; + /// function arguments to the function parameters, the pointer points to a + /// fixed size array with NumConversions elements. The memory is owned by + /// the OverloadCandidateSet. + ImplicitConversionSequence *Conversions; /// The FixIt hints which can be used to fix the Bad candidate. ConversionFixItGenerator Fix; + /// NumConversions - The number of elements in the Conversions array. + unsigned NumConversions; + /// Viable - True to indicate that this overload candidate is viable. bool Viable; @@ -639,10 +699,9 @@ namespace clang { /// hasAmbiguousConversion - Returns whether this overload /// candidate requires an ambiguous conversion or not. bool hasAmbiguousConversion() const { - for (SmallVectorImpl<ImplicitConversionSequence>::const_iterator - I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { - if (!I->isInitialized()) return false; - if (I->isAmbiguous()) return true; + for (unsigned i = 0, e = NumConversions; i != e; ++i) { + if (!Conversions[i].isInitialized()) return false; + if (Conversions[i].isAmbiguous()) return true; } return false; } @@ -663,17 +722,29 @@ namespace clang { /// OverloadCandidateSet - A set of overload candidates, used in C++ /// overload resolution (C++ 13.3). - class OverloadCandidateSet : public SmallVector<OverloadCandidate, 16> { - typedef SmallVector<OverloadCandidate, 16> inherited; + class OverloadCandidateSet { + SmallVector<OverloadCandidate, 16> Candidates; llvm::SmallPtrSet<Decl *, 16> Functions; - SourceLocation Loc; - + // Allocator for OverloadCandidate::Conversions. We store the first few + // elements inline to avoid allocation for small sets. + llvm::BumpPtrAllocator ConversionSequenceAllocator; + + SourceLocation Loc; + + unsigned NumInlineSequences; + char InlineSpace[16 * sizeof(ImplicitConversionSequence)]; + OverloadCandidateSet(const OverloadCandidateSet &); OverloadCandidateSet &operator=(const OverloadCandidateSet &); public: - OverloadCandidateSet(SourceLocation Loc) : Loc(Loc) {} + OverloadCandidateSet(SourceLocation Loc) : Loc(Loc), NumInlineSequences(0){} + ~OverloadCandidateSet() { + for (iterator i = begin(), e = end(); i != e; ++i) + for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) + i->Conversions[ii].~ImplicitConversionSequence(); + } SourceLocation getLocation() const { return Loc; } @@ -686,6 +757,40 @@ namespace clang { /// \brief Clear out all of the candidates. void clear(); + typedef SmallVector<OverloadCandidate, 16>::iterator iterator; + iterator begin() { return Candidates.begin(); } + iterator end() { return Candidates.end(); } + + size_t size() const { return Candidates.size(); } + bool empty() const { return Candidates.empty(); } + + /// \brief Add a new candidate with NumConversions conversion sequence slots + /// to the overload set. + OverloadCandidate &addCandidate(unsigned NumConversions = 0) { + Candidates.push_back(OverloadCandidate()); + OverloadCandidate &C = Candidates.back(); + + // Assign space from the inline array if there are enough free slots + // available. + if (NumConversions + NumInlineSequences <= 16) { + ImplicitConversionSequence *I = + (ImplicitConversionSequence*)InlineSpace; + C.Conversions = &I[NumInlineSequences]; + NumInlineSequences += NumConversions; + } else { + // Otherwise get memory from the allocator. + C.Conversions = ConversionSequenceAllocator + .Allocate<ImplicitConversionSequence>(NumConversions); + } + + // Construct the new objects. + for (unsigned i = 0; i != NumConversions; ++i) + new (&C.Conversions[i]) ImplicitConversionSequence(); + + C.NumConversions = NumConversions; + return C; + } + /// Find the best viable function on this overload set, if it exists. OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator& Best, @@ -693,7 +798,7 @@ namespace clang { void NoteCandidates(Sema &S, OverloadCandidateDisplayKind OCD, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, const char *Opc = 0, SourceLocation Loc = SourceLocation()); }; |