re PR c++/30849 (ICE with invalid asm statement)
authorLee Millward <lee.millward@gmail.com>
Thu, 2 Aug 2007 17:50:55 +0000 (17:50 +0000)
committerLee Millward <lmillward@gcc.gnu.org>
Thu, 2 Aug 2007 17:50:55 +0000 (17:50 +0000)
PR c++/30849
PR c++/30850
PR c++/30851
* parser.c (cp_parser_asm_definition): Detect and discard asm
statements with invalid inputs or outputs.
        (cp_parser_asm_operand_list): Return error mark node if any
        of the operands are invalid. Adjust documentation.

PR c++/30849
* g++.dg/parse/asm1.C: New test.

PR c++/30850
* g++.dg/parse/asm2.C: Likewise.

PR c++/30851
* g++.dg/parse/asm3.C: Likewise.

From-SVN: r127167

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/asm1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/asm2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/asm3.C [new file with mode: 0644]

index 2697da3938e6fab3bde6074e057e292ebd64dd16..26edb7dfdcff71309c4693f16497f359c5df6ca6 100644 (file)
@@ -1,3 +1,14 @@
+
+2007-08-02  Lee Millward  <lee.millward@gmail.com>
+
+       PR c++/30849
+       PR c++/30850
+       PR c++/30851
+       * parser.c (cp_parser_asm_definition): Detect and discard asm
+       statements with invalid inputs or outputs.
+        (cp_parser_asm_operand_list): Return error mark node if any
+        of the operands are invalid. Adjust documentation.
+       
 2007-08-02  Nick Clifton  <nickc@redhat.com>
 
        * typeck.c: Change copyright header to refer to version 3 of the
index 4e4242290c16e0a8d50b0db89c844bccbdd7c81a..530ddbae8a2a7985287d86bc07c7669d58f2d0e5 100644 (file)
@@ -11755,6 +11755,8 @@ cp_parser_asm_definition (cp_parser* parser)
   tree asm_stmt;
   bool volatile_p = false;
   bool extended_p = false;
+  bool invalid_inputs_p = false;
+  bool invalid_outputs_p = false;
 
   /* Look for the `asm' keyword.  */
   cp_parser_require_keyword (parser, RID_ASM, "`asm'");
@@ -11808,6 +11810,9 @@ cp_parser_asm_definition (cp_parser* parser)
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            outputs = cp_parser_asm_operand_list (parser);
+
+           if (outputs == error_mark_node)
+             invalid_outputs_p = true;
        }
       /* If the next token is `::', there are no outputs, and the
         next token is the beginning of the inputs.  */
@@ -11827,6 +11832,9 @@ cp_parser_asm_definition (cp_parser* parser)
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            inputs = cp_parser_asm_operand_list (parser);
+
+           if (inputs == error_mark_node)
+             invalid_inputs_p = true;
        }
       else if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
        /* The clobbers are coming next.  */
@@ -11850,23 +11858,26 @@ cp_parser_asm_definition (cp_parser* parser)
                                           /*consume_paren=*/true);
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
 
-  /* Create the ASM_EXPR.  */
-  if (parser->in_function_body)
+  if (!invalid_inputs_p && !invalid_outputs_p)
     {
-      asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
-                                 inputs, clobbers);
-      /* If the extended syntax was not used, mark the ASM_EXPR.  */
-      if (!extended_p)
+      /* Create the ASM_EXPR.  */
+      if (parser->in_function_body)
        {
-         tree temp = asm_stmt;
-         if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
-           temp = TREE_OPERAND (temp, 0);
+         asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
+                                     inputs, clobbers);
+         /* If the extended syntax was not used, mark the ASM_EXPR.  */
+         if (!extended_p)
+           {
+             tree temp = asm_stmt;
+             if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
+               temp = TREE_OPERAND (temp, 0);
 
-         ASM_INPUT_P (temp) = 1;
+             ASM_INPUT_P (temp) = 1;
+           }
        }
+      else
+       cgraph_add_asm_node (string);
     }
-  else
-    cgraph_add_asm_node (string);
 }
 
 /* Declarators [gram.dcl.decl] */
@@ -15645,12 +15656,14 @@ cp_parser_asm_specification_opt (cp_parser* parser)
    each node is the expression.  The TREE_PURPOSE is itself a
    TREE_LIST whose TREE_PURPOSE is a STRING_CST for the bracketed
    string-literal (or NULL_TREE if not present) and whose TREE_VALUE
-   is a STRING_CST for the string literal before the parenthesis.  */
+   is a STRING_CST for the string literal before the parenthesis. Returns
+   ERROR_MARK_NODE if any of the operands are invalid.  */
 
 static tree
 cp_parser_asm_operand_list (cp_parser* parser)
 {
   tree asm_operands = NULL_TREE;
+  bool invalid_operands = false;
 
   while (true)
     {
@@ -15682,6 +15695,11 @@ cp_parser_asm_operand_list (cp_parser* parser)
       /* Look for the `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
+      if (name == error_mark_node 
+         || string_literal == error_mark_node 
+         || expression == error_mark_node)
+        invalid_operands = true;
+
       /* Add this operand to the list.  */
       asm_operands = tree_cons (build_tree_list (name, string_literal),
                                expression,
@@ -15694,7 +15712,7 @@ cp_parser_asm_operand_list (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
     }
 
-  return nreverse (asm_operands);
+  return invalid_operands ? error_mark_node : nreverse (asm_operands);
 }
 
 /* Parse an asm-clobber-list.
index a03a6d138be0df787c496a30023ba7ace2682fe0..07d751b5d7ae1f23a796243a92f6fa443e91c4f6 100644 (file)
@@ -1,3 +1,14 @@
+2007-08-02  Lee Millward  <lee.millward@gmail.com>
+
+       PR c++/30849
+       * g++.dg/parse/asm1.C: New test.
+
+       PR c++/30850
+       * g++.dg/parse/asm2.C: Likewise.
+
+       PR c++/30851
+       * g++.dg/parse/asm3.C: Likewise.
+       
 2007-08-02  Rask Ingemann Lambertsen  <rask@sygehus.dk>
 
        * gcc.dg/tree-ssa/gen-vect-2.c: Use "char" for vector elements if
diff --git a/gcc/testsuite/g++.dg/parse/asm1.C b/gcc/testsuite/g++.dg/parse/asm1.C
new file mode 100644 (file)
index 0000000..009ffbd
--- /dev/null
@@ -0,0 +1,6 @@
+//PR c++/30849
+
+void foo()
+{
+  asm("" : 0);  // { dg-error "numeric constant|token" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/asm2.C b/gcc/testsuite/g++.dg/parse/asm2.C
new file mode 100644 (file)
index 0000000..09924c9
--- /dev/null
@@ -0,0 +1,6 @@
+//PR c++/30850
+
+void foo()
+{
+  asm("" :: 0);  // { dg-error "numeric constant|token" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/asm3.C b/gcc/testsuite/g++.dg/parse/asm3.C
new file mode 100644 (file)
index 0000000..91f19e4
--- /dev/null
@@ -0,0 +1,6 @@
+//PR c++/30851
+
+void foo()
+{
+  asm ("%[x]" : [0](x));  // { dg-error "numeric constant|token" }
+}