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.h94
1 files changed, 87 insertions, 7 deletions
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index 144e6d927c..a97a7181f7 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -71,6 +71,30 @@ class Sema;
OCD_ViableCandidates
};
+ /// The parameter ordering that will be used for the candidate. This is
+ /// used to represent C++20 binary operator rewrites that reverse the order
+ /// of the arguments. If the parameter ordering is Reversed, the Args list is
+ /// reversed (but obviously the ParamDecls for the function are not).
+ ///
+ /// After forming an OverloadCandidate with reversed parameters, the list
+ /// of conversions will (as always) be indexed by argument, so will be
+ /// in reverse parameter order.
+ enum class OverloadCandidateParamOrder : char { Normal, Reversed };
+
+ /// The kinds of rewrite we perform on overload candidates. Note that the
+ /// values here are chosen to serve as both bitflags and as a rank (lower
+ /// values are preferred by overload resolution).
+ enum OverloadCandidateRewriteKind : unsigned {
+ /// Candidate is not a rewritten candidate.
+ CRK_None = 0x0,
+
+ /// Candidate is a rewritten candidate with a different operator name.
+ CRK_DifferentOperator = 0x1,
+
+ /// Candidate is a rewritten candidate with a reversed order of parameters.
+ CRK_Reversed = 0x2,
+ };
+
/// ImplicitConversionKind - The kind of implicit conversion used to
/// convert an argument to a parameter's type. The enumerator values
/// match with the table titled 'Conversions' in [over.ics.scs] and are listed
@@ -757,7 +781,8 @@ class Sema;
CXXConversionDecl *Surrogate;
/// The conversion sequences used to convert the function arguments
- /// to the function parameters.
+ /// to the function parameters. Note that these are indexed by argument,
+ /// so may not match the parameter order of Function.
ConversionSequenceList Conversions;
/// The FixIt hints which can be used to fix the Bad candidate.
@@ -783,6 +808,9 @@ class Sema;
/// True if the candidate was found using ADL.
CallExpr::ADLCallKind IsADLCandidate : 1;
+ /// Whether this is a rewritten candidate, and if so, of what kind?
+ OverloadCandidateRewriteKind RewriteKind : 2;
+
/// FailureKind - The reason why this candidate is not viable.
/// Actually an OverloadFailureKind.
unsigned char FailureKind;
@@ -838,7 +866,8 @@ class Sema;
private:
friend class OverloadCandidateSet;
- OverloadCandidate() : IsADLCandidate(CallExpr::NotADL) {}
+ OverloadCandidate()
+ : IsADLCandidate(CallExpr::NotADL), RewriteKind(CRK_None) {}
};
/// OverloadCandidateSet - A set of overload candidates, used in C++
@@ -867,9 +896,54 @@ class Sema;
CSK_InitByConstructor,
};
+ /// Information about operator rewrites to consider when adding operator
+ /// functions to a candidate set.
+ struct OperatorRewriteInfo {
+ OperatorRewriteInfo()
+ : OriginalOperator(OO_None), AllowRewrittenCandidates(false) {}
+ OperatorRewriteInfo(OverloadedOperatorKind Op, bool AllowRewritten)
+ : OriginalOperator(Op), AllowRewrittenCandidates(AllowRewritten) {}
+
+ /// The original operator as written in the source.
+ OverloadedOperatorKind OriginalOperator;
+ /// Whether we should include rewritten candidates in the overload set.
+ bool AllowRewrittenCandidates;
+
+ /// Would use of this function result in a rewrite using a different
+ /// operator?
+ bool isRewrittenOperator(const FunctionDecl *FD) {
+ return OriginalOperator &&
+ FD->getDeclName().getCXXOverloadedOperator() != OriginalOperator;
+ }
+
+ bool isAcceptableCandidate(const FunctionDecl *FD) {
+ return AllowRewrittenCandidates || !isRewrittenOperator(FD);
+ }
+
+ /// Determine the kind of rewrite that should be performed for this
+ /// candidate.
+ OverloadCandidateRewriteKind
+ getRewriteKind(const FunctionDecl *FD, OverloadCandidateParamOrder PO) {
+ OverloadCandidateRewriteKind CRK = CRK_None;
+ if (isRewrittenOperator(FD))
+ CRK = OverloadCandidateRewriteKind(CRK | CRK_DifferentOperator);
+ if (PO == OverloadCandidateParamOrder::Reversed)
+ CRK = OverloadCandidateRewriteKind(CRK | CRK_Reversed);
+ return CRK;
+ }
+
+ /// Determine whether we should consider looking for and adding reversed
+ /// candidates for operator Op.
+ bool shouldAddReversed(OverloadedOperatorKind Op);
+
+ /// Determine whether we should add a rewritten candidate for \p FD with
+ /// reversed parameter order.
+ bool shouldAddReversed(ASTContext &Ctx, const FunctionDecl *FD);
+ };
+
private:
SmallVector<OverloadCandidate, 16> Candidates;
- llvm::SmallPtrSet<Decl *, 16> Functions;
+ llvm::SmallPtrSet<uintptr_t, 16> Functions;
// Allocator for ConversionSequenceLists. We store the first few of these
// inline to avoid allocation for small sets.
@@ -877,6 +951,7 @@ class Sema;
SourceLocation Loc;
CandidateSetKind Kind;
+ OperatorRewriteInfo RewriteInfo;
constexpr static unsigned NumInlineBytes =
24 * sizeof(ImplicitConversionSequence);
@@ -915,19 +990,24 @@ class Sema;
void destroyCandidates();
public:
- OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK)
- : Loc(Loc), Kind(CSK) {}
+ OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK,
+ OperatorRewriteInfo RewriteInfo = {})
+ : Loc(Loc), Kind(CSK), RewriteInfo(RewriteInfo) {}
OverloadCandidateSet(const OverloadCandidateSet &) = delete;
OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete;
~OverloadCandidateSet() { destroyCandidates(); }
SourceLocation getLocation() const { return Loc; }
CandidateSetKind getKind() const { return Kind; }
+ OperatorRewriteInfo getRewriteInfo() const { return RewriteInfo; }
/// Determine when this overload candidate will be new to the
/// overload set.
- bool isNewCandidate(Decl *F) {
- return Functions.insert(F->getCanonicalDecl()).second;
+ bool isNewCandidate(Decl *F, OverloadCandidateParamOrder PO =
+ OverloadCandidateParamOrder::Normal) {
+ uintptr_t Key = reinterpret_cast<uintptr_t>(F->getCanonicalDecl());
+ Key |= static_cast<uintptr_t>(PO);
+ return Functions.insert(Key).second;
}
/// Clear out all of the candidates.