aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBalaji V. Iyer <balaji.v.iyer@intel.com>2012-12-13 03:42:50 +0000
committerBalaji V. Iyer <balaji.v.iyer@intel.com>2012-12-13 03:42:50 +0000
commitf4d5a299b5ec1b940a1bbfc74f8d9b1ab0a47ec3 (patch)
treeeb91ac79f646c1afba1d04e219d09363f9efb69f
parent7f7215acbcadc60f52e3d02e15e8fea688475c52 (diff)
Check invalid gotos and increments and report errors.
gcc/c-family/ChangeLog.cilkplus +2012-12-12 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * c-typeck.c (c_finish_cilk_loop) Added location for error reporting. + * c-cilk.c (wrapper_parm_cb): Likewise. + (copy_decl_for_cilk): Likewise. + (check_outlined_calls): Likewise. + (extract_for_fields): Reported an error instead of gcc_unreachable (). + gcc/testsuite/ChangeLog.cilkplus +2012-12-12 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c: + New test. + * gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c: + Likewise. + * gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp: New script. + gcc/ChangeLog.cilkplus +2012-12-12 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * c/c-objc-common.h (LANG_HOOKS_CILK_CHECK_CTRL_FLOW): New define. + * cilk.c (store_labels): New function. + (find_all_labels): Likewise. + (check_goto_labels_inside_cilk_for_body): Likewise. + (check_gotos_inside_cilk_for): Likewise. + (check_gotos_outside_cilk_for): Likewise. + (check_cilk_ctrl_flow): Likewise. + * langhooks.c (lhd_cilk_check_ctrl_flow): Likewise. + * langhooks.h (struct lang_hooks_for_cilkplus): New function pointer. + * gimplify.c (gimplify_function_tree): Called cilk_check_ctrl_flow + function that is part of lang_hooks. + * langhooks-def.h (LANG_HOOKS_CILK): New field added. + git-svn-id: https://gcc.gnu.org/svn/gcc/branches/cilkplus@194467 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.cilkplus15
-rw-r--r--gcc/c-family/ChangeLog.cilkplus8
-rw-r--r--gcc/c-family/c-cilk.c22
-rw-r--r--gcc/c/c-objc-common.h3
-rw-r--r--gcc/c/c-typeck.c8
-rw-r--r--gcc/cilk.c157
-rw-r--r--gcc/cilk.h1
-rw-r--r--gcc/gimplify.c2
-rw-r--r--gcc/langhooks-def.h3
-rw-r--r--gcc/langhooks.c5
-rw-r--r--gcc/langhooks.h1
-rw-r--r--gcc/testsuite/ChangeLog.cilkplus8
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c22
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp59
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c49
15 files changed, 353 insertions, 10 deletions
diff --git a/gcc/ChangeLog.cilkplus b/gcc/ChangeLog.cilkplus
index 5bbf9287353..227c4b0ce29 100644
--- a/gcc/ChangeLog.cilkplus
+++ b/gcc/ChangeLog.cilkplus
@@ -1,3 +1,18 @@
+2012-12-12 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c/c-objc-common.h (LANG_HOOKS_CILK_CHECK_CTRL_FLOW): New define.
+ * cilk.c (store_labels): New function.
+ (find_all_labels): Likewise.
+ (check_goto_labels_inside_cilk_for_body): Likewise.
+ (check_gotos_inside_cilk_for): Likewise.
+ (check_gotos_outside_cilk_for): Likewise.
+ (check_cilk_ctrl_flow): Likewise.
+ * langhooks.c (lhd_cilk_check_ctrl_flow): Likewise.
+ * langhooks.h (struct lang_hooks_for_cilkplus): New function pointer.
+ * gimplify.c (gimplify_function_tree): Called cilk_check_ctrl_flow
+ function that is part of lang_hooks.
+ * langhooks-def.h (LANG_HOOKS_CILK): New field added.
+
2012-12-10 Balaji V. Iyer <balaji.v.iyer@intel.com>
* doc/tm.texi (TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR): Added
diff --git a/gcc/c-family/ChangeLog.cilkplus b/gcc/c-family/ChangeLog.cilkplus
index 82e4d39a70a..ab4e088a5a7 100644
--- a/gcc/c-family/ChangeLog.cilkplus
+++ b/gcc/c-family/ChangeLog.cilkplus
@@ -1,3 +1,11 @@
+2012-12-12 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c-typeck.c (c_finish_cilk_loop) Added location for error reporting.
+ * c-cilk.c (wrapper_parm_cb): Likewise.
+ (copy_decl_for_cilk): Likewise.
+ (check_outlined_calls): Likewise.
+ (extract_for_fields): Reported an error instead of gcc_unreachable ().
+
2012-12-10 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-cpp-elem-function.c: New file.
diff --git a/gcc/c-family/c-cilk.c b/gcc/c-family/c-cilk.c
index ee87a3e9a9e..8d873f9f187 100644
--- a/gcc/c-family/c-cilk.c
+++ b/gcc/c-family/c-cilk.c
@@ -1292,8 +1292,9 @@ wrapper_parm_cb (const void *key0, void **val0, void *data)
them in code that spawns. */
if ((TREE_CODE (arg) == VAR_DECL) && DECL_HARD_REGISTER (arg))
{
- error ("explicit register variable %qD may not be modified in spawn",
- arg);
+ error_at (EXPR_LOCATION (arg),
+ "explicit register variable %qD may not be modified in "
+ "spawn", arg);
arg = null_pointer_node;
}
else
@@ -1464,7 +1465,8 @@ copy_decl_for_cilk (tree decl, copy_body_data *id)
return copy_decl_no_change (decl, id);
case LABEL_DECL:
- error ("Invalid use of label %q+D in spawn", decl);
+ error_at (EXPR_LOCATION (decl),
+ "Invalid use of label %q+D in spawn", decl);
return error_mark_node;
case RESULT_DECL:
@@ -1544,7 +1546,8 @@ check_outlined_calls (tree *tp,
if (! (flags & ECF_NOTHROW) && flag_exceptions)
*throws = true;
if (flags & ECF_RETURNS_TWICE)
- error ("Can not spawn call to function that returns twice");
+ error_at (EXPR_LOCATION (t),
+ "Can not spawn call to function that returns twice");
return 0;
}
@@ -1761,6 +1764,7 @@ extract_for_fields (struct cilk_for_desc *cfd, tree loop)
tree cond = FOR_COND (loop);
tree init = CILK_FOR_INIT (loop);
tree incr = cilk_simplify_tree (FOR_EXPR (loop));
+ tree orig_incr = cilk_simplify_tree (FOR_EXPR (loop)); /* Copy for LOC. */
tree grain = CILK_FOR_GRAIN (loop);
tree body = FOR_BODY (loop);
@@ -1937,9 +1941,12 @@ extract_for_fields (struct cilk_for_desc *cfd, tree loop)
exactly_one = incr_direction == -1;
}
else
- gcc_unreachable ();
+ {
+ error_at (EXPR_LOCATION (orig_incr),
+ "Invalid loop increment operation.");
+ cfd->invalid = true;
+ }
break;
-
default:
gcc_unreachable ();
}
@@ -2865,3 +2872,6 @@ c_make_cilk_frame (void)
}
return decl;
}
+
+
+
diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
index f44c20e0700..cffecaa7276 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -120,4 +120,7 @@ along with GCC; see the file COPYING3. If not see
#undef LANG_HOOKS_ELEM_FN_CREATE_FN
#define LANG_HOOKS_ELEM_FN_CREATE_FN elem_fn_create_fn
+
+#undef LANG_HOOKS_CILK_CHECK_CTRL_FLOW
+#define LANG_HOOKS_CILK_CHECK_CTRL_FLOW cilk_check_ctrl_flow
#endif /* GCC_C_OBJC_COMMON */
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 19dab7f5302..d39714967b7 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -10982,19 +10982,19 @@ c_finish_cilk_loop (location_t start_locus ATTRIBUTE_UNUSED, tree cvar,
if (!cond)
{
- error ("cilk_for missing condition");
+ error ("_Cilk_for missing condition");
return;
}
if (!incr)
{
- error ("cilk_for missing increment");
+ error ("_Cilk_for missing increment");
return;
}
/* If the condition is zero don't generate a loop construct. */
if (TREE_CONSTANT (cond))
{
- error ("cilk_for has constant condition");
+ error_at (EXPR_LOCATION (cond), "_Cilk_for has constant condition");
return;
}
if (!cvar)
@@ -11004,7 +11004,7 @@ c_finish_cilk_loop (location_t start_locus ATTRIBUTE_UNUSED, tree cvar,
}
if (clab)
{
- error ("cilk_for has continue");
+ error_at (EXPR_LOCATION (clab), "_Cilk_for has continue");
return;
}
diff --git a/gcc/cilk.c b/gcc/cilk.c
index 80e9e742e48..446285b16ab 100644
--- a/gcc/cilk.c
+++ b/gcc/cilk.c
@@ -37,6 +37,16 @@ along with GCC; see the file COPYING3. If not see
#include "output.h"
#include "dwarf2out.h"
+
+/* The only reason why we have this struct is that we need a void * to pass
+ into the walk_tree function. */
+
+struct label_list_struct
+{
+ vec <tree, va_gc> *labels;
+};
+
+
tree cilk_trees[(int) CILK_TI_MAX];
static HOST_WIDE_INT worker_tail_offset;
@@ -1406,3 +1416,150 @@ is_cilk_function_decl (tree olddecl, tree newdecl)
return true;
return false;
}
+
+
+/* Helper function for walk_trees. *WALK_SUBTREES is seto to zero if it
+ encounters a CILK_FOR, LABEL_DECL or GOTO in *TP. If LABEL_DECL is found
+ then the value is pushed into the list pointed by DATA. */
+
+static tree
+store_labels (tree *tp, int *walk_subtrees, void *data)
+{
+ struct label_list_struct *label_list = (struct label_list_struct *)data;
+
+ if (!tp || !*tp)
+ return NULL_TREE;
+ else if (TREE_CODE (*tp) == CILK_FOR_STMT
+ || TREE_CODE (*tp) == GOTO_EXPR)
+ *walk_subtrees = 0;
+ else if (TREE_CODE (*tp) == LABEL_DECL)
+ {
+ *walk_subtrees = 0;
+ vec_safe_push (label_list->labels, *tp);
+ }
+ else
+ *walk_subtrees = 1;
+ return NULL_TREE;
+}
+
+/* Finds all the labels in STMT that is not inside a CILK_FOR. */
+
+static struct label_list_struct
+find_all_labels (tree stmt)
+{
+ struct label_list_struct label_list;
+
+ label_list.labels = NULL;
+ walk_tree (&stmt, store_labels, (void *)&label_list, NULL);
+ return label_list;
+}
+
+/* Helper function for walk_trees. If the *TP is GOTO_EXPR it will check if
+ its destination label is in the list in *DATA. *WALK_SUBTREES is always
+ set to one. */
+
+static tree
+check_goto_labels_inside_cilk_for_body (tree *tp, int *walk_subtrees,
+ void *data)
+{
+ size_t ii = 0;
+ tree ii_t = NULL_TREE;
+ bool label_ok = false;
+ struct label_list_struct *label_list = (struct label_list_struct *)data;
+ if (!tp || !*tp)
+ return NULL_TREE;
+
+ if (TREE_CODE (*tp) == GOTO_EXPR)
+ {
+ tree goto_label = GOTO_DESTINATION (*tp);
+ for (ii = 0; vec_safe_iterate (label_list->labels, ii, &ii_t); ii++)
+ if (ii_t == goto_label)
+ label_ok = true;
+
+ if (!label_ok)
+ {
+ error_at (EXPR_LOCATION (*tp), "goto destination is outside the "
+ "_Cilk_for scope.");
+ *tp = error_mark_node;
+ }
+ }
+ else if (TREE_CODE (*tp) == CILK_FOR_STMT)
+ *walk_subtrees = 0;
+ else
+ *walk_subtrees = 1;
+ return NULL_TREE;
+}
+
+/* Helper function for walk_tree. If *TP is a CILK_FOR_STMT, then it will find
+ all the labels in it and then walks through the body to see if the gotos in
+ it are using the local labels. */
+
+static tree
+check_gotos_inside_cilk_for (tree *tp, int *walk_subtrees,
+ void *data ATTRIBUTE_UNUSED)
+{
+ struct label_list_struct label_list;
+ if (!tp || !*tp)
+ return NULL_TREE;
+
+ if (TREE_CODE (*tp) == CILK_FOR_STMT)
+ {
+ label_list = find_all_labels (FOR_BODY (*tp));
+ walk_tree (&FOR_BODY (*tp), check_goto_labels_inside_cilk_for_body,
+ (void *) &label_list, NULL);
+ }
+ *walk_subtrees = 1;
+ return NULL_TREE;
+}
+
+/* Helper function for walk_tree. */
+
+static tree
+check_gotos_outside_cilk_for (tree *tp, int *walk_subtrees,
+ void *data)
+{
+ tree ii_t = NULL_TREE;
+ size_t ii = 0;
+ bool label_ok = false;
+ struct label_list_struct *label_list = (struct label_list_struct *) data;
+ if (!tp || !*tp)
+ return NULL_TREE;
+
+ if (TREE_CODE (*tp) == GOTO_EXPR)
+ {
+ tree goto_label = GOTO_DESTINATION (*tp);
+ *walk_subtrees = 0;
+ for (ii = 0; vec_safe_iterate (label_list->labels, ii, &ii_t); ii++)
+ if (ii_t == goto_label)
+ label_ok = true;
+
+ if (!label_ok)
+ {
+ error_at (EXPR_LOCATION (*tp), "Goto label is inside a _Cilk_for "
+ "while the goto itself is outside.");
+ *tp = error_mark_node;
+ }
+ }
+ else if (TREE_CODE (*tp) == CILK_FOR_STMT)
+ *walk_subtrees = 0;
+ else
+ *walk_subtrees = 1;
+
+ return NULL_TREE;
+}
+
+/* Checks some of the control flow changing statements (e.g. goto) in *FNBODY
+ are valid. */
+
+void
+cilk_check_ctrl_flow (tree *fnbody)
+{
+ struct label_list_struct label_list;
+ if (!fnbody)
+ return;
+ walk_tree (fnbody, check_gotos_inside_cilk_for, NULL, NULL);
+
+ label_list = find_all_labels (*fnbody);
+ walk_tree (fnbody, check_gotos_outside_cilk_for, (void *) &label_list, NULL);
+ return;
+}
diff --git a/gcc/cilk.h b/gcc/cilk.h
index c14b8e6910c..8b399f8737a 100644
--- a/gcc/cilk.h
+++ b/gcc/cilk.h
@@ -296,6 +296,7 @@ bool cilk_valid_spawn (tree);
void gimplify_cilk_spawn (tree *, gimple_seq *, gimple_seq *);
void gimplify_cilk_sync (tree *, gimple_seq *);
void gimplify_cilk_for (tree *, gimple_seq *, gimple_seq *);
+void cilk_check_ctrl_flow (tree *);
extern tree cilk_call_setjmp (tree);
extern tree make_cilk_frame (tree);
extern tree build_cilk_function_exit (tree, bool, bool);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 1b982f05915..a4394bbc77e 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -8415,6 +8415,8 @@ gimplify_function_tree (tree fndecl)
gcc_assert (!gimple_body (fndecl));
+ if (flag_enable_cilk)
+ lang_hooks.cilkplus.cilk_check_ctrl_flow (&DECL_SAVED_TREE (fndecl));
/* Here we check to see if we have a function with the attribute "vector."
If so, then we must clone it to masked/unmasked when apropriate. */
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index d56d1b673ee..a19d7681596 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -217,6 +217,7 @@ void lhd_gimplify_cilk_spawn (tree *, gimple_seq *, gimple_seq *);
void lhd_gimplify_cilk_for (tree *, gimple_seq *, gimple_seq *);
void lhd_gimplify_cilk_sync (tree *, gimple_seq *);
void lhd_elem_fn_create_fn (tree);
+void lhd_cilk_check_ctrl_flow (tree *);
#define LANG_HOOKS_CILK_RECOGNIZE_SPAWN hook_bool_tree_false
#define LANG_HOOKS_CILK_VALID_CTOR hook_bool_tree_false
#define LANG_HOOKS_CILK_VALID_SPAWN lhd_cilk_valid_spawn
@@ -224,6 +225,7 @@ void lhd_elem_fn_create_fn (tree);
#define LANG_HOOKS_GIMPLIFY_CILK_FOR lhd_gimplify_cilk_for
#define LANG_HOOKS_GIMPLIFY_CILK_SYNC lhd_gimplify_cilk_sync
#define LANG_HOOKS_ELEM_FN_CREATE_FN lhd_elem_fn_create_fn
+#define LANG_HOOKS_CILK_CHECK_CTRL_FLOW lhd_cilk_check_ctrl_flow
#define LANG_HOOKS_CILK { \
LANG_HOOKS_CILK_RECOGNIZE_SPAWN, \
LANG_HOOKS_CILK_VALID_CTOR, \
@@ -231,6 +233,7 @@ void lhd_elem_fn_create_fn (tree);
LANG_HOOKS_GIMPLIFY_CILK_SPAWN, \
LANG_HOOKS_GIMPLIFY_CILK_FOR, \
LANG_HOOKS_GIMPLIFY_CILK_SYNC, \
+ LANG_HOOKS_CILK_CHECK_CTRL_FLOW, \
LANG_HOOKS_ELEM_FN_CREATE_FN \
}
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 9f339ae1a2b..7ca43e3cc99 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -730,3 +730,8 @@ lhd_elem_fn_create_fn (tree x ATTRIBUTE_UNUSED)
{
return;
}
+
+void lhd_cilk_check_ctrl_flow (tree *x ATTRIBUTE_UNUSED)
+{
+ return;
+}
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index e7ccae3013c..16ca99e0d20 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -235,6 +235,7 @@ struct lang_hooks_for_cilkplus
void (*gimplify_cilk_spawn) (tree *, gimple_seq *, gimple_seq *);
void (*gimplify_cilk_for) (tree *, gimple_seq *, gimple_seq *);
void (*gimplify_cilk_sync) (tree *, gimple_seq *);
+ void (*cilk_check_ctrl_flow) (tree *);
void (*elem_fn_create_fn) (tree);
};
diff --git a/gcc/testsuite/ChangeLog.cilkplus b/gcc/testsuite/ChangeLog.cilkplus
index b38d6685681..85959df6983 100644
--- a/gcc/testsuite/ChangeLog.cilkplus
+++ b/gcc/testsuite/ChangeLog.cilkplus
@@ -1,3 +1,11 @@
+2012-12-12 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c:
+ New test.
+ * gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c:
+ Likewise.
+ * gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp: New script.
+
2012-12-10 Balaji V. Iyer <balaji.v.iyer@intel.com>
* gcc.dg/cilk-plus/elem_fn_tests/test1.c: Remove.
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c
new file mode 100644
index 00000000000..e75b584f4c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c
@@ -0,0 +1,22 @@
+#define ARRAY_SIZE 100000
+
+int main(void)
+{
+ int ii = 0;
+ int array[ARRAY_SIZE];
+
+ _Cilk_for (ii = 0; ii < 10; ii <<= 2) /* { dg-error "Invalid loop increment operation." } */
+ array[ii] = 5;
+
+ _Cilk_for (ii = 0; ii < 10; ii *= 2) /* { dg-error "Invalid loop increment operation." } */
+ array[ii] = 5;
+
+ _Cilk_for (ii = 0; ii < 10; ii /= 2) /* { dg-error "Invalid loop increment operation." } */
+ array[ii] = 5;
+
+ _Cilk_for (ii = 0; ii < 10; ii = 5) /* { dg-error "Invalid loop increment operation." } */
+ array[ii] = 5;
+
+ _Cilk_for (ii = 0; ii < 10; ii >>= 2) /* { dg-error "Invalid loop increment operation." } */
+ array[ii] = 5;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp
new file mode 100644
index 00000000000..9a66f1b8154
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp
@@ -0,0 +1,59 @@
+# Copyright (C) 2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+if { ![istarget i?86*-*-*] && ![istarget x86_64-*-*] } then {
+ return
+}
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O0" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O1" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O2" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O3" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O0 -g" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O1 -g" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O2 -g" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O3 -g" " "
+dg-finish
+
+dg-finish
+
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c
new file mode 100644
index 00000000000..9b5877bdecc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c
@@ -0,0 +1,49 @@
+/* Checks goto inside cilk_for and outside of cilk_for. */
+
+#define ARRAY_SIZE 10000
+int a[ARRAY_SIZE], b[ARRAY_SIZE][ARRAY_SIZE];
+int main (int argc, char **argv)
+{
+ int i = 0, q = 0, j = 0;
+ _Cilk_for (i = 0; i < ARRAY_SIZE; i++)
+ {
+l1:
+ a[i] = i;
+l2:
+ if (i%2)
+ q+=2;
+ }
+ goto l1; /* { dg-error "Goto label is inside a _Cilk_for while the goto itself is outside." } */
+ if(a[(ARRAY_SIZE / 2)] == (ARRAY_SIZE / 2))
+ goto l2; /* { dg-error "Goto label is inside a _Cilk_for while the goto itself is outside." } */
+
+ _Cilk_for (i = 0; i < ARRAY_SIZE; i++)
+ {
+ /* Goto jumps into another Cilk_for. */
+ goto l2; /* { dg-error "goto destination is outside the _Cilk_for scope." } */
+ a[i] = i;
+l3:
+ goto l3; /* This is OK! */
+ }
+ if(a[(ARRAY_SIZE / 2)] == (ARRAY_SIZE / 2))
+ goto l4; /* This is OK! */
+ else
+ goto l3; /* { dg-error "Goto label is inside a _Cilk_for while the goto itself is outside." } */
+
+ _Cilk_for (i = 0; i < ARRAY_SIZE; i++) {
+l5:
+ if (i % 5) {
+ _Cilk_for (j = 0; j < ARRAY_SIZE; j++) {
+ goto l5; /* { dg-error "goto destination is outside the _Cilk_for scope." } */
+ b[i][j] = (i+j);
+l6:
+ q++;
+ goto l6; /* This is OK! */
+ }
+ goto l6; /* { dg-error "goto destination is outside the _Cilk_for scope." } */
+ }
+ }
+
+l4:
+ return 0;
+}