diff options
author | Chris Lattner <sabre@nondot.org> | 2007-07-24 16:58:17 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-07-24 16:58:17 +0000 |
commit | 366727fca1a5863965eb16b06b39b58941fdee1d (patch) | |
tree | 0d2ac3df50c1325c56d5e80fbf1de6c363ceb9b2 | |
parent | a2e618712df2bafe1ecee1692e49b9fc9b9b6794 (diff) | |
download | bcm5719-llvm-366727fca1a5863965eb16b06b39b58941fdee1d.tar.gz bcm5719-llvm-366727fca1a5863965eb16b06b39b58941fdee1d.zip |
implement ast building and trivial semantic analysis of stmt exprs.
This implements test/Sema/stmt_exprs.c
llvm-svn: 40465
-rw-r--r-- | clang/AST/StmtPrinter.cpp | 8 | ||||
-rw-r--r-- | clang/Parse/ParseExpr.cpp | 12 | ||||
-rw-r--r-- | clang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | clang/Sema/SemaExpr.cpp | 23 | ||||
-rw-r--r-- | clang/include/clang/AST/Expr.h | 28 | ||||
-rw-r--r-- | clang/include/clang/AST/Stmt.h | 4 | ||||
-rw-r--r-- | clang/include/clang/AST/StmtNodes.def | 7 | ||||
-rw-r--r-- | clang/include/clang/Parse/Action.h | 8 | ||||
-rw-r--r-- | clang/test/Sema/stmt_exprs.c | 12 |
9 files changed, 96 insertions, 9 deletions
diff --git a/clang/AST/StmtPrinter.cpp b/clang/AST/StmtPrinter.cpp index 64e94f9048a..2c4b21eb854 100644 --- a/clang/AST/StmtPrinter.cpp +++ b/clang/AST/StmtPrinter.cpp @@ -468,9 +468,15 @@ void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) { void StmtPrinter::VisitAddrLabel(AddrLabel *Node) { OS << "&&" << Node->getLabel()->getName(); - } +void StmtPrinter::VisitStmtExpr(StmtExpr *E) { + OS << "("; + PrintRawCompoundStmt(E->getSubStmt()); + OS << ")"; +} + + // C++ void StmtPrinter::VisitCXXCastExpr(CXXCastExpr *Node) { diff --git a/clang/Parse/ParseExpr.cpp b/clang/Parse/ParseExpr.cpp index 467dc1dcf31..de0a2a2d677 100644 --- a/clang/Parse/ParseExpr.cpp +++ b/clang/Parse/ParseExpr.cpp @@ -539,7 +539,7 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) { case tok::kw___real: // unary-expression: '__real' cast-expression [GNU] case tok::kw___imag: // unary-expression: '__imag' cast-expression [GNU] case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU] - // FIXME: Extension not handled correctly here! + // FIXME: Extension should silence extwarns in subexpressions. SourceLocation SavedLoc = ConsumeToken(); Res = ParseCastExpression(false); if (!Res.isInvalid) @@ -853,15 +853,19 @@ Parser::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType, SourceLocation &RParenLoc) { assert(Tok.getKind() == tok::l_paren && "Not a paren expr!"); SourceLocation OpenLoc = ConsumeParen(); - ExprResult Result(false); + ExprResult Result(true); CastTy = 0; if (ExprType >= CompoundStmt && Tok.getKind() == tok::l_brace && !getLang().NoExtensions) { Diag(Tok, diag::ext_gnu_statement_expr); - ParseCompoundStatement(); + Parser::StmtResult Stmt = ParseCompoundStatement(); ExprType = CompoundStmt; - // TODO: Build AST for GNU compound stmt. + + // If the substmt parsed correctly, build the AST node. + if (!Stmt.isInvalid && Tok.getKind() == tok::r_paren) + Result = Actions.ParseStmtExpr(OpenLoc, Stmt.Val, Tok.getLocation()); + } else if (ExprType >= CompoundLiteral && isTypeSpecifierQualifier()) { // Otherwise, this is a compound literal expression or cast expression. TypeTy *Ty = ParseTypeName(); diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index 39a3cc08f13..e1857b7583c 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -271,6 +271,9 @@ public: virtual ExprResult ParseAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, IdentifierInfo *LabelII); + virtual ExprResult ParseStmtExpr(SourceLocation LPLoc, StmtTy *SubStmt, + SourceLocation RPLoc); // "({..})" + /// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's. virtual ExprResult ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind, SourceLocation LAngleBracketLoc, TypeTy *Ty, diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index 3bad52a4751..7e0b6412761 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/Sema/SemaExpr.cpp @@ -1476,3 +1476,26 @@ Sema::ExprResult Sema::ParseAddrLabel(SourceLocation OpLoc, Context.getPointerType(Context.VoidTy)); } +Sema::ExprResult Sema::ParseStmtExpr(SourceLocation LPLoc, StmtTy *substmt, + SourceLocation RPLoc) { // "({..})" + Stmt *SubStmt = static_cast<Stmt*>(substmt); + assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!"); + CompoundStmt *Compound = cast<CompoundStmt>(SubStmt); + + // FIXME: there are a variety of strange constraints to enforce here, for + // example, it is not possible to goto into a stmt expression apparently. + // More semantic analysis is needed. + + // FIXME: the last statement in the compount stmt has its value used. We + // should not warn about it being unused. + + // If there are sub stmts in the compound stmt, take the type of the last one + // as the type of the stmtexpr. + QualType Ty = Context.VoidTy; + + if (!Compound->body_empty()) + if (Expr *LastExpr = dyn_cast<Expr>(Compound->body_back())) + Ty = LastExpr->getType(); + + return new StmtExpr(Compound, Ty, LPLoc, RPLoc); +} diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 73dce8ede44..cf5ee87c797 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -134,7 +134,7 @@ public: static bool classof(const DeclRefExpr *) { return true; } }; -// PreDefinedExpr - [C99 6.4.2.2] - A pre-defined identifier such as __func__ +/// PreDefinedExpr - [C99 6.4.2.2] - A pre-defined identifier such as __func__. class PreDefinedExpr : public Expr { public: enum IdentType { @@ -661,7 +661,33 @@ public: } static bool classof(const AddrLabel *) { return true; } }; + +/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}). +/// The StmtExpr contains a single CompoundStmt node, which it evaluates and +/// takes the value of the last subexpression. +class StmtExpr : public Expr { + CompoundStmt *SubStmt; + SourceLocation LParenLoc, RParenLoc; +public: + StmtExpr(CompoundStmt *substmt, QualType T, + SourceLocation lp, SourceLocation rp) + : Expr(StmtExprClass, T), SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { + } + + CompoundStmt *getSubStmt() { return SubStmt; } + const CompoundStmt *getSubStmt() const { return SubStmt; } + + virtual SourceRange getSourceRange() const { + return SourceRange(LParenLoc, RParenLoc); + } + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == StmtExprClass; + } + static bool classof(const StmtExpr *) { return true; } +}; + } // end namespace clang #endif diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 4fcf7aecb82..ef6e7394476 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -107,13 +107,17 @@ public: CompoundStmt(Stmt **StmtStart, unsigned NumStmts) : Stmt(CompoundStmtClass), Body(StmtStart, StmtStart+NumStmts) {} + bool body_empty() const { return Body.empty(); } + typedef llvm::SmallVector<Stmt*, 16>::iterator body_iterator; body_iterator body_begin() { return Body.begin(); } body_iterator body_end() { return Body.end(); } + Stmt *body_back() { return Body.back(); } typedef llvm::SmallVector<Stmt*, 16>::const_iterator const_body_iterator; const_body_iterator body_begin() const { return Body.begin(); } const_body_iterator body_end() const { return Body.end(); } + const Stmt *body_back() const { return Body.back(); } void push_back(Stmt *S) { Body.push_back(S); } diff --git a/clang/include/clang/AST/StmtNodes.def b/clang/include/clang/AST/StmtNodes.def index b4c220c0e22..b99d225d2ad 100644 --- a/clang/include/clang/AST/StmtNodes.def +++ b/clang/include/clang/AST/StmtNodes.def @@ -65,11 +65,12 @@ STMT(48, CompoundLiteralExpr , Expr) // GNU Extensions. STMT(49, AddrLabel , Expr) +STMT(50, StmtExpr , Expr) // C++ Expressions. -STMT(50, CXXCastExpr , Expr) -STMT(51, CXXBoolLiteralExpr , Expr) -LAST_EXPR(51) +STMT(51, CXXCastExpr , Expr) +STMT(52, CXXBoolLiteralExpr , Expr) +LAST_EXPR(52) #undef STMT #undef FIRST_STMT diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 4cb49b2ac6d..d9e3e12c4c6 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -364,11 +364,19 @@ public: return 0; } + //===---------------------- GNU Extension Expressions -------------------===// + virtual ExprResult ParseAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, IdentifierInfo *LabelII) { // "&&foo" return 0; } + virtual ExprResult ParseStmtExpr(SourceLocation LPLoc, StmtTy *SubStmt, + SourceLocation RPLoc) { // "({..})" + return 0; + } + + //===------------------------- C++ Expressions --------------------------===// /// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's. virtual ExprResult ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind, diff --git a/clang/test/Sema/stmt_exprs.c b/clang/test/Sema/stmt_exprs.c new file mode 100644 index 00000000000..34186a8d5cf --- /dev/null +++ b/clang/test/Sema/stmt_exprs.c @@ -0,0 +1,12 @@ +// clang %s -fsyntax-only + +typedef unsigned __uint32_t; + +#define __byte_swap_int_var(x) \ +__extension__ ({ register __uint32_t __X = (x); \ + __asm ("bswap %0" : "+r" (__X)); \ + __X; }) + +int test(int _x) { + return (__byte_swap_int_var(_x)); +} |