]> granicus.if.org Git - clang/commitdiff
Two fixes:
authorChris Lattner <sabre@nondot.org>
Sat, 21 Jul 2007 03:00:26 +0000 (03:00 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 21 Jul 2007 03:00:26 +0000 (03:00 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40134 91177308-0d34-0410-b5e6-96231b3b80d8

Sema/SemaStmt.cpp
include/clang/Basic/DiagnosticKinds.def
test/Sema/default.c [new file with mode: 0644]

index 395948c062ef7198e7359d0a7ee5970e469019fe..17e042c9f1036ccc6709bad81ea694cdfa972047 100644 (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;
 }
 
index 5459e35c89b10d09c7361d24e13cde5581c9462b..6a3ecf7814cb0ba57250a8c8939b7f5e64704d40 100644 (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,
diff --git a/test/Sema/default.c b/test/Sema/default.c
new file mode 100644 (file)
index 0000000..e714eff
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: clang -parse-ast-check %s
+
+void f5 (int z) { 
+  if (z) 
+    default:  // expected-error {{not in switch statement}}
+      ; 
+} 
+