summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-10-19 00:04:38 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-10-19 00:04:38 +0000
commitea521aa6024431138f7890d486a6e3500822b3d5 (patch)
treefdac644533e0b19bd5e54c53170aaea83d86f668 /include
parent3b03365d5fddd6485581747d7a7ba1799d94241f (diff)
downloadclang-ea521aa6024431138f7890d486a6e3500822b3d5.tar.gz
[c++20] Add CXXRewrittenBinaryOperator to represent a comparison
operator that is rewritten as a call to multiple other operators. No functionality change yet: nothing creates these expressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@375305 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/clang/AST/ExprCXX.h90
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h9
-rw-r--r--include/clang/AST/Stmt.h10
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Serialization/ASTBitCodes.h3
5 files changed, 113 insertions, 0 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 9c05de6fdc..2b3085183c 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -220,6 +220,96 @@ public:
}
};
+/// A rewritten comparison expression that was originally written using
+/// operator syntax.
+///
+/// In C++20, the following rewrites are performed:
+/// - <tt>a == b</tt> -> <tt>b == a</tt>
+/// - <tt>a != b</tt> -> <tt>!(a == b)</tt>
+/// - <tt>a != b</tt> -> <tt>!(b == a)</tt>
+/// - For \c \@ in \c <, \c <=, \c >, \c >=, \c <=>:
+/// - <tt>a @ b<tt> -> <tt>(a <=> b) @ 0</tt>
+/// - <tt>a @ b<tt> -> <tt>0 @ (b <=> a)</tt>
+///
+/// This expression provides access to both the original syntax and the
+/// rewritten expression.
+///
+/// Note that the rewritten calls to \c ==, \c <=>, and \c \@ are typically
+/// \c CXXOperatorCallExprs, but could theoretically be \c BinaryOperators.
+class CXXRewrittenBinaryOperator : public Expr {
+ friend class ASTStmtReader;
+
+ /// The rewritten semantic form.
+ Stmt *SemanticForm;
+
+public:
+ CXXRewrittenBinaryOperator(Expr *SemanticForm, bool IsReversed)
+ : Expr(CXXRewrittenBinaryOperatorClass, SemanticForm->getType(),
+ SemanticForm->getValueKind(), SemanticForm->getObjectKind(),
+ SemanticForm->isTypeDependent(), SemanticForm->isValueDependent(),
+ SemanticForm->isInstantiationDependent(),
+ SemanticForm->containsUnexpandedParameterPack()),
+ SemanticForm(SemanticForm) {
+ CXXRewrittenBinaryOperatorBits.IsReversed = IsReversed;
+ }
+ CXXRewrittenBinaryOperator(EmptyShell Empty)
+ : Expr(CXXRewrittenBinaryOperatorClass, Empty), SemanticForm() {}
+
+ /// Get an equivalent semantic form for this expression.
+ Expr *getSemanticForm() { return cast<Expr>(SemanticForm); }
+ const Expr *getSemanticForm() const { return cast<Expr>(SemanticForm); }
+
+ struct DecomposedForm {
+ /// The original opcode, prior to rewriting.
+ BinaryOperatorKind Opcode;
+ /// The original left-hand side.
+ const Expr *LHS;
+ /// The original right-hand side.
+ const Expr *RHS;
+ /// The inner \c == or \c <=> operator expression.
+ const Expr *InnerBinOp;
+ };
+
+ /// Decompose this operator into its syntactic form.
+ DecomposedForm getDecomposedForm() const LLVM_READONLY;
+
+ /// Determine whether this expression was rewritten in reverse form.
+ bool isReversed() const { return CXXRewrittenBinaryOperatorBits.IsReversed; }
+
+ BinaryOperatorKind getOperator() const { return getDecomposedForm().Opcode; }
+ const Expr *getLHS() const { return getDecomposedForm().LHS; }
+ const Expr *getRHS() const { return getDecomposedForm().RHS; }
+
+ SourceLocation getOperatorLoc() const LLVM_READONLY {
+ return getDecomposedForm().InnerBinOp->getExprLoc();
+ }
+ SourceLocation getExprLoc() const LLVM_READONLY { return getOperatorLoc(); }
+
+ /// Compute the begin and end locations from the decomposed form.
+ /// The locations of the semantic form are not reliable if this is
+ /// a reversed expression.
+ //@{
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getDecomposedForm().LHS->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getDecomposedForm().RHS->getEndLoc();
+ }
+ SourceRange getSourceRange() const LLVM_READONLY {
+ DecomposedForm DF = getDecomposedForm();
+ return SourceRange(DF.LHS->getBeginLoc(), DF.RHS->getEndLoc());
+ }
+ //@}
+
+ child_range children() {
+ return child_range(&SemanticForm, &SemanticForm + 1);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXRewrittenBinaryOperatorClass;
+ }
+};
+
/// Represents a call to a CUDA kernel function.
class CUDAKernelCallExpr final : public CallExpr {
friend class ASTStmtReader;
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index c01a2da926..5b58eab95d 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -2606,6 +2606,15 @@ DEF_TRAVERSE_STMT(SEHLeaveStmt, {})
DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
+DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ CXXRewrittenBinaryOperator::DecomposedForm Decomposed =
+ S->getDecomposedForm();
+ TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.LHS)));
+ TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.RHS)));
+ ShouldVisitChildren = false;
+ }
+})
DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
DEF_TRAVERSE_STMT(TypoExpr, {})
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 403b88ac3a..7aebbf2cb6 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -604,6 +604,15 @@ protected:
unsigned FPFeatures : 3;
};
+ class CXXRewrittenBinaryOperatorBitfields {
+ friend class ASTStmtReader;
+ friend class CXXRewrittenBinaryOperator;
+
+ unsigned : NumCallExprBits;
+
+ unsigned IsReversed : 1;
+ };
+
class CXXBoolLiteralExprBitfields {
friend class CXXBoolLiteralExpr;
@@ -978,6 +987,7 @@ protected:
// C++ Expressions
CXXOperatorCallExprBitfields CXXOperatorCallExprBits;
+ CXXRewrittenBinaryOperatorBitfields CXXRewrittenBinaryOperatorBits;
CXXBoolLiteralExprBitfields CXXBoolLiteralExprBits;
CXXNullPtrLiteralExprBitfields CXXNullPtrLiteralExprBits;
CXXThisExprBitfields CXXThisExprBits;
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 8d972f75e4..59444b2919 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -114,6 +114,7 @@ def GNUNullExpr : DStmt<Expr>;
// C++ Expressions.
def CXXOperatorCallExpr : DStmt<CallExpr>;
def CXXMemberCallExpr : DStmt<CallExpr>;
+def CXXRewrittenBinaryOperator : DStmt<Expr>;
def CXXNamedCastExpr : DStmt<ExplicitCastExpr, 1>;
def CXXStaticCastExpr : DStmt<CXXNamedCastExpr>;
def CXXDynamicCastExpr : DStmt<CXXNamedCastExpr>;
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index b95c281a58..f310572754 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1845,6 +1845,9 @@ namespace serialization {
/// A CXXMemberCallExpr record.
EXPR_CXX_MEMBER_CALL,
+ /// A CXXRewrittenBinaryOperator record.
+ EXPR_CXX_REWRITTEN_BINARY_OPERATOR,
+
/// A CXXConstructExpr record.
EXPR_CXX_CONSTRUCT,