//===--- Stmt.h - Classes for representing statements -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the Stmt interface and subclasses. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_STMT_H #define LLVM_CLANG_AST_STMT_H #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" #include "clang/Basic/SourceLocation.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtIterator.h" #include "clang/AST/DeclGroup.h" #include "llvm/ADT/SmallVector.h" #include "clang/AST/ASTContext.h" #include using llvm::dyn_cast_or_null; namespace llvm { class FoldingSetNodeID; } namespace clang { class ASTContext; class Expr; class Decl; class ParmVarDecl; class QualType; class IdentifierInfo; class SourceManager; class StringLiteral; class SwitchStmt; //===----------------------------------------------------------------------===// // ExprIterator - Iterators for iterating over Stmt* arrays that contain // only Expr*. This is needed because AST nodes use Stmt* arrays to store // references to children (to be compatible with StmtIterator). //===----------------------------------------------------------------------===// class Stmt; class Expr; class ExprIterator { Stmt** I; public: ExprIterator(Stmt** i) : I(i) {} ExprIterator() : I(0) {} ExprIterator& operator++() { ++I; return *this; } ExprIterator operator-(size_t i) { return I-i; } ExprIterator operator+(size_t i) { return I+i; } Expr* operator[](size_t idx); // FIXME: Verify that this will correctly return a signed distance. signed operator-(const ExprIterator& R) const { return I - R.I; } Expr* operator*() const; Expr* operator->() const; bool operator==(const ExprIterator& R) const { return I == R.I; } bool operator!=(const ExprIterator& R) const { return I != R.I; } bool operator>(const ExprIterator& R) const { return I > R.I; } bool operator>=(const ExprIterator& R) const { return I >= R.I; } }; class ConstExprIterator { Stmt* const * I; public: ConstExprIterator(Stmt* const* i) : I(i) {} ConstExprIterator() : I(0) {} ConstExprIterator& operator++() { ++I; return *this; } ConstExprIterator operator+(size_t i) { return I+i; } ConstExprIterator operator-(size_t i) { return I-i; } const Expr * operator[](size_t idx) const; signed operator-(const ConstExprIterator& R) const { return I - R.I; } const Expr * operator*() const; const Expr * operator->() const; bool operator==(const ConstExprIterator& R) const { return I == R.I; } bool operator!=(const ConstExprIterator& R) const { return I != R.I; } bool operator>(const ConstExprIterator& R) const { return I > R.I; } bool operator>=(const ConstExprIterator& R) const { return I >= R.I; } }; //===----------------------------------------------------------------------===// // AST classes for statements. //===----------------------------------------------------------------------===// /// Stmt - This represents one statement. /// class Stmt { public: enum StmtClass { NoStmtClass = 0, #define STMT(CLASS, PARENT) CLASS##Class, #define FIRST_STMT(CLASS) firstStmtConstant = CLASS##Class, #define LAST_STMT(CLASS) lastStmtConstant = CLASS##Class, #define FIRST_EXPR(CLASS) firstExprConstant = CLASS##Class, #define LAST_EXPR(CLASS) lastExprConstant = CLASS##Class #include "clang/AST/StmtNodes.def" }; private: /// \brief The statement class. const unsigned sClass : 8; /// \brief The reference count for this statement. unsigned RefCount : 24; // Make vanilla 'new' and 'delete' illegal for Stmts. protected: void* operator new(size_t bytes) throw() { assert(0 && "Stmts cannot be allocated with regular 'new'."); return 0; } void operator delete(void* data) throw() { assert(0 && "Stmts cannot be released with regular 'delete'."); } public: // Only allow allocation of Stmts using the allocator in ASTContext // or by doing a placement new. void* operator new(size_t bytes, ASTContext& C, unsigned alignment = 16) throw() { return ::operator new(bytes, C, alignment); } void* operator new(size_t bytes, ASTContext* C, unsigned alignment = 16) throw() { return ::operator new(bytes, *C, alignment); } void* operator new(size_t bytes, void* mem) throw() { return mem; } void operator delete(void*, ASTContext&, unsigned) throw() { } void operator delete(void*, ASTContext*, unsigned) throw() { } void operator delete(void*, std::size_t) throw() { } void operator delete(void*, void*) throw() { } public: /// \brief A placeholder type used to construct an empty shell of a /// type, that will be filled in later (e.g., by some /// de-serialization). struct EmptyShell { }; protected: /// DestroyChildren - Invoked by destructors of subclasses of Stmt to /// recursively release child AST nodes. void DestroyChildren(ASTContext& Ctx); /// \brief Construct an empty statement. explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) { if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); } /// \brief Virtual method that performs the actual destruction of /// this statement. /// /// Subclasses should override this method (not Destroy()) to /// provide class-specific destruction. virtual void DoDestroy(ASTContext &Ctx); public: Stmt(StmtClass SC) : sClass(SC), RefCount(1) { if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); } virtual ~Stmt() {} #ifndef NDEBUG /// \brief True if this statement's refcount is in a valid state. /// Should be used only in assertions. bool isRetained() const { return (RefCount >= 1); } #endif /// \brief Destroy the current statement and its children. void Destroy(ASTContext &Ctx) { assert(RefCount >= 1); if (--RefCount == 0) DoDestroy(Ctx); } /// \brief Increases the reference count for this statement. /// /// Invoke the Retain() operation when this statement or expression /// is being shared by another owner. Stmt *Retain() { assert(RefCount >= 1); ++RefCount; return this; } StmtClass getStmtClass() const { assert(RefCount >= 1 && "Referencing already-destroyed statement!"); return (StmtClass)sClass; } const char *getStmtClassName() const; /// 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. virtual SourceRange getSourceRange() const = 0; SourceLocation getLocStart() const { return getSourceRange().getBegin(); } SourceLocation getLocEnd() const { return getSourceRange().getEnd(); } // global temp stats (until we have a per-module visitor) static void addStmtClass(const StmtClass s); static bool CollectingStats(bool Enable = false); static void PrintStats(); /// dump - This does a local dump of the specified AST fragment. It dumps the /// specified node and a few nodes underneath it, but not the whole subtree. /// This is useful in a debugger. void dump() const; void dump(SourceManager &SM) const; /// dumpAll - This does a dump of the specified AST fragment and all subtrees. void dumpAll() const; void dumpAll(SourceManager &SM) const; /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST /// back to its original source language syntax. void dumpPretty(ASTContext& Context) const; void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation = 0) const { printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation); } void printPretty(llvm::raw_ostream &OS, ASTContext &Context, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation = 0) const; /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only /// works on systems with GraphViz (Mac OS X) or dot+gv installed. void viewAST() const; // Implement isa support. static bool classof(const Stmt *) { return true; } /// hasImplicitControlFlow - Some statements (e.g. short circuited operations) /// contain implicit control-flow in the order their subexpressions /// are evaluated. This predicate returns true if this statement has /// such implicit control-flow. Such statements are also specially handled /// within CFGs. bool hasImplicitControlFlow() const; /// 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 StmtIterator child_iterator; typedef ConstStmtIterator const_child_iterator; virtual child_iterator child_begin() = 0; virtual child_iterator child_end() = 0; const_child_iterator child_begin() const { return const_child_iterator(const_cast(this)->child_begin()); } const_child_iterator child_end() const { return const_child_iterator(const_cast(this)->child_end()); } /// \brief Produce a unique representation of the given statement. /// /// \brief ID once the profiling operation is complete, will contain /// the unique representation of the given statement. /// /// \brief Context the AST context in which the statement resides /// /// \brief Canonical whether the profile should be based on the canonical /// representation of this statement (e.g., where non-type template /// parameters are identified by index/level rather than their /// declaration pointers) or the exact representation of the statement as /// written in the source. void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, bool Canonical); }; /// DeclStmt - Adaptor class for mixing declarations with statements and /// expressions. For example, CompoundStmt mixes statements, expressions /// and declarations (variables, types). Another example is ForStmt, where /// the first statement can be an expression or a declaration. /// class DeclStmt : public Stmt { DeclGroupRef DG; SourceLocation StartLoc, EndLoc; public: DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), StartLoc(startLoc), EndLoc(endLoc) {} /// \brief Build an empty declaration statement. explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { } /// isSingleDecl - This method returns true if this DeclStmt refers /// to a single Decl. bool isSingleDecl() const { return DG.isSingleDecl(); } const Decl *getSingleDecl() const { return DG.getSingleDecl(); } Decl *getSingleDecl() { return DG.getSingleDecl(); } const DeclGroupRef getDeclGroup() const { return DG; } DeclGroupRef getDeclGroup() { return DG; } void setDeclGroup(DeclGroupRef DGR) { DG = DGR; } SourceLocation getStartLoc() const { return StartLoc; } void setStartLoc(SourceLocation L) { StartLoc = L; } SourceLocation getEndLoc() const { return EndLoc; } void setEndLoc(SourceLocation L) { EndLoc = L; } SourceRange getSourceRange() const { return SourceRange(StartLoc, EndLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == DeclStmtClass; } static bool classof(const DeclStmt *) { return true; } // Iterators over subexpressions. virtual child_iterator child_begin(); virtual child_iterator child_end(); typedef DeclGroupRef::iterator decl_iterator; typedef DeclGroupRef::const_iterator const_decl_iterator; decl_iterator decl_begin() { return DG.begin(); } decl_iterator decl_end() { return DG.end(); } const_decl_iterator decl_begin() const { return DG.begin(); } const_decl_iterator decl_end() const { return DG.end(); } }; /// NullStmt - This is the null statement ";": C99 6.8.3p3. /// class NullStmt : public Stmt { SourceLocation SemiLoc; public: NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {} /// \brief Build an empty null statement. explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { } SourceLocation getSemiLoc() const { return SemiLoc; } void setSemiLoc(SourceLocation L) { SemiLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == NullStmtClass; } static bool classof(const NullStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// CompoundStmt - This represents a group of statements like { stmt stmt }. /// class CompoundStmt : public Stmt { Stmt** Body; unsigned NumStmts; SourceLocation LBracLoc, RBracLoc; public: CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts, SourceLocation LB, SourceLocation RB) : Stmt(CompoundStmtClass), NumStmts(numStmts), LBracLoc(LB), RBracLoc(RB) { if (NumStmts == 0) { Body = 0; return; } Body = new (C) Stmt*[NumStmts]; memcpy(Body, StmtStart, numStmts * sizeof(*Body)); } // \brief Build an empty compound statement. explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { } void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts); bool body_empty() const { return NumStmts == 0; } unsigned size() const { return NumStmts; } typedef Stmt** body_iterator; body_iterator body_begin() { return Body; } body_iterator body_end() { return Body + NumStmts; } Stmt *body_back() { return NumStmts ? Body[NumStmts-1] : 0; } typedef Stmt* const * const_body_iterator; const_body_iterator body_begin() const { return Body; } const_body_iterator body_end() const { return Body + NumStmts; } const Stmt *body_back() const { return NumStmts ? Body[NumStmts-1] : 0; } typedef std::reverse_iterator reverse_body_iterator; reverse_body_iterator body_rbegin() { return reverse_body_iterator(body_end()); } reverse_body_iterator body_rend() { return reverse_body_iterator(body_begin()); } typedef std::reverse_iterator const_reverse_body_iterator; const_reverse_body_iterator body_rbegin() const { return const_reverse_body_iterator(body_end()); } const_reverse_body_iterator body_rend() const { return const_reverse_body_iterator(body_begin()); } virtual SourceRange getSourceRange() const { return SourceRange(LBracLoc, RBracLoc); } SourceLocation getLBracLoc() const { return LBracLoc; } void setLBracLoc(SourceLocation L) { LBracLoc = L; } SourceLocation getRBracLoc() const { return RBracLoc; } void setRBracLoc(SourceLocation L) { RBracLoc = L; } static bool classof(const Stmt *T) { return T->getStmtClass() == CompoundStmtClass; } static bool classof(const CompoundStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; // SwitchCase is the base class for CaseStmt and DefaultStmt, class SwitchCase : public Stmt { protected: // A pointer to the following CaseStmt or DefaultStmt class, // used by SwitchStmt. SwitchCase *NextSwitchCase; SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {} public: const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } SwitchCase *getNextSwitchCase() { return NextSwitchCase; } void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } Stmt *getSubStmt() { return v_getSubStmt(); } virtual SourceRange getSourceRange() const { return SourceRange(); } static bool classof(const Stmt *T) { return T->getStmtClass() == CaseStmtClass || T->getStmtClass() == DefaultStmtClass; } static bool classof(const SwitchCase *) { return true; } protected: virtual Stmt* v_getSubStmt() = 0; }; class CaseStmt : public SwitchCase { enum { SUBSTMT, LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for // GNU "case 1 ... 4" extension SourceLocation CaseLoc; SourceLocation EllipsisLoc; SourceLocation ColonLoc; virtual Stmt* v_getSubStmt() { return getSubStmt(); } public: CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, SourceLocation ellipsisLoc, SourceLocation colonLoc) : SwitchCase(CaseStmtClass) { SubExprs[SUBSTMT] = 0; SubExprs[LHS] = reinterpret_cast(lhs); SubExprs[RHS] = reinterpret_cast(rhs); CaseLoc = caseLoc; EllipsisLoc = ellipsisLoc; ColonLoc = colonLoc; } /// \brief Build an empty switch case statement. explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass) { } SourceLocation getCaseLoc() const { return CaseLoc; } void setCaseLoc(SourceLocation L) { CaseLoc = L; } SourceLocation getEllipsisLoc() const { return EllipsisLoc; } void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; } SourceLocation getColonLoc() const { return ColonLoc; } void setColonLoc(SourceLocation L) { ColonLoc = L; } Expr *getLHS() { return reinterpret_cast(SubExprs[LHS]); } Expr *getRHS() { return reinterpret_cast(SubExprs[RHS]); } Stmt *getSubStmt() { return SubExprs[SUBSTMT]; } const Expr *getLHS() const { return reinterpret_cast(SubExprs[LHS]); } const Expr *getRHS() const { return reinterpret_cast(SubExprs[RHS]); } const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; } void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; } void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast(Val); } void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast(Val); } virtual SourceRange getSourceRange() const { // Handle deeply nested case statements with iteration instead of recursion. const CaseStmt *CS = this; while (const CaseStmt *CS2 = dyn_cast(CS->getSubStmt())) CS = CS2; return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd()); } static bool classof(const Stmt *T) { return T->getStmtClass() == CaseStmtClass; } static bool classof(const CaseStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; class DefaultStmt : public SwitchCase { Stmt* SubStmt; SourceLocation DefaultLoc; SourceLocation ColonLoc; virtual Stmt* v_getSubStmt() { return getSubStmt(); } public: DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL), ColonLoc(CL) {} /// \brief Build an empty default statement. explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { } Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } void setSubStmt(Stmt *S) { SubStmt = S; } SourceLocation getDefaultLoc() const { return DefaultLoc; } void setDefaultLoc(SourceLocation L) { DefaultLoc = L; } SourceLocation getColonLoc() const { return ColonLoc; } void setColonLoc(SourceLocation L) { ColonLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(DefaultLoc, SubStmt->getLocEnd()); } static bool classof(const Stmt *T) { return T->getStmtClass() == DefaultStmtClass; } static bool classof(const DefaultStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; class LabelStmt : public Stmt { IdentifierInfo *Label; Stmt *SubStmt; SourceLocation IdentLoc; public: LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt) : Stmt(LabelStmtClass), Label(label), SubStmt(substmt), IdentLoc(IL) {} // \brief Build an empty label statement. explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { } SourceLocation getIdentLoc() const { return IdentLoc; } IdentifierInfo *getID() const { return Label; } void setID(IdentifierInfo *II) { Label = II; } const char *getName() const; Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } void setIdentLoc(SourceLocation L) { IdentLoc = L; } void setSubStmt(Stmt *SS) { SubStmt = SS; } virtual SourceRange getSourceRange() const { return SourceRange(IdentLoc, SubStmt->getLocEnd()); } static bool classof(const Stmt *T) { return T->getStmtClass() == LabelStmtClass; } static bool classof(const LabelStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// IfStmt - This represents an if/then/else. /// class IfStmt : public Stmt { enum { COND, THEN, ELSE, END_EXPR }; Stmt* SubExprs[END_EXPR]; /// \brief If non-NULL, the declaration in the "if" statement. VarDecl *Var; SourceLocation IfLoc; SourceLocation ElseLoc; public: IfStmt(SourceLocation IL, VarDecl *Var, Expr *cond, Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0) : Stmt(IfStmtClass), Var(Var), IfLoc(IL), ElseLoc(EL) { SubExprs[COND] = reinterpret_cast(cond); SubExprs[THEN] = then; SubExprs[ELSE] = elsev; } /// \brief Build an empty if/then/else statement explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } /// \brief Retrieve the variable declared in this "if" statement, if any. /// /// In the following example, "x" is the condition variable. /// \code /// if (int x = foo()) { /// printf("x is %d", x); /// } /// \endcode VarDecl *getConditionVariable() const { return Var; } void setConditionVariable(VarDecl *V) { Var = V; } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } const Stmt *getThen() const { return SubExprs[THEN]; } void setThen(Stmt *S) { SubExprs[THEN] = S; } const Stmt *getElse() const { return SubExprs[ELSE]; } void setElse(Stmt *S) { SubExprs[ELSE] = S; } Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } Stmt *getThen() { return SubExprs[THEN]; } Stmt *getElse() { return SubExprs[ELSE]; } SourceLocation getIfLoc() const { return IfLoc; } void setIfLoc(SourceLocation L) { IfLoc = L; } SourceLocation getElseLoc() const { return ElseLoc; } void setElseLoc(SourceLocation L) { ElseLoc = L; } virtual SourceRange getSourceRange() const { if (SubExprs[ELSE]) return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd()); else return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd()); } static bool classof(const Stmt *T) { return T->getStmtClass() == IfStmtClass; } static bool classof(const IfStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// SwitchStmt - This represents a 'switch' stmt. /// class SwitchStmt : public Stmt { enum { COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; VarDecl *Var; // This points to a linked list of case and default statements. SwitchCase *FirstCase; SourceLocation SwitchLoc; protected: virtual void DoDestroy(ASTContext &Ctx); public: SwitchStmt(VarDecl *Var, Expr *cond) : Stmt(SwitchStmtClass), Var(Var), FirstCase(0) { SubExprs[COND] = reinterpret_cast(cond); SubExprs[BODY] = NULL; } /// \brief Build a empty switch statement. explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } /// \brief Retrieve the variable declared in this "switch" statement, if any. /// /// In the following example, "x" is the condition variable. /// \code /// switch (int x = foo()) { /// case 0: break; /// // ... /// } /// \endcode VarDecl *getConditionVariable() const { return Var; } void setConditionVariable(VarDecl *V) { Var = V; } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} const Stmt *getBody() const { return SubExprs[BODY]; } const SwitchCase *getSwitchCaseList() const { return FirstCase; } Expr *getCond() { return reinterpret_cast(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } Stmt *getBody() { return SubExprs[BODY]; } void setBody(Stmt *S) { SubExprs[BODY] = S; } SwitchCase *getSwitchCaseList() { return FirstCase; } /// \brief Set the case list for this switch statement. /// /// The caller is responsible for incrementing the retain counts on /// all of the SwitchCase statements in this list. void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; } SourceLocation getSwitchLoc() const { return SwitchLoc; } void setSwitchLoc(SourceLocation L) { SwitchLoc = L; } void setBody(Stmt *S, SourceLocation SL) { SubExprs[BODY] = S; SwitchLoc = SL; } void addSwitchCase(SwitchCase *SC) { assert(!SC->getNextSwitchCase() && "case/default already added to a switch"); SC->Retain(); SC->setNextSwitchCase(FirstCase); FirstCase = SC; } virtual SourceRange getSourceRange() const { return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { return T->getStmtClass() == SwitchStmtClass; } static bool classof(const SwitchStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// WhileStmt - This represents a 'while' stmt. /// class WhileStmt : public Stmt { enum { COND, BODY, END_EXPR }; VarDecl *Var; Stmt* SubExprs[END_EXPR]; SourceLocation WhileLoc; public: WhileStmt(VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL) : Stmt(WhileStmtClass), Var(Var) { SubExprs[COND] = reinterpret_cast(cond); SubExprs[BODY] = body; WhileLoc = WL; } /// \brief Build an empty while statement. explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { } /// \brief Retrieve the variable declared in this "while" statement, if any. /// /// In the following example, "x" is the condition variable. /// \code /// while (int x = random()) { /// // ... /// } /// \endcode VarDecl *getConditionVariable() const { return Var; } void setConditionVariable(VarDecl *V) { Var = V; } Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } Stmt *getBody() { return SubExprs[BODY]; } const Stmt *getBody() const { return SubExprs[BODY]; } void setBody(Stmt *S) { SubExprs[BODY] = S; } SourceLocation getWhileLoc() const { return WhileLoc; } void setWhileLoc(SourceLocation L) { WhileLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { return T->getStmtClass() == WhileStmtClass; } static bool classof(const WhileStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// DoStmt - This represents a 'do/while' stmt. /// class DoStmt : public Stmt { enum { COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; SourceLocation DoLoc; SourceLocation WhileLoc; SourceLocation RParenLoc; // Location of final ')' in do stmt condition. public: DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL, SourceLocation RP) : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) { SubExprs[COND] = reinterpret_cast(cond); SubExprs[BODY] = body; } /// \brief Build an empty do-while statement. explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { } Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } Stmt *getBody() { return SubExprs[BODY]; } const Stmt *getBody() const { return SubExprs[BODY]; } void setBody(Stmt *S) { SubExprs[BODY] = S; } SourceLocation getDoLoc() const { return DoLoc; } void setDoLoc(SourceLocation L) { DoLoc = L; } SourceLocation getWhileLoc() const { return WhileLoc; } void setWhileLoc(SourceLocation L) { WhileLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(DoLoc, RParenLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == DoStmtClass; } static bool classof(const DoStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of /// the init/cond/inc parts of the ForStmt will be null if they were not /// specified in the source. /// class ForStmt : public Stmt { enum { INIT, COND, INC, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt. VarDecl *CondVar; SourceLocation ForLoc; SourceLocation LParenLoc, RParenLoc; public: ForStmt(Stmt *Init, Expr *Cond, VarDecl *CondVar, Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP) : Stmt(ForStmtClass), CondVar(CondVar), ForLoc(FL), LParenLoc(LP), RParenLoc(RP) { SubExprs[INIT] = Init; SubExprs[COND] = reinterpret_cast(Cond); SubExprs[INC] = reinterpret_cast(Inc); SubExprs[BODY] = Body; } /// \brief Build an empty for statement. explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } Stmt *getInit() { return SubExprs[INIT]; } /// \brief Retrieve the variable declared in this "for" statement, if any. /// /// In the following example, "y" is the condition variable. /// \code /// for (int x = random(); int y = mangle(x); ++x) { /// // ... /// } /// \endcode VarDecl *getConditionVariable() const { return CondVar; } void setConditionVariable(VarDecl *V) { CondVar = V; } Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } Stmt *getBody() { return SubExprs[BODY]; } const Stmt *getInit() const { return SubExprs[INIT]; } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} const Expr *getInc() const { return reinterpret_cast(SubExprs[INC]); } const Stmt *getBody() const { return SubExprs[BODY]; } void setInit(Stmt *S) { SubExprs[INIT] = S; } void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast(E); } void setBody(Stmt *S) { SubExprs[BODY] = S; } SourceLocation getForLoc() const { return ForLoc; } void setForLoc(SourceLocation L) { ForLoc = L; } SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { return T->getStmtClass() == ForStmtClass; } static bool classof(const ForStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// GotoStmt - This represents a direct goto. /// class GotoStmt : public Stmt { LabelStmt *Label; SourceLocation GotoLoc; SourceLocation LabelLoc; public: GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL) : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {} /// \brief Build an empty goto statement. explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { } LabelStmt *getLabel() const { return Label; } void setLabel(LabelStmt *S) { Label = S; } SourceLocation getGotoLoc() const { return GotoLoc; } void setGotoLoc(SourceLocation L) { GotoLoc = L; } SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(GotoLoc, LabelLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == GotoStmtClass; } static bool classof(const GotoStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// IndirectGotoStmt - This represents an indirect goto. /// class IndirectGotoStmt : public Stmt { SourceLocation GotoLoc; SourceLocation StarLoc; Stmt *Target; public: IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc, Expr *target) : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc), Target((Stmt*)target) {} /// \brief Build an empty indirect goto statement. explicit IndirectGotoStmt(EmptyShell Empty) : Stmt(IndirectGotoStmtClass, Empty) { } void setGotoLoc(SourceLocation L) { GotoLoc = L; } SourceLocation getGotoLoc() const { return GotoLoc; } void setStarLoc(SourceLocation L) { StarLoc = L; } SourceLocation getStarLoc() const { return StarLoc; } Expr *getTarget(); const Expr *getTarget() const; void setTarget(Expr *E) { Target = reinterpret_cast(E); } virtual SourceRange getSourceRange() const { return SourceRange(GotoLoc, Target->getLocEnd()); } static bool classof(const Stmt *T) { return T->getStmtClass() == IndirectGotoStmtClass; } static bool classof(const IndirectGotoStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ContinueStmt - This represents a continue. /// class ContinueStmt : public Stmt { SourceLocation ContinueLoc; public: ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {} /// \brief Build an empty continue statement. explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { } SourceLocation getContinueLoc() const { return ContinueLoc; } void setContinueLoc(SourceLocation L) { ContinueLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(ContinueLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == ContinueStmtClass; } static bool classof(const ContinueStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// BreakStmt - This represents a break. /// class BreakStmt : public Stmt { SourceLocation BreakLoc; public: BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {} /// \brief Build an empty break statement. explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { } SourceLocation getBreakLoc() const { return BreakLoc; } void setBreakLoc(SourceLocation L) { BreakLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == BreakStmtClass; } static bool classof(const BreakStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ReturnStmt - This represents a return, optionally of an expression: /// return; /// return 4; /// /// Note that GCC allows return with no argument in a function declared to /// return a value, and it allows returning a value in functions declared to /// return void. We explicitly model this in the AST, which means you can't /// depend on the return type of the function and the presence of an argument. /// class ReturnStmt : public Stmt { Stmt *RetExpr; SourceLocation RetLoc; public: ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL) {} /// \brief Build an empty return expression. explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { } const Expr *getRetValue() const; Expr *getRetValue(); void setRetValue(Expr *E) { RetExpr = reinterpret_cast(E); } SourceLocation getReturnLoc() const { return RetLoc; } void setReturnLoc(SourceLocation L) { RetLoc = L; } virtual SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() == ReturnStmtClass; } static bool classof(const ReturnStmt *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// AsmStmt - This represents a GNU inline-assembly statement extension. /// class AsmStmt : public Stmt { SourceLocation AsmLoc, RParenLoc; StringLiteral *AsmStr; bool IsSimple; bool IsVolatile; unsigned NumOutputs; unsigned NumInputs; llvm::SmallVector Names; llvm::SmallVector Constraints; llvm::SmallVector Exprs; llvm::SmallVector Clobbers; public: AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile, unsigned numoutputs, unsigned numinputs, std::string *names, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, StringLiteral **clobbers, SourceLocation rparenloc); /// \brief Build an empty inline-assembly statement. explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty) { } SourceLocation getAsmLoc() const { return AsmLoc; } void setAsmLoc(SourceLocation L) { AsmLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } bool isVolatile() const { return IsVolatile; } void setVolatile(bool V) { IsVolatile = V; } bool isSimple() const { return IsSimple; } void setSimple(bool V) { IsSimple = false; } //===--- Asm String Analysis ---===// const StringLiteral *getAsmString() const { return AsmStr; } StringLiteral *getAsmString() { return AsmStr; } void setAsmString(StringLiteral *E) { AsmStr = E; } /// AsmStringPiece - this is part of a decomposed asm string specification /// (for use with the AnalyzeAsmString function below). An asm string is /// considered to be a concatenation of these parts. class AsmStringPiece { public: enum Kind { String, // String in .ll asm string form, "$" -> "$$" and "%%" -> "%". Operand // Operand reference, with optional modifier %c4. }; private: Kind MyKind; std::string Str; unsigned OperandNo; public: AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {} AsmStringPiece(unsigned OpNo, char Modifier) : MyKind(Operand), Str(), OperandNo(OpNo) { Str += Modifier; } bool isString() const { return MyKind == String; } bool isOperand() const { return MyKind == Operand; } const std::string &getString() const { assert(isString()); return Str; } unsigned getOperandNo() const { assert(isOperand()); return OperandNo; } /// getModifier - Get the modifier for this operand, if present. This /// returns '\0' if there was no modifier. char getModifier() const { assert(isOperand()); return Str[0]; } }; /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing /// it into pieces. If the asm string is erroneous, emit errors and return /// true, otherwise return false. This handles canonicalization and /// translation of strings from GCC syntax to LLVM IR syntax, and handles //// flattening of named references like %[foo] to Operand AsmStringPiece's. unsigned AnalyzeAsmString(llvm::SmallVectorImpl &Pieces, ASTContext &C, unsigned &DiagOffs) const; //===--- Output operands ---===// unsigned getNumOutputs() const { return NumOutputs; } const std::string &getOutputName(unsigned i) const { return Names[i]; } /// getOutputConstraint - Return the constraint string for the specified /// output operand. All output constraints are known to be non-empty (either /// '=' or '+'). std::string getOutputConstraint(unsigned i) const; const StringLiteral *getOutputConstraintLiteral(unsigned i) const { return Constraints[i]; } StringLiteral *getOutputConstraintLiteral(unsigned i) { return Constraints[i]; } Expr *getOutputExpr(unsigned i); const Expr *getOutputExpr(unsigned i) const { return const_cast(this)->getOutputExpr(i); } /// isOutputPlusConstraint - Return true if the specified output constraint /// is a "+" constraint (which is both an input and an output) or false if it /// is an "=" constraint (just an output). bool isOutputPlusConstraint(unsigned i) const { return getOutputConstraint(i)[0] == '+'; } /// getNumPlusOperands - Return the number of output operands that have a "+" /// constraint. unsigned getNumPlusOperands() const; //===--- Input operands ---===// unsigned getNumInputs() const { return NumInputs; } const std::string &getInputName(unsigned i) const { return Names[i + NumOutputs]; } /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. std::string getInputConstraint(unsigned i) const; const StringLiteral *getInputConstraintLiteral(unsigned i) const { return Constraints[i + NumOutputs]; } StringLiteral *getInputConstraintLiteral(unsigned i) { return Constraints[i + NumOutputs]; } Expr *getInputExpr(unsigned i); const Expr *getInputExpr(unsigned i) const { return const_cast(this)->getInputExpr(i); } void setOutputsAndInputs(unsigned NumOutputs, unsigned NumInputs, const std::string *Names, StringLiteral **Constraints, Stmt **Exprs); //===--- Other ---===// /// getNamedOperand - Given a symbolic operand reference like %[foo], /// translate this into a numeric value needed to reference the same operand. /// This returns -1 if the operand name is invalid. int getNamedOperand(const std::string &SymbolicName) const; unsigned getNumClobbers() const { return Clobbers.size(); } StringLiteral *getClobber(unsigned i) { return Clobbers[i]; } const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; } void setClobbers(StringLiteral **Clobbers, unsigned NumClobbers); virtual SourceRange getSourceRange() const { return SourceRange(AsmLoc, RParenLoc); } static bool classof(const Stmt *T) {return T->getStmtClass() == AsmStmtClass;} static bool classof(const AsmStmt *) { return true; } // Input expr iterators. typedef ExprIterator inputs_iterator; typedef ConstExprIterator const_inputs_iterator; inputs_iterator begin_inputs() { return Exprs.data() + NumOutputs; } inputs_iterator end_inputs() { return Exprs.data() + NumOutputs + NumInputs; } const_inputs_iterator begin_inputs() const { return Exprs.data() + NumOutputs; } const_inputs_iterator end_inputs() const { return Exprs.data() + NumOutputs + NumInputs; } // Output expr iterators. typedef ExprIterator outputs_iterator; typedef ConstExprIterator const_outputs_iterator; outputs_iterator begin_outputs() { return Exprs.data(); } outputs_iterator end_outputs() { return Exprs.data() + NumOutputs; } const_outputs_iterator begin_outputs() const { return Exprs.data(); } const_outputs_iterator end_outputs() const { return Exprs.data() + NumOutputs; } // Input name iterator. const std::string *begin_output_names() const { return &Names[0]; } const std::string *end_output_names() const { return &Names[0] + NumOutputs; } // Child iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; } // end namespace clang #endif