forked from OSchip/llvm-project
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:
parent
5e39293e62
commit
3940737edf
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// RUN: clang -parse-ast-check %s
|
||||
|
||||
void f5 (int z) {
|
||||
if (z)
|
||||
default: // expected-error {{not in switch statement}}
|
||||
;
|
||||
}
|
||||
|
Loading…
Reference in New Issue