implement ast building and trivial semantic analysis of stmt exprs.

This implements test/Sema/stmt_exprs.c

llvm-svn: 40465
This commit is contained in:
Chris Lattner 2007-07-24 16:58:17 +00:00
parent a2e618712d
commit 366727fca1
9 changed files with 96 additions and 9 deletions

View File

@ -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) {

View File

@ -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();

View File

@ -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,

View File

@ -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);
}

View File

@ -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

View File

@ -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); }

View File

@ -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

View File

@ -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,

View File

@ -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));
}