From: Ted Kremenek Date: Fri, 24 Aug 2007 18:13:47 +0000 (+0000) Subject: Began implementing "child iterator" interface for Stmts and Exprs. Each X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=77ed8e4edf6ed78c53fb20ec3210aff2a59c9d87;p=clang Began implementing "child iterator" interface for Stmts and Exprs. Each subclass of Stmt will implement child_begin() and child_end(), which will be used to iterate over all the children (subexpressions/substatements) of a Stmt object. This will provide for easy traversal over the AST, which is useful for a variety of purposes. None of the interfaces to subclasses of Stmt will be changed (other than adding the child_begin and child_end methods). The only caveat is that the implementation of subclasses of Stmt will require colocating all substatements (subexpressions) in an array. This is because we define child_iterator as Stmt**. All accessor methods to subexpressions will need to be altered to reflect this new implementation. This patch includes the typedefs for child_iterator, as well the implementation for child_begin/child_end for the primary expressions and some postfix expressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41363 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Expr.cpp b/AST/Expr.cpp index 8701b9bb06..ce5a8ce262 100644 --- a/AST/Expr.cpp +++ b/AST/Expr.cpp @@ -78,10 +78,11 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) { CallExpr::CallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc) - : Expr(CallExprClass, t), Fn(fn), NumArgs(numargs) { - Args = new Expr*[numargs]; + : Expr(CallExprClass, t), NumArgs(numargs) { + SubExprs = new Expr*[numargs+1]; + SubExprs[FN] = fn; for (unsigned i = 0; i != numargs; ++i) - Args[i] = args[i]; + SubExprs[i+ARGS_START] = args[i]; RParenLoc = rparenloc; } @@ -711,3 +712,75 @@ unsigned OCUVectorElementExpr::getEncodedElementAccess() const { return Result; } +//===----------------------------------------------------------------------===// +// Child Iterators for iterating over subexpressions/substatements +//===----------------------------------------------------------------------===// + +// DeclRefExpr +Stmt::child_iterator DeclRefExpr::child_begin() { return NULL; } +Stmt::child_iterator DeclRefExpr::child_end() { return NULL; } + +// PreDefinedExpr +Stmt::child_iterator PreDefinedExpr::child_begin() { return NULL; } +Stmt::child_iterator PreDefinedExpr::child_end() { return NULL; } + +// IntegerLiteral +Stmt::child_iterator IntegerLiteral::child_begin() { return NULL; } +Stmt::child_iterator IntegerLiteral::child_end() { return NULL; } + +// CharacterLiteral +Stmt::child_iterator CharacterLiteral::child_begin() { return NULL; } +Stmt::child_iterator CharacterLiteral::child_end() { return NULL; } + +// FloatingLiteral +Stmt::child_iterator FloatingLiteral::child_begin() { return NULL; } +Stmt::child_iterator FloatingLiteral::child_end() { return NULL; } + +// StringLiteral +Stmt::child_iterator StringLiteral::child_begin() { return NULL; } +Stmt::child_iterator StringLiteral::child_end() { return NULL; } + +// ParenExpr +Stmt::child_iterator ParenExpr::child_begin() { + return reinterpret_cast(&Val); +} + +Stmt::child_iterator ParenExpr::child_end() { + return child_begin()+1; +} + +// UnaryOperator +Stmt::child_iterator UnaryOperator::child_begin() { + return reinterpret_cast(&Val); +} + +Stmt::child_iterator UnaryOperator::child_end() { + return child_begin()+1; +} + +// SizeOfAlignOfTypeExpr +Stmt::child_iterator SizeOfAlignOfTypeExpr::child_begin() { + return NULL; +} + +Stmt::child_iterator SizeOfAlignOfTypeExpr::child_end() { + return NULL; +} + +// ArraySubscriptExpr +Stmt::child_iterator ArraySubscriptExpr::child_begin() { + return reinterpret_cast(&SubExprs); +} + +Stmt::child_iterator ArraySubscriptExpr::child_end() { + return child_begin()+END_EXPR; +} + +// CallExpr +Stmt::child_iterator CallExpr::child_begin() { + return reinterpret_cast(&SubExprs); +} + +Stmt::child_iterator CallExpr::child_end() { + return child_begin()+NumArgs+ARGS_START; +} diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 4136a9eb1d..dca86e6e9f 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -36,7 +36,7 @@ protected: public: QualType getType() const { return TR; } void setType(QualType t) { TR = t; } - + /// SourceLocation tokens are not useful in isolation - they are low level /// value objects created/interpreted by SourceManager. We assume AST /// clients will have a pointer to the respective SourceManager. @@ -132,6 +132,10 @@ public: return T->getStmtClass() == DeclRefExprClass; } static bool classof(const DeclRefExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; /// PreDefinedExpr - [C99 6.4.2.2] - A pre-defined identifier such as __func__. @@ -157,7 +161,11 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == PreDefinedExprClass; } - static bool classof(const PreDefinedExpr *) { return true; } + static bool classof(const PreDefinedExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; class IntegerLiteral : public Expr { @@ -177,6 +185,10 @@ public: return T->getStmtClass() == IntegerLiteralClass; } static bool classof(const IntegerLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; class CharacterLiteral : public Expr { @@ -197,6 +209,10 @@ public: return T->getStmtClass() == CharacterLiteralClass; } static bool classof(const CharacterLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; class FloatingLiteral : public Expr { @@ -214,6 +230,10 @@ public: return T->getStmtClass() == FloatingLiteralClass; } static bool classof(const FloatingLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; /// StringLiteral - This represents a string literal expression, e.g. "foo" @@ -244,6 +264,10 @@ public: return T->getStmtClass() == StringLiteralClass; } static bool classof(const StringLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; /// ParenExpr - This represents a parethesized expression, e.g. "(1)". This @@ -263,6 +287,10 @@ public: return T->getStmtClass() == ParenExprClass; } static bool classof(const ParenExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; @@ -326,6 +354,10 @@ public: return T->getStmtClass() == UnaryOperatorClass; } static bool classof(const UnaryOperator *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; /// SizeOfAlignOfTypeExpr - [C99 6.5.3.4] - This is only for sizeof/alignof of @@ -350,6 +382,10 @@ public: return T->getStmtClass() == SizeOfAlignOfTypeExprClass; } static bool classof(const SizeOfAlignOfTypeExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; //===----------------------------------------------------------------------===// @@ -358,38 +394,49 @@ public: /// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. class ArraySubscriptExpr : public Expr { - Expr *LHS, *RHS; + enum { LHS, RHS, END_EXPR=2 }; + Expr* SubExprs[END_EXPR]; SourceLocation RBracketLoc; public: ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, SourceLocation rbracketloc) : Expr(ArraySubscriptExprClass, t), - LHS(lhs), RHS(rhs), RBracketLoc(rbracketloc) {} + RBracketLoc(rbracketloc) { + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + } /// An array access can be written A[4] or 4[A] (both are equivalent). /// - getBase() and getIdx() always present the normalized view: A[4]. /// In this case getBase() returns "A" and getIdx() returns "4". /// - getLHS() and getRHS() present the syntactic view. e.g. for /// 4[A] getLHS() returns "4". + + Expr *getLHS() { return SubExprs[LHS]; } + const Expr *getLHS() const { return SubExprs[LHS]; } - Expr *getBase() { return (LHS->getType()->isIntegerType()) ? RHS : LHS; } + Expr *getRHS() { return SubExprs[RHS]; } + const Expr *getRHS() const { return SubExprs[RHS]; } + + Expr *getBase() { + return (getLHS()->getType()->isIntegerType()) ? getRHS() : getLHS(); + } + const Expr *getBase() const { - return (LHS->getType()->isIntegerType()) ? RHS : LHS; + return (getLHS()->getType()->isIntegerType()) ? getRHS() : getLHS(); } - Expr *getIdx() { return (LHS->getType()->isIntegerType()) ? LHS : RHS; } - const Expr *getIdx() const { - return (LHS->getType()->isIntegerType()) ? LHS : RHS; + Expr *getIdx() { + return (getLHS()->getType()->isIntegerType()) ? getLHS() : getRHS(); } - Expr *getLHS() { return LHS; } - const Expr *getLHS() const { return LHS; } - - Expr *getRHS() { return RHS; } - const Expr *getRHS() const { return RHS; } + const Expr *getIdx() const { + return (getLHS()->getType()->isIntegerType()) ? getLHS() : getRHS(); + } + SourceRange getSourceRange() const { - return SourceRange(LHS->getLocStart(), RBracketLoc); + return SourceRange(getLHS()->getLocStart(), RBracketLoc); } virtual SourceLocation getExprLoc() const { return RBracketLoc; } @@ -397,25 +444,29 @@ public: return T->getStmtClass() == ArraySubscriptExprClass; } static bool classof(const ArraySubscriptExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; /// CallExpr - [C99 6.5.2.2] Function Calls. /// class CallExpr : public Expr { - Expr *Fn; - Expr **Args; + enum { FN=0, ARGS_START=1 }; + Expr **SubExprs; unsigned NumArgs; SourceLocation RParenLoc; public: CallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc); ~CallExpr() { - delete [] Args; + delete [] SubExprs; } - const Expr *getCallee() const { return Fn; } - Expr *getCallee() { return Fn; } + const Expr *getCallee() const { return SubExprs[FN]; } + Expr *getCallee() { return SubExprs[FN]; } /// getNumArgs - Return the number of actual arguments to this call. /// @@ -424,11 +475,11 @@ public: /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); - return Args[Arg]; + return SubExprs[Arg+ARGS_START]; } const Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return Args[Arg]; + return SubExprs[Arg+ARGS_START]; } /// getNumCommas - Return the number of commas that must have been present in @@ -438,13 +489,17 @@ public: bool isBuiltinClassifyType(llvm::APSInt &Result) const; SourceRange getSourceRange() const { - return SourceRange(Fn->getLocStart(), RParenLoc); + return SourceRange(getCallee()->getLocStart(), RParenLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == CallExprClass; } static bool classof(const CallExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); }; /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index bfae638133..718c98563e 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -16,6 +16,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator" #include namespace clang { @@ -67,6 +68,49 @@ public: // Implement isa support. static bool classof(const Stmt *) { return true; } + + + /// Child Iterators: All subclasses must implement child_begin and child_end + /// to permit easy iteration over the substatements/subexpessions of an + /// AST node. This permits easy iteration over all nodes in the AST. + typedef Stmt** child_iterator; + typedef Stmt* const * const_child_iterator; + + typedef std::reverse_iterator + reverse_child_iterator; + typedef std::reverse_iterator + const_reverse_child_iterator; + + // FIXME: Still implementing the the child_begin and child_end functions + // for all subclasses. +#if 0 + virtual child_iterator child_begin() = 0; + virtual child_iterator child_end() = 0; + + const_child_iterator child_begin() const { + return (child_iterator) const_cast(this)->child_begin(); + } + + const_child_iterator child_end() const { + return (child_iterator) const_cast(this)->child_end(); + } + + reverse_child_iterator child_rbegin() { + return reverse_child_iterator(child_end()); + } + + reverse_child_iterator child_rend() { + return reverse_child_iterator(child_begin()); + } + + const_reverse_child_iterator child_rbegin() const { + return const_reverse_child_iterator(child_end()); + } + + const_reverse_child_iterator child_rend() const { + return const_reverse_child_iterator(child_begin()); + } +#endif }; /// DeclStmt - Adaptor class for mixing declarations with statements and