Two fixes:

1) fix a crash on test/Sema/default.c by making
   sure that the switch scope is non-null.
2) if there is an error sema'ing a default or case stmt,
   make sure to return the substmt up, so that the error
   recovery code has more acurate info to continue with.

llvm-svn: 40134
This commit is contained in:
Chris Lattner 2007-07-21 03:00:26 +00:00
parent 5e39293e62
commit 3940737edf
3 changed files with 36 additions and 18 deletions

View File

@ -52,55 +52,63 @@ Sema::ParseCompoundStmt(SourceLocation L, SourceLocation R,
Action::StmtResult
Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval,
SourceLocation DotDotDotLoc, ExprTy *rhsval,
SourceLocation ColonLoc, StmtTy *SubStmt) {
SourceLocation ColonLoc, StmtTy *subStmt) {
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))
return Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr,
LHSVal->getSourceRange());
if (!LHSVal->isIntegerConstantExpr(Context, &ExpLoc)) {
Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr,
LHSVal->getSourceRange());
return SubStmt;
}
// 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());
if (RHSVal && !RHSVal->isIntegerConstantExpr(Context, &ExpLoc)) {
Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr,
RHSVal->getSourceRange());
return SubStmt;
}
return new CaseStmt(LHSVal, (Expr*)RHSVal, (Stmt*)SubStmt);
return new CaseStmt(LHSVal, (Expr*)RHSVal, SubStmt);
}
Action::StmtResult
Sema::ParseDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
StmtTy *SubStmt, Scope *CurScope) {
StmtTy *subStmt, Scope *CurScope) {
Stmt *SubStmt = static_cast<Stmt*>(subStmt);
Scope *S = CurScope->getBreakParent();
if (!S) {
Diag(DefaultLoc, diag::err_default_not_in_switch);
return SubStmt;
}
if (S->getDefaultStmt()) {
Diag(DefaultLoc, diag::err_multiple_default_labels_defined);
Diag(((DefaultStmt *)S->getDefaultStmt())->getDefaultLoc(),
diag::err_first_label);
return true;
return SubStmt;
}
DefaultStmt *DS = new DefaultStmt(DefaultLoc, (Stmt*)SubStmt);
DefaultStmt *DS = new DefaultStmt(DefaultLoc, SubStmt);
S->setDefaultStmt(DS);
return DS;
}
Action::StmtResult
Sema::ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
SourceLocation ColonLoc, StmtTy *SubStmt) {
SourceLocation ColonLoc, StmtTy *subStmt) {
Stmt *SubStmt = static_cast<Stmt*>(subStmt);
// Look up the record for this label identifier.
LabelStmt *&LabelDecl = LabelMap[II];
// If not forward referenced or defined already, just create a new LabelStmt.
if (LabelDecl == 0)
return LabelDecl = new LabelStmt(IdentLoc, II, (Stmt*)SubStmt);
return LabelDecl = new LabelStmt(IdentLoc, II, SubStmt);
assert(LabelDecl->getID() == II && "Label mismatch!");
@ -109,13 +117,13 @@ Sema::ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
if (LabelDecl->getSubStmt()) {
Diag(IdentLoc, diag::err_redefinition_of_label, LabelDecl->getName());
Diag(LabelDecl->getIdentLoc(), diag::err_previous_definition);
return (Stmt*)SubStmt;
return SubStmt;
}
// Otherwise, this label was forward declared, and we just found its real
// definition. Fill in the forward definition and return it.
LabelDecl->setIdentLoc(IdentLoc);
LabelDecl->setSubStmt((Stmt*)SubStmt);
LabelDecl->setSubStmt(SubStmt);
return LabelDecl;
}

View File

@ -653,6 +653,8 @@ DIAG(err_continue_not_in_loop, ERROR,
"'continue' statement not in loop statement")
DIAG(err_break_not_in_loop_or_switch, ERROR,
"'break' statement not in loop or switch statement")
DIAG(err_default_not_in_switch, ERROR,
"'default' statement not in switch statement")
DIAG(err_typecheck_return_incompatible, ERROR,
"incompatible type returning '%1', expected '%0'")
DIAG(ext_typecheck_return_pointer_int, EXTENSION,

View File

@ -0,0 +1,8 @@
// RUN: clang -parse-ast-check %s
void f5 (int z) {
if (z)
default: // expected-error {{not in switch statement}}
;
}