forked from OSchip/llvm-project
Add initial switch stmt support, patch by Anders Carlsson!
llvm-svn: 39989
This commit is contained in:
parent
a603a80607
commit
46eeb22fec
|
@ -338,7 +338,7 @@ Parser::StmtResult Parser::ParseDefaultStatement() {
|
|||
return true;
|
||||
|
||||
// TODO: look up enclosing switch stmt.
|
||||
return Actions.ParseDefaultStmt(DefaultLoc, ColonLoc, SubStmt.Val);
|
||||
return Actions.ParseDefaultStmt(DefaultLoc, ColonLoc, SubStmt.Val, CurScope);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -167,7 +167,8 @@ public:
|
|||
SourceLocation DotDotDotLoc, ExprTy *RHSVal,
|
||||
SourceLocation ColonLoc, StmtTy *SubStmt);
|
||||
virtual StmtResult ParseDefaultStmt(SourceLocation DefaultLoc,
|
||||
SourceLocation ColonLoc, StmtTy *SubStmt);
|
||||
SourceLocation ColonLoc, StmtTy *SubStmt,
|
||||
Scope *CurScope);
|
||||
virtual StmtResult ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
|
||||
SourceLocation ColonLoc, StmtTy *SubStmt);
|
||||
virtual StmtResult ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal,
|
||||
|
|
|
@ -51,7 +51,7 @@ Sema::ParseCompoundStmt(SourceLocation L, SourceLocation R,
|
|||
|
||||
Action::StmtResult
|
||||
Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval,
|
||||
SourceLocation DotDotDotLoc, ExprTy *RHSVal,
|
||||
SourceLocation DotDotDotLoc, ExprTy *rhsval,
|
||||
SourceLocation ColonLoc, StmtTy *SubStmt) {
|
||||
Expr *LHSVal = ((Expr *)lhsval);
|
||||
assert((LHSVal != 0) && "missing expression in case statement");
|
||||
|
@ -62,15 +62,34 @@ Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval,
|
|||
return Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr,
|
||||
LHSVal->getSourceRange());
|
||||
|
||||
// FIXME: SEMA for RHS of case range.
|
||||
// GCC extension: The expression shall be an integer constant.
|
||||
Expr *RHSVal = ((Expr *)rhsval);
|
||||
if (RHSVal) {
|
||||
if (!RHSVal->isIntegerConstantExpr(Context, &ExpLoc))
|
||||
return Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr,
|
||||
RHSVal->getSourceRange());
|
||||
}
|
||||
|
||||
return new CaseStmt(LHSVal, (Expr*)RHSVal, (Stmt*)SubStmt);
|
||||
}
|
||||
|
||||
Action::StmtResult
|
||||
Sema::ParseDefaultStmt(SourceLocation DefaultLoc,
|
||||
SourceLocation ColonLoc, StmtTy *SubStmt) {
|
||||
return new DefaultStmt((Stmt*)SubStmt);
|
||||
Sema::ParseDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
|
||||
StmtTy *SubStmt, Scope *CurScope) {
|
||||
Scope *S = CurScope->getBreakParent();
|
||||
|
||||
if (S->getDefaultStmt()) {
|
||||
Diag(DefaultLoc, diag::err_multiple_default_labels_defined);
|
||||
Diag(((DefaultStmt *)S->getDefaultStmt())->getDefaultLoc(),
|
||||
diag::err_first_label);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DefaultStmt *DS = new DefaultStmt(DefaultLoc, (Stmt*)SubStmt);
|
||||
S->setDefaultStmt(DS);
|
||||
|
||||
return DS;
|
||||
}
|
||||
|
||||
Action::StmtResult
|
||||
|
@ -119,6 +138,14 @@ Sema::ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal,
|
|||
|
||||
Action::StmtResult
|
||||
Sema::ParseSwitchStmt(SourceLocation SwitchLoc, ExprTy *Cond, StmtTy *Body) {
|
||||
Expr *condExpr = (Expr *)Cond;
|
||||
|
||||
QualType condType = condExpr->getType();
|
||||
|
||||
if (!condType->isIntegerType()) // C99 6.8.4.2p1
|
||||
return Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer,
|
||||
condType.getAsString(), condExpr->getSourceRange());
|
||||
|
||||
return new SwitchStmt((Expr*)Cond, (Stmt*)Body);
|
||||
}
|
||||
|
||||
|
@ -205,7 +232,6 @@ Sema::ParseContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// FIXME: Remember that this continue goes with this loop.
|
||||
return new ContinueStmt();
|
||||
}
|
||||
|
||||
|
@ -218,7 +244,6 @@ Sema::ParseBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// FIXME: Remember that this break goes with this loop/switch.
|
||||
return new BreakStmt();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace clang {
|
|||
class Decl;
|
||||
class IdentifierInfo;
|
||||
class StmtVisitor;
|
||||
class SwitchStmt;
|
||||
|
||||
/// Stmt - This represents one statement.
|
||||
///
|
||||
|
@ -127,9 +128,11 @@ class CaseStmt : public Stmt {
|
|||
Expr *LHSVal;
|
||||
Expr *RHSVal; // Non-null for GNU "case 1 ... 4" extension
|
||||
Stmt *SubStmt;
|
||||
SwitchStmt *Switch;
|
||||
public:
|
||||
CaseStmt(Expr *lhs, Expr *rhs, Stmt *substmt)
|
||||
: Stmt(CaseStmtClass), LHSVal(lhs), RHSVal(rhs), SubStmt(substmt) {}
|
||||
: Stmt(CaseStmtClass), LHSVal(lhs), RHSVal(rhs), SubStmt(substmt),
|
||||
Switch(0) {}
|
||||
|
||||
Expr *getLHS() { return LHSVal; }
|
||||
Expr *getRHS() { return RHSVal; }
|
||||
|
@ -143,10 +146,13 @@ public:
|
|||
};
|
||||
|
||||
class DefaultStmt : public Stmt {
|
||||
SourceLocation DefaultLoc;
|
||||
Stmt *SubStmt;
|
||||
public:
|
||||
DefaultStmt(Stmt *substmt) : Stmt(DefaultStmtClass), SubStmt(substmt) {}
|
||||
DefaultStmt(SourceLocation DL, Stmt *substmt) : Stmt(DefaultStmtClass),
|
||||
DefaultLoc(DL), SubStmt(substmt) {}
|
||||
|
||||
SourceLocation getDefaultLoc() const { return DefaultLoc; }
|
||||
Stmt *getSubStmt() { return SubStmt; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
|
|
|
@ -464,6 +464,8 @@ DIAG(err_previous_definition, ERROR,
|
|||
"previous definition is here")
|
||||
DIAG(err_previous_use, ERROR,
|
||||
"previous use is here")
|
||||
DIAG(err_first_label, ERROR,
|
||||
"first label is here")
|
||||
|
||||
DIAG(err_unexpected_typedef, ERROR,
|
||||
"unexpected type name '%0': expected expression")
|
||||
|
@ -659,6 +661,10 @@ DIAG(ext_typecheck_return_discards_qualifiers, EXTENSION,
|
|||
"returning '%1' from function expecting '%0' discards qualifiers")
|
||||
DIAG(err_typecheck_statement_requires_scalar, ERROR,
|
||||
"statement requires expression of scalar type ('%0' invalid)")
|
||||
DIAG(err_typecheck_statement_requires_integer, ERROR,
|
||||
"statement requires expression of integer type ('%0' invalid)")
|
||||
DIAG(err_multiple_default_labels_defined, ERROR,
|
||||
"multiple default labels in one switch")
|
||||
|
||||
DIAG(warn_return_missing_expr, WARNING,
|
||||
"non-void function '%0' should return a value")
|
||||
|
|
|
@ -204,7 +204,8 @@ public:
|
|||
return 0;
|
||||
}
|
||||
virtual StmtResult ParseDefaultStmt(SourceLocation DefaultLoc,
|
||||
SourceLocation ColonLoc, StmtTy *SubStmt){
|
||||
SourceLocation ColonLoc, StmtTy *SubStmt,
|
||||
Scope *CurScope){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,10 @@ private:
|
|||
/// implement these semantics.
|
||||
typedef llvm::SmallPtrSet<Action::DeclTy*, 32> DeclSetTy;
|
||||
DeclSetTy DeclsInScope;
|
||||
|
||||
/// DefaultStmt - when parsing the body of a switch statement, this keeps
|
||||
/// track of the statement with the default label.
|
||||
Action::StmtTy *DefaultStmt;
|
||||
public:
|
||||
Scope(Scope *Parent, unsigned ScopeFlags) {
|
||||
Init(Parent, ScopeFlags);
|
||||
|
@ -114,6 +118,8 @@ public:
|
|||
return DeclsInScope.count(D) != 0;
|
||||
}
|
||||
|
||||
void setDefaultStmt(Action::StmtTy *S) { DefaultStmt = S; }
|
||||
Action::StmtTy *getDefaultStmt() const { return DefaultStmt; }
|
||||
|
||||
/// Init - This is used by the parser to implement scope caching.
|
||||
///
|
||||
|
@ -132,6 +138,8 @@ public:
|
|||
FnParent = BreakParent = ContinueParent = 0;
|
||||
}
|
||||
|
||||
DefaultStmt = 0;
|
||||
|
||||
// If this scope is a function or contains breaks/continues, remember it.
|
||||
if (Flags & FnScope) FnParent = this;
|
||||
if (Flags & BreakScope) BreakParent = this;
|
||||
|
|
Loading…
Reference in New Issue