diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-10-19 00:04:38 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-10-19 00:04:38 +0000 |
commit | ea521aa6024431138f7890d486a6e3500822b3d5 (patch) | |
tree | fdac644533e0b19bd5e54c53170aaea83d86f668 /include | |
parent | 3b03365d5fddd6485581747d7a7ba1799d94241f (diff) | |
download | clang-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.h | 90 | ||||
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 9 | ||||
-rw-r--r-- | include/clang/AST/Stmt.h | 10 | ||||
-rw-r--r-- | include/clang/Basic/StmtNodes.td | 1 | ||||
-rw-r--r-- | include/clang/Serialization/ASTBitCodes.h | 3 |
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, |