summaryrefslogtreecommitdiff
path: root/include/clang/Sema/Overload.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Sema/Overload.h')
-rw-r--r--include/clang/Sema/Overload.h145
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());
};