forked from OSchip/llvm-project
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:
parent
a2e618712d
commit
366727fca1
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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); }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
}
|
Loading…
Reference in New Issue