diff options
Diffstat (limited to 'clang/Sema/SemaStmt.cpp')
| -rw-r--r-- | clang/Sema/SemaStmt.cpp | 74 |
1 files changed, 58 insertions, 16 deletions
diff --git a/clang/Sema/SemaStmt.cpp b/clang/Sema/SemaStmt.cpp index 17e042c9f10..33a11344e7a 100644 --- a/clang/Sema/SemaStmt.cpp +++ b/clang/Sema/SemaStmt.cpp @@ -18,6 +18,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" #include "clang/Lex/IdentifierTable.h" + using namespace clang; Sema::StmtResult Sema::ParseExprStmt(ExprTy *expr) { @@ -56,7 +57,7 @@ Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval, Stmt *SubStmt = static_cast<Stmt*>(subStmt); Expr *LHSVal = ((Expr *)lhsval); assert((LHSVal != 0) && "missing expression in case statement"); - + SourceLocation ExpLoc; // C99 6.8.4.2p3: The expression shall be an integer constant. if (!LHSVal->isIntegerConstantExpr(Context, &ExpLoc)) { @@ -73,7 +74,13 @@ Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval, return SubStmt; } - return new CaseStmt(LHSVal, (Expr*)RHSVal, SubStmt); + CaseStmt *CS = new CaseStmt(LHSVal, RHSVal, SubStmt); + + assert(!SwitchStack.empty() && "missing push/pop in switch stack!"); + SwitchStmt *SS = SwitchStack.back(); + SS->addSwitchCase(CS); + + return CS; } Action::StmtResult @@ -87,15 +94,12 @@ Sema::ParseDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, return SubStmt; } - if (S->getDefaultStmt()) { - Diag(DefaultLoc, diag::err_multiple_default_labels_defined); - Diag(((DefaultStmt *)S->getDefaultStmt())->getDefaultLoc(), - diag::err_first_label); - return SubStmt; - } - DefaultStmt *DS = new DefaultStmt(DefaultLoc, SubStmt); - S->setDefaultStmt(DS); + + assert(!SwitchStack.empty() && "missing push/pop in switch stack!"); + SwitchStmt *SS = SwitchStack.back(); + SS->addSwitchCase(DS); + return DS; } @@ -145,16 +149,54 @@ Sema::ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal, } Action::StmtResult -Sema::ParseSwitchStmt(SourceLocation SwitchLoc, ExprTy *Cond, StmtTy *Body) { - Expr *condExpr = (Expr *)Cond; +Sema::StartSwitchStmt(ExprTy *Cond) { + SwitchStmt *SS = new SwitchStmt((Expr*)Cond); + SwitchStack.push_back(SS); + return SS; +} + +Action::StmtResult +Sema::FinishSwitchStmt(SourceLocation SwitchLoc, StmtTy *Switch, ExprTy *Body) { + Stmt *BodyStmt = (Stmt*)Body; + + SwitchStmt *SS = SwitchStack.back(); + assert(SS == (SwitchStmt*)Switch && "switch stack missing push/pop!"); + + SS->setBody(BodyStmt); + SwitchStack.pop_back(); + Expr *condExpr = SS->getCond(); 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()); + if (!condType->isIntegerType()) { // C99 6.8.4.2p1 + Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer, + condType.getAsString(), condExpr->getSourceRange()); + return false; + } + + DefaultStmt *CurDefaultStmt = 0; + + // FIXME: The list of cases is backwards and needs to be reversed. + for (SwitchCase *SC = SS->getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) { + if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC)) { + if (CurDefaultStmt) { + Diag(DS->getDefaultLoc(), + diag::err_multiple_default_labels_defined); + Diag(CurDefaultStmt->getDefaultLoc(), + diag::err_first_label); + + // FIXME: Remove the default statement from the switch block + // so that we'll return a valid AST. + } else { + CurDefaultStmt = DS; + } + + // FIXME: Check that case values are unique here. + } + } - return new SwitchStmt((Expr*)Cond, (Stmt*)Body); + return SS; } Action::StmtResult |

