Merge C++ from gomp-20050608-branch.

From-SVN: r111867
This commit is contained in:
Richard Henderson 2006-03-09 10:14:39 -08:00
parent f8fe05458d
commit 1799e5d5ca
131 changed files with 6607 additions and 310 deletions

View File

@ -1,3 +1,8 @@
2006-03-09 Diego Novillo <dnovillo@redhat.com>
* tree-cfg.c (move_block_to_fn): Remove the statements from the
original fn's eh regions.
2006-03-09 Eric Botcazou <ebotcazou@adacore.com>
* fold-const.c (build_range_check): Make sure to use a valid type to

View File

@ -1,3 +1,452 @@
2006-03-09 Diego Novillo <dnovillo@redhat.com>
Merge from gomp-20050608-branch
2006-02-02 Diego Novillo <dnovillo@redhat.com>
* decl.c (pop_labels_1): Use appropriate pointer casting.
(poplevel_named_label_1): Likewise.
(named_label_entry_hash): Likewise.
(named_label_entry_eq): Likewise.
(check_goto): Likewise.
(define_label): Likewise.
2006-01-26 Diego Novillo <dnovillo@redhat.com>
* cp-tree.h (CP_OMP_CLAUSE_INFO): Use TREE_TYPE instead
of TREE_BLOCK.
* pt.c: Use OMP_CLAUSE_CODE and OMP_CLAUSE_OPERAND
instead of TREE_CODE/TREE_OPERAND.
* semantics.c: Likewise.
* parser.c: Likewise.
2005-11-10 Diego Novillo <dnovillo@redhat.com>
* parser.c (cp_parser_omp_threadprivate): Emit diagnostic if
target does not support TLS.
2005-11-09 Jakub Jelinek <jakub@redhat.com>
* decl.c (redeclaration_error_message): Don't error about
DECL_THREAD_LOCAL_P mismatches if CP_DECL_THREADPRIVATE_P
(olddecl).
2005-11-08 Jakub Jelinek <jakub@redhat.com>
PR c++/24735
* semantics.c (finish_omp_barrier, finish_omp_flush): New
functions.
* parser.c (cp_parser_omp_barrier): Call finish_omp_barrier.
(cp_parser_omp_flush): Call finish_omp_flush.
* cp-tree.h (finish_omp_barrier, finish_omp_flush): New
prototypes.
PR c++/24734
* pt.c (tsubst_expr): Handle OMP_MASTER and OMP_ORDERED.
2005-11-03 Jakub Jelinek <jakub@redhat.com>
* semantics.c (finish_omp_threadprivate): Error on class-scope
variables.
2005-11-02 Jakub Jelinek <jakub@redhat.com>
* parser.c (cp_parser_omp_all_clauses): If some clause
type is not allowed, don't remove just one of the
clauses, but all clauses added in that loop round.
* semantics.c (finish_omp_clauses): Fix function
comment. Don't handle non-const or mutable specially,
as const and not mutable is predetermined shared and
that leads to double error. Don't ICE if copyin var is
PARM_DECL.
PR c++/24613
* parser.c (cp_parser_pragma): Diagnose
PRAGMA_OMP_SECTION outside of PRAGMA_OMP_SECTIONS
construct.
* semantics.c (finish_omp_threadprivate): Error if V
is automatic variable or has incomplete type.
2005-11-01 Diego Novillo <dnovillo@redhat.com>
* parser.c (cp_parser_omp_all_clauses): Use
OMP_CLAUSE_CHAIN instead of TREE_CHAIN.
2005-11-01 Diego Novillo <dnovillo@redhat.com>
* parser.c (cp_parser_omp_all_clauses): When emitting an
error message, remove the invalid clause from the list.
2005-10-31 Diego Novillo <dnovillo@redhat.com>
* parser.c (cp_parser_omp_parallel): Do not allow 'nowait' in
combined parallel+workshare directives.
2005-10-31 Richard Henderson <rth@redhat.com>
* cp-objcp-common.h (LANG_HOOKS_OMP_CLAUSE_DTOR):
Use cxx_omp_clause_dtor.
* cp-tree.h (CP_OMP_CLAUSE_INFO): New.
(cxx_omp_clause_dtor): New.
* cp-gimplify.c (cxx_omp_clause_apply_fn): New.
(cxx_omp_clause_default_ctor): Use it.
(cxx_omp_clause_copy_ctor, cxx_omp_clause_assign_op):
Likewise.
(cxx_omp_clause_dtor): New.
* semantics.c (finish_omp_clauses): Rewrite cdtor
checking to fill in CP_OMP_CLAUSE_INFO. Don't
specialcase LASTPRIVATE for removal.
(cxx_omp_clause_default_ctor, cxx_omp_clause_copy_ctor,
cxx_omp_clause_assign_op): Move to cp-gimplify.c.
2005-10-28 Jakub Jelinek <jakub@redhat.com>
* semantics.c (finish_omp_threadprivate): If
DECL_RTL_SET_P, call make_decl_rtl again so that
encode_section_info can update SYMBOL_REF's flags.
2005-10-26 Jakub Jelinek <jakub@redhat.com>
* semantics.c (finish_omp_for): Don't segfault if COND
or INCR is NULL. If not calling c_finish_omp_for
right away and one of COND and INCR is NULL, issue
error and don't expand anything.
PR c++/24512
* cp-tree.h (finish_omp_for): Add PRE_BODY argument.
* semantics.c (finish_omp_for): Likewise. Set
OMP_FOR_PRE_BODY to PRE_BODY if deferring, add it
into the current statement list if not processing
template decl or pass it to c_finish_omp_for.
* parser.c (cp_parser_omp_for_loop): Expand optional DECL_EXPRs
into PRE_BODY statement list. Pass it to finish_omp_for.
* pt.c (tsubst_expr) <case OMP_FOR>: tsubst_expr also
OMP_FOR_PRE_BODY into PRE_BODY stmt list, pass it to
finish_omp_for. Put all the statements into sk_omp
scope.
2005-10-25 Jakub Jelinek <jakub@redhat.com>
PR c++/24516
* parser.c (struct cp_parser): Rename in_iteration_statement
field to in_statement.
(IN_SWITCH_STMT, IN_ITERATION_STMT): Define.
(IN_OMP_BLOCK, IN_OMP_FOR): Change values.
(cp_parser_new, cp_parser_begin_omp_structured_block,
cp_parser_end_omp_structured_block,
cp_parser_omp_for_loop): Adjust for
in_iteration_statement renaming.
(cp_parser_selection_statement): Save
parser->in_iteration, or it temporarily with
IN_SWITCH_STMT for the
cp_parser_implicitly_scoped_statement call.
(cp_parser_iteration_statement): Adjust for
in_iteration_statement renaming. Use
IN_ITERATION_STMT rather than true.
(cp_parser_jump_statement): Adjust for
in_iteration_statement renaming and new values. Don't
error on break in a switch statement within OMP_FOR or
OpenMP structured block.
PR c++/24513
* parser.c (cp_parser_cache_group): Don't stop if next
token is CPP_PRAGMA_EOL and end is CPP_PRAGMA_EOL as
well. If current token is CPP_PRAGMA, consume
everything until CPP_PRAGMA_EOL inclusive.
2005-10-24 Jakub Jelinek <jakub@redhat.com>
PR c++/24502
* semantics.c (finish_omp_for): Handle MODOP_EXPR in
addition to MODIFY_EXPR.
2005-10-23 Richard Henderson <rth@redhat.com>
* cp-gimplify.c (struct cp_gimplify_ctx): Remove.
(bc_label): New.
(begin_bc_block, finish_bc_block): Use it.
(push_context, pop_context): Remove.
(cp_genericize): Don't use them. Assert bc_label is null.
* semantics.c (finish_omp_clauses): Create a fake data
element of TYPE for probing ctors.
2005-10-23 Richard Henderson <rth@redhat.com>
* cp-objcp-common.h (LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR): New.
(LANG_HOOKS_OMP_CLAUSE_COPY_CTOR): New.
(LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP): New.
(LANG_HOOKS_OMP_CLAUSE_DTOR): New.
* semantics.c (finish_omp_clauses): Look through
arrays when looking up special member calls. Also
remove FIRSTPRIVATE when LASTPRIVATE fails.
(cxx_omp_clause_default_ctor, cxx_omp_clause_copy_ctor): New.
(cxx_omp_clause_assign_op): New.
* cp-tree.h: Declare them.
2005-10-21 Richard Henderson <rth@redhat.com>
* decl.c (check_previous_goto_1): Return false if error.
(check_switch_goto): Likewise.
(finish_case_label): Don't emit the case label on error.
* parser.c (struct cp_parser): Revert
in_switch_statement_p changes.
(cp_parser_labeled_statement,
cp_parser_selection_statement): Likewise.
(cp_parser_begin_omp_structured_block): Don't save...
(cp_parser_end_omp_structured_block): or restore
in_switch_statement_p.
2005-10-21 Richard Henderson <rth@redhat.com>
* semantics.c (finish_omp_threadprivate): Set
decl_flags.u2sel when necessary.
2005-10-21 Richard Henderson <rth@redhat.com>
* decl.c (poplevel_named_label_1): Restore creation of the
bad_decls list.
(decl_jump_unsafe): Check for error_mark_node types.
(check_goto): Don't check cdtor_label. Don't use identify_goto. * semantics.c (finish_return_stmt): Do check_omp_return before
converting to cdtor_label goto.
2005-10-21 Richard Henderson <rth@redhat.com>
PR c++/24451
* decl.c (check_omp_return): Return false on error.
* cp-tree.h (check_omp_return): Update decl.
* semantics.c (finish_return_stmt): Avoid adding
return on error.
2005-10-21 Richard Henderson <rth@redhat.com>
* cp-tree.h (struct language_function): Remove
x_named_label_uses.
Change x_named_labels to a hashtable.
(check_omp_return): Declare.
* decl.c (struct named_label_use_entry): Rename from
named_label_use_list. Remove label_decl.
(struct named_label_entry): Rename from
named_label_list. Remove old_value and next. Change
in_try_scope and in_catch_scope to bool. Add
in_omp_scope.
(pop_labels_1): New.
(pop_labels): Use it.
(pop_local_label, poplevel_named_label_1): New.
(poplevel): Use them.
(named_label_entry_hash, named_label_entry_eq): New.
(make_label_decl): Create named_labels. Move label
creation bits from lookup_label.
(declare_local_label): Tidy.
(identify_goto): Split out from ...
(check_previous_goto_1): Add exited_omp argument.
Handle omp scopes.
(use_label): Merge into...
(check_goto): ... here. Handle omp scopes.
(check_omp_return): New.
(check_previous_gotos): Merge into...
(define_label): ... here.
(save_function_data): Remove x_named_label_uses reference.
(finish_function): Likewise.
* name-lookup.h (sk_omp): New.
* name-lookup.c (begin_scope): Handle it.
* parser.c (cp_parser_omp_for): Don't create extra
compound stmt.
(cp_parser_omp_sections): Likewise.
* semantics.c (finish_return_stmt): Call check_omp_return.
(begin_omp_structured_block): Use sk_omp.
(finish_omp_structured_block): Use do_poplevel. Don't build a
MUST_NOT_THROW expression here.
(begin_omp_parallel, finish_omp_parallel): Don't create extra
compound statements.
2005-10-21 Diego Novillo <dnovillo@redhat.com>
PR 24455
* cp/cp-tree.h (struct lang_decl_flags): Add field
threadprivate_p.
(CP_DECL_IS_THREADPRIVATE): Define.
* cp/semantics.c (finish_omp_threadprivate): Set. Do
not error out if CP_DECL_IS_THREADPRIVATE is set
already.
* cp/decl.c (duplicate_decls): Merge
CP_DECL_THREADPRIVATE_P.
2005-10-20 Richard Henderson <rth@redhat.com>
* cp-gimplify.c (cp_gimplify_omp_for): New.
(cp_gimplify_expr): Call it.
* cp-tree.h (OMP_FOR_GIMPLIFYING_P): New.
* parser.c (struct cp_parser): Rename
in_iteration_statement_p to in_iteration_statement and
change to unsigned char. Similarly with
in_switch_statement. Update all users.
(IN_OMP_BLOCK, IN_OMP_FOR): New.
(cp_parser_labeled_statement): Diagnose case labels
binding closer to an openmp block nested than the
switch.
(cp_parser_jump_statement): Diagnose break and
continue labels binding closer to an openmp block than
an iteration or switch.
(cp_parser_omp_for_loop): Mark in_iteration_statement
for an omp for.
(cp_parser_begin_omp_structured_block): New.
(cp_parser_end_omp_structured_block): New.
(cp_parser_omp_structured_block): Use them.
(cp_parser_omp_for, cp_parser_omp_sections_scope): Likewise.
(cp_parser_omp_parallel): Likewise.
2005-10-20 Richard Henderson <rth@redhat.com>
* semantics.c (begin_omp_structured_block): New.
(finish_omp_structured_block): New.
(begin_omp_parallel, finish_omp_parallel): Use them.
* parser.c (cp_parser_omp_structured_block): Likewise.
(cp_parser_omp_for): Likewise.
(cp_parser_omp_sections_scope): Likewise.
* cp-tree.h: Declare them.
2005-10-20 Richard Henderson <rth@redhat.com>
* parser.c (cp_parser_omp_master): Return the statement.
(cp_parser_omp_ordered): Likewise.
(cp_parser_omp_construct): Set the locus for them.
2005-10-19 Richard Henderson <rth@redhat.com>
* semantics.c (finish_omp_atomic): Revert to
uses_template_parms.
2005-10-19 Richard Henderson <rth@redhat.com>
* semantics.c (finish_omp_clauses): Avoid
DECL_THREAD_LOCAL_P on a PARM_DECL. Remove some
stub asserts guaranteed to fail.
2005-10-19 Richard Henderson <rth@redhat.com>
* cp-tree.h (OMP_ATOMIC_DEPENDENT_P, OMP_ATOMIC_CODE): New.
(finish_omp_clauses, finish_omp_for, finish_omp_atomic): New.
* parser.c (cp_parser_omp_clause_copyin): Remove.
(cp_parser_omp_all_clauses): Use cp_parser_omp_var_list instead. Call finish_omp_clauses.
(cp_parser_omp_clause_if): Don't do error checking here.
(cp_parser_omp_clause_num_threads): Likewise.
(cp_parser_omp_clause_schedule): Likewise.
(cp_parser_omp_atomic): Use finish_omp_atomic.
(cp_parser_omp_for_loop): Don't discard DECL_EXPR.
Don't decompose assignment statment here. Use
finish_omp_for.
* pt.c (tsubst_omp_clauses): New.
(tsubst_expr): Handle OMP_PARALLEL, OMP_FOR, OMP_SECTIONS,
OMP_SINGLE, OMP_SECTION, OMP_CRITICAL, OMP_ATOMIC.
* semantics.c (finish_omp_clauses): New.
(begin_omp_parallel, finish_omp_parallel): Know Less about the
internals of the stmt_list stack.
(finish_omp_for, finish_omp_atomic): New.
2005-10-18 Jakub Jelinek <jakub@redhat.com>
* semantics.c (cxx_omp_predetermined_sharing): New function.
* cp-tree.h (cxx_omp_predetermined_sharing): New prototype.
* cp-objcp-common.h
(LANG_HOOKS_OMP_PREDETERMINED_SHARING): Redefine.
2005-10-18 Richard Henderson <rth@redhat.com>
* parser.c (cp_parser_omp_single): Use make_node and accessors
instead of build.
2005-10-17 Richard Henderson <rth@redhat.com>
* parser.c (cp_parser_omp_for_loop): Handle declarations.
2005-10-12 Richard Henderson <rth@redhat.com>
* Make-lang.in (CXX_C_OBJS): Add c-omp.o.
* cp-tree.h (begin_omp_parallel, finish_omp_parallel): Declare.
(finish_omp_threadprivate): Declare.
* parser.c (struct cp_lexer): Add in_pragma.
(cp_lexer_consume_token): Don't consume a PRAGMA_EOL
when in_pragma.
(cp_parser_skip_to_closing_parenthesis): Stop at PRAGMA_EOL.
(cp_parser_skip_to_end_of_statement): Likewise.
(cp_parser_skip_to_end_of_block_or_statement): Likewise.
(cp_parser_skip_to_closing_brace): Likewise.
(cp_parser_skip_to_pragma_eol): Reset in_pragma.
(cp_parser_require_pragma_eol): New.
(cp_parser_statement): Add in_compound argument;
update all callers.
Restart if a non-statement pragma seen outside a
compound.
(cp_parser_statement_seq_opt): Stop at PRAGMA_EOL.
(cp_parser_declaration_seq_opt): Likewise.
(cp_parser_member_specification_opt): Likewise.
(cp_parser_function_definition_after_decl): Likewise.
(cp_parser_skip_until_found): Likewise.
(cp_parser_cache_group): Likewise.
(enum pragma_omp_clause, cp_parser_omp_clause_name,
check_no_duplicate_clause,
cp_parser_omp_var_list_no_open,
cp_parser_omp_var_list, cp_parser_omp_clause_copyin,
cp_parser_omp_clause_default, cp_parser_omp_clause_if,
cp_parser_omp_clause_nowait,
cp_parser_omp_clause_num_threads,
cp_parser_omp_clause_ordered,
cp_parser_omp_clause_reduction,
cp_parser_omp_clause_schedule,
cp_parser_omp_all_clauses,
cp_parser_omp_structured_block, cp_parser_omp_atomic,
cp_parser_omp_barrier, cp_parser_omp_critical,
cp_parser_omp_flush, cp_parser_omp_for_loop,
cp_parser_omp_for, cp_parser_omp_master,
cp_parser_omp_ordered, cp_parser_omp_sections_scope,
cp_parser_omp_sections, cp_parser_omp_parallel,
cp_parser_omp_single, cp_parser_omp_threadprivate,
cp_parser_omp_construct): New.
(cp_parser_pragma): Handle OpenMP pragmas.
* semantics.c (finish_omp_threadprivate): New.
(begin_omp_parallel, finish_omp_parallel): New.
2005-10-11 Richard Henderson <rth@redhat.com>
* parser.c (struct cp_token): Add pragma_kind.
(eof_token): Initialize it.
(cp_lexer_handle_pragma): Remove.
(cp_parser_initial_pragma): New.
(cp_lexer_new_main): Use it.
(cp_lexer_get_preprocessor_token): Initialize pragma_kind.
(cp_lexer_print_token): Don't handle CPP_PRAGMA.
(cp_parser_skip_to_pragma_eol): New.
(cp_parser_error): Use it.
(pragma_lex): New.
2005-10-09 Richard Henderson <rth@redhat.com>
* lex.c (parse_strconst_pragma): Update for c_lex name change.
(handle_pragma_java_exceptions): Likewise.
* parser.c (cp_lexer_new_main): Likewise.
2005-10-06 Richard Henderson <rth@redhat.com>
* parser.c (cp_lexer_new_main): Comment out defer_pragmas.
(cp_lexer_handle_pragma): Comment out
cpp_handle_deferred_pragma.
2005-10-01 Richard Henderson <rth@redhat.com>
* name-lookup.c (lookup_name): Remove prefer_type argument.
(lookup_name_prefer_type): New function.
* name-lookup.h (lookup_name_prefer_type): Declare it.
* decl.c (lookup_and_check_tag): Use it.
* pt.c (tsubst_friend_class): Likewise. Update for
lookup_name change.
(lookup_template_class, tsubst_copy_and_build): Likewise.
2006-03-06 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c++/15759
@ -27,7 +476,7 @@
PR c++/26291
* decl.c (grok_op_properties): Check for ellipsis in arguments of
operators.
operators.
2006-02-20 Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
@ -443,10 +892,10 @@
2006-01-20 Dirk Mueller <dmueller@suse.com>
PR c++/5520
* semantics.c (finish_if_stmt): Call empty_body_warning.
* parser.c (cp_parser_implicitly_scoped_statement):
Mark empty statement with an empty stmt.
PR c++/5520
* semantics.c (finish_if_stmt): Call empty_body_warning.
* parser.c (cp_parser_implicitly_scoped_statement):
Mark empty statement with an empty stmt.
2006-01-19 Mark Mitchell <mark@codesourcery.com>
@ -572,8 +1021,8 @@
2006-01-04 Chris Lattner <sabre@gnu.org>
* typeck2.c: update copyright to 2006
(split_nonconstant_init_1): Set TREE_CONSTANT to true.
* typeck2.c: update copyright to 2006
(split_nonconstant_init_1): Set TREE_CONSTANT to true.
2006-01-04 Mark Mitchell <mark@codesourcery.com>
@ -814,7 +1263,7 @@
2005-12-06 Aldy Hernandez <aldyh@redhat.com>
PR C++/24138
* decl.c (reshape_init_array_1): Handle max_index of -1.
* decl.c (reshape_init_array_1): Handle max_index of -1.
2005-12-06 Roger Sayle <roger@eyesopen.com>
@ -1479,7 +1928,7 @@
2005-10-10 Giovanni Bajo <giovannibajo@gcc.gnu.org>
Mark Mitchell <mark@codesourcery.com>
PR c++/23437
PR c++/23437
* parser.c (cp_parser_template_argument_list): Do not treat
contents of argument list as part of a constant expression.
@ -1977,27 +2426,27 @@
2005-08-15 Fariborz Jahanian <fjahanian@apple.com>
* cp-tree.h (can_convert_arg, fn_type_unification): New argument.
* call.c (add_template_candidate_real): Pass down 'flags' to
fn_type_unification.
(can_convert_arg): New 'flags' argument. Pass it to call to
implicit_conversion instead of LOOKUP_NORMAL.
* cp-tree.h (can_convert_arg, fn_type_unification): New argument.
* call.c (add_template_candidate_real): Pass down 'flags' to
fn_type_unification.
(can_convert_arg): New 'flags' argument. Pass it to call to
implicit_conversion instead of LOOKUP_NORMAL.
(can_convert): Add LOOKUP_NORMAL to call to can_convert_arg.
* class.c (resolve_address_of_overloaded_function): Ditto.
(resolve_address_of_overloaded_function): Ditto.
* decl.c (reshape_init, check_default_argument): Ditto.
* typeck.c (build_ptrmemfunc): Ditto.
* pt.c (type_unification_real): Add 'flags' argument.
(fn_type_unification): Pass 'flags' to type_unification_real.
(type_unification_real): Pass new 'flags' argument to call to
can_convert_arg.
* class.c (resolve_address_of_overloaded_function): Ditto.
(resolve_address_of_overloaded_function): Ditto.
* decl.c (reshape_init, check_default_argument): Ditto.
* typeck.c (build_ptrmemfunc): Ditto.
* pt.c (type_unification_real): Add 'flags' argument.
(fn_type_unification): Pass 'flags' to type_unification_real.
(type_unification_real): Pass new 'flags' argument to call to
can_convert_arg.
2005-08-12 Giovanni Bajo <giovannibajo@libero.it>
Nathan Sidwell <nathan@codesourcery.com>
PR c++/21799
PR c++/8271
* pt.c (unify) <METHOD_TYPE>: Check this-pointer cv-qualifiers
* pt.c (unify) <METHOD_TYPE>: Check this-pointer cv-qualifiers
explicitly.
2005-08-12 Nathan Sidwell <nathan@codesourcery.com>
@ -2327,7 +2776,7 @@
diagnostics.
2005-07-02 Zack Weinberg <zack@codesourcery.com>
Joseph S. Myers <joseph@codesourcery.com>
Joseph S. Myers <joseph@codesourcery.com>
* error.c (location_of): Add comment.
(locate_error, cp_error_at, cp_warning_at, cp_pedwarn_at): Remove.

View File

@ -75,7 +75,7 @@ g++-cross$(exeext): g++$(exeext)
CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o \
c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \
c-gimplify.o tree-inline.o
c-gimplify.o c-omp.o tree-inline.o
# Language-specific object files for C++ and Objective C++.
CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \

View File

@ -37,30 +37,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
enum bc_t { bc_break = 0, bc_continue = 1 };
static struct cp_gimplify_ctx
{
/* Stack of labels which are targets for "break" or "continue",
linked through TREE_CHAIN. */
tree current_label[2];
} *ctxp;
static void
push_context (void)
{
gcc_assert (!ctxp);
ctxp = ((struct cp_gimplify_ctx *)
xcalloc (1, sizeof (struct cp_gimplify_ctx)));
}
static void
pop_context (void)
{
gcc_assert (ctxp
&& !ctxp->current_label[0]
&& !ctxp->current_label[1]);
free (ctxp);
ctxp = NULL;
}
/* Stack of labels which are targets for "break" or "continue",
linked through TREE_CHAIN. */
static tree bc_label[2];
/* Begin a scope which can be exited by a break or continue statement. BC
indicates which.
@ -71,8 +50,8 @@ static tree
begin_bc_block (enum bc_t bc)
{
tree label = create_artificial_label ();
TREE_CHAIN (label) = ctxp->current_label[bc];
ctxp->current_label[bc] = label;
TREE_CHAIN (label) = bc_label[bc];
bc_label[bc] = label;
return label;
}
@ -86,7 +65,7 @@ begin_bc_block (enum bc_t bc)
static tree
finish_bc_block (enum bc_t bc, tree label, tree body)
{
gcc_assert (label == ctxp->current_label[bc]);
gcc_assert (label == bc_label[bc]);
if (TREE_USED (label))
{
@ -99,7 +78,7 @@ finish_bc_block (enum bc_t bc, tree label, tree body)
body = sl;
}
ctxp->current_label[bc] = TREE_CHAIN (label);
bc_label[bc] = TREE_CHAIN (label);
TREE_CHAIN (label) = NULL_TREE;
return body;
}
@ -110,7 +89,7 @@ finish_bc_block (enum bc_t bc, tree label, tree body)
static tree
build_bc_goto (enum bc_t bc)
{
tree label = ctxp->current_label[bc];
tree label = bc_label[bc];
if (label == NULL_TREE)
{
@ -338,6 +317,36 @@ gimplify_switch_stmt (tree *stmt_p)
*stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
}
/* Hook into the middle of gimplifying an OMP_FOR node. This is required
in order to properly gimplify CONTINUE statements. Here we merely
manage the continue stack; the rest of the job is performed by the
regular gimplifier. */
static enum gimplify_status
cp_gimplify_omp_for (tree *expr_p)
{
tree for_stmt = *expr_p;
tree cont_block;
/* Protect ourselves from recursion. */
if (OMP_FOR_GIMPLIFYING_P (for_stmt))
return GS_UNHANDLED;
OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
/* Note that while technically the continue label is enabled too soon
here, we should have already diagnosed invalid continues nested within
statement expressions within the INIT, COND, or INCR expressions. */
cont_block = begin_bc_block (bc_continue);
gimplify_stmt (expr_p);
OMP_FOR_BODY (for_stmt)
= finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt));
OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
return GS_ALL_DONE;
}
/* Gimplify an EXPR_STMT node. */
static void
@ -543,6 +552,10 @@ cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
ret = GS_ALL_DONE;
break;
case OMP_FOR:
ret = cp_gimplify_omp_for (expr_p);
break;
case CONTINUE_STMT:
*expr_p = build_bc_goto (bc_continue);
ret = GS_ALL_DONE;
@ -686,7 +699,157 @@ cp_genericize (tree fndecl)
pointer_set_destroy (p_set);
/* Do everything else. */
push_context ();
c_genericize (fndecl);
pop_context ();
gcc_assert (bc_label[bc_break] == NULL);
gcc_assert (bc_label[bc_continue] == NULL);
}
/* Build code to apply FN to each member of ARG1 and ARG2. FN may be
NULL if there is in fact nothing to do. ARG2 may be null if FN
actually only takes one argument. */
static tree
cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
{
if (fn == NULL)
return NULL;
if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
{
tree inner_type = TREE_TYPE (arg1);
tree start1, end1, p1;
tree start2 = NULL, p2 = NULL;
tree ret = NULL, lab, t;
start1 = arg1;
start2 = arg2;
do
{
inner_type = TREE_TYPE (inner_type);
start1 = build4 (ARRAY_REF, inner_type, start1,
size_zero_node, NULL, NULL);
if (arg2)
start2 = build4 (ARRAY_REF, inner_type, start2,
size_zero_node, NULL, NULL);
}
while (TREE_CODE (inner_type) == ARRAY_TYPE);
start1 = build_fold_addr_expr (start1);
if (arg2)
start2 = build_fold_addr_expr (start2);
end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
end1 = fold_convert (TREE_TYPE (start1), end1);
end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
p1 = create_tmp_var (TREE_TYPE (start1), NULL);
t = build2 (MODIFY_EXPR, void_type_node, p1, start1);
append_to_statement_list (t, &ret);
if (arg2)
{
p2 = create_tmp_var (TREE_TYPE (start2), NULL);
t = build2 (MODIFY_EXPR, void_type_node, p2, start2);
append_to_statement_list (t, &ret);
}
lab = create_artificial_label ();
t = build1 (LABEL_EXPR, void_type_node, lab);
append_to_statement_list (t, &ret);
t = NULL;
if (arg2)
t = tree_cons (NULL, p2, t);
t = tree_cons (NULL, p1, t);
t = build_call (fn, t);
append_to_statement_list (t, &ret);
t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
t = build2 (MODIFY_EXPR, void_type_node, p1, t);
append_to_statement_list (t, &ret);
if (arg2)
{
t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
t = build2 (MODIFY_EXPR, void_type_node, p2, t);
append_to_statement_list (t, &ret);
}
t = build2 (NE_EXPR, boolean_type_node, p1, end1);
t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
append_to_statement_list (t, &ret);
return ret;
}
else
{
tree t = NULL;
if (arg2)
t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
t = tree_cons (NULL, build_fold_addr_expr (arg1), t);
return build_call (fn, t);
}
}
/* Return code to initialize DECL with its default constructor, or
NULL if there's nothing to do. */
tree
cxx_omp_clause_default_ctor (tree clause, tree decl)
{
tree info = CP_OMP_CLAUSE_INFO (clause);
tree ret = NULL;
if (info)
ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
return ret;
}
/* Return code to initialize DST with a copy constructor from SRC. */
tree
cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
{
tree info = CP_OMP_CLAUSE_INFO (clause);
tree ret = NULL;
if (info)
ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
if (ret == NULL)
ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
return ret;
}
/* Similarly, except use an assignment operator instead. */
tree
cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
{
tree info = CP_OMP_CLAUSE_INFO (clause);
tree ret = NULL;
if (info)
ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
if (ret == NULL)
ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
return ret;
}
/* Return code to destroy DECL. */
tree
cxx_omp_clause_dtor (tree clause, tree decl)
{
tree info = CP_OMP_CLAUSE_INFO (clause);
tree ret = NULL;
if (info)
ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
return ret;
}

View File

@ -151,5 +151,15 @@ extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
#define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
#undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
#undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
#define LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR cxx_omp_clause_default_ctor
#undef LANG_HOOKS_OMP_CLAUSE_COPY_CTOR
#define LANG_HOOKS_OMP_CLAUSE_COPY_CTOR cxx_omp_clause_copy_ctor
#undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP
#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP cxx_omp_clause_assign_op
#undef LANG_HOOKS_OMP_CLAUSE_DTOR
#define LANG_HOOKS_OMP_CLAUSE_DTOR cxx_omp_clause_dtor
#endif /* GCC_CP_OBJCP_COMMON */

View File

@ -52,6 +52,8 @@ struct diagnostic_context;
TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
REFERENCE_REF_P (in INDIRECT_EXPR)
QUALIFIED_NAME_IS_TEMPLATE (in SCOPE_REF)
OMP_ATOMIC_DEPENDENT_P (in OMP_ATOMIC)
OMP_FOR_GIMPLIFYING_P (in OMP_FOR)
BASELINK_QUALIFIED_P (in BASELINK)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
@ -742,8 +744,7 @@ struct language_function GTY(())
/* True if this function can throw an exception. */
BOOL_BITFIELD can_throw : 1;
struct named_label_use_list *x_named_label_uses;
struct named_label_list *x_named_labels;
htab_t GTY((param_is(struct named_label_entry))) x_named_labels;
struct cp_binding_level *bindings;
VEC(tree,gc) *x_local_names;
};
@ -1521,7 +1522,8 @@ struct lang_decl_flags GTY(())
unsigned this_thunk_p : 1;
unsigned repo_available_p : 1;
unsigned hidden_friend_p : 1;
unsigned dummy : 2;
unsigned threadprivate_p : 1;
/* One unused bit. */
union lang_decl_u {
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
@ -2348,6 +2350,11 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define DECL_HIDDEN_FRIEND_P(NODE) \
(DECL_LANG_SPECIFIC (DECL_COMMON_CHECK (NODE))->decl_flags.hidden_friend_p)
/* Nonzero if DECL has been declared threadprivate by
#pragma omp threadprivate. */
#define CP_DECL_THREADPRIVATE_P(DECL) \
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (DECL))->decl_flags.threadprivate_p)
/* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
@ -2947,6 +2954,26 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define QUALIFIED_NAME_IS_TEMPLATE(NODE) \
(TREE_LANG_FLAG_0 (SCOPE_REF_CHECK (NODE)))
/* True for an OMP_ATOMIC that has dependent parameters. These are stored
as bare LHS/RHS, and not as ADDR/RHS, as in the generic statement. */
#define OMP_ATOMIC_DEPENDENT_P(NODE) \
(TREE_LANG_FLAG_0 (OMP_ATOMIC_CHECK (NODE)))
/* Used to store the operation code when OMP_ATOMIC_DEPENDENT_P is set. */
#define OMP_ATOMIC_CODE(NODE) \
(OMP_ATOMIC_CHECK (NODE)->exp.complexity)
/* Used while gimplifying continue statements bound to OMP_FOR nodes. */
#define OMP_FOR_GIMPLIFYING_P(NODE) \
(TREE_LANG_FLAG_0 (OMP_FOR_CHECK (NODE)))
/* A language-specific token attached to the OpenMP data clauses to
hold code (or code fragments) related to ctors, dtors, and op=.
See semantics.c for details. */
#define CP_OMP_CLAUSE_INFO(NODE) \
TREE_TYPE (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_PRIVATE, \
OMP_CLAUSE_COPYPRIVATE))
/* These macros provide convenient access to the various _STMT nodes
created when parsing template declarations. */
#define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
@ -3782,12 +3809,12 @@ extern tree pushtag (tree, tree, tag_scope);
extern tree make_anon_name (void);
extern int decls_match (tree, tree);
extern tree duplicate_decls (tree, tree, bool);
extern tree pushdecl_top_level (tree);
extern tree pushdecl_top_level_maybe_friend (tree, bool);
extern tree pushdecl_top_level_and_finish (tree, tree);
extern tree declare_local_label (tree);
extern tree define_label (location_t, tree);
extern void check_goto (tree);
extern bool check_omp_return (void);
extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t);
extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
extern tree check_for_out_of_scope_variable (tree);
@ -4216,6 +4243,22 @@ extern tree finish_qualified_id_expr (tree, tree, bool, bool,
extern void simplify_aggr_init_expr (tree *);
extern void finalize_nrv (tree *, tree, tree);
extern void note_decl_for_pch (tree);
extern tree finish_omp_clauses (tree);
extern void finish_omp_threadprivate (tree);
extern tree begin_omp_structured_block (void);
extern tree finish_omp_structured_block (tree);
extern tree begin_omp_parallel (void);
extern tree finish_omp_parallel (tree, tree);
extern tree finish_omp_for (location_t, tree, tree,
tree, tree, tree, tree);
extern void finish_omp_atomic (enum tree_code, tree, tree);
extern void finish_omp_barrier (void);
extern void finish_omp_flush (void);
extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree);
extern tree cxx_omp_clause_default_ctor (tree, tree);
extern tree cxx_omp_clause_copy_ctor (tree, tree, tree);
extern tree cxx_omp_clause_assign_op (tree, tree, tree);
extern tree cxx_omp_clause_dtor (tree, tree);
/* in tree.c */
extern void lang_check_failed (const char *, int,

View File

@ -80,15 +80,6 @@ static tree record_builtin_java_type (const char *, int);
static const char *tag_name (enum tag_types);
static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool);
static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
static tree make_label_decl (tree, int);
static void use_label (tree);
static void check_previous_goto_1 (tree, struct cp_binding_level *, tree,
const location_t *);
static void check_previous_goto (struct named_label_use_list *);
static void check_switch_goto (struct cp_binding_level *);
static void check_previous_gotos (tree);
static void pop_label (tree, tree);
static void pop_labels (tree);
static void maybe_deduce_size_from_array_init (tree, tree);
static void layout_var_decl (tree);
static void maybe_commonize_var (tree);
@ -167,20 +158,6 @@ tree global_type_node;
/* The node that holds the "name" of the global scope. */
tree global_scope_name;
/* Used only for jumps to as-yet undefined labels, since jumps to
defined labels can have their validity checked immediately. */
struct named_label_use_list GTY(())
{
struct cp_binding_level *binding_level;
tree names_in_scope;
tree label_decl;
location_t o_goto_locus;
struct named_label_use_list *next;
};
#define named_label_uses cp_function_chain->x_named_label_uses
#define local_names cp_function_chain->x_local_names
/* A list of objects which have constructors or destructors
@ -195,20 +172,58 @@ tree static_aggregates;
tree integer_two_node, integer_three_node;
/* Used only for jumps to as-yet undefined labels, since jumps to
defined labels can have their validity checked immediately. */
struct named_label_use_entry GTY(())
{
struct named_label_use_entry *next;
/* The binding level to which this entry is *currently* attached.
This is initially the binding level in which the goto appeared,
but is modified as scopes are closed. */
struct cp_binding_level *binding_level;
/* The head of the names list that was current when the goto appeared,
or the inner scope popped. These are the decls that will *not* be
skipped when jumping to the label. */
tree names_in_scope;
/* The location of the goto, for error reporting. */
location_t o_goto_locus;
/* True if an OpenMP structured block scope has been closed since
the goto appeared. This means that the branch from the label will
illegally exit an OpenMP scope. */
bool in_omp_scope;
};
/* A list of all LABEL_DECLs in the function that have names. Here so
we can clear out their names' definitions at the end of the
function, and so we can check the validity of jumps to these labels. */
struct named_label_list GTY(())
struct named_label_entry GTY(())
{
struct cp_binding_level *binding_level;
tree names_in_scope;
tree old_value;
/* The decl itself. */
tree label_decl;
/* The binding level to which the label is *currently* attached.
This is initially set to the binding level in which the label
is defined, but is modified as scopes are closed. */
struct cp_binding_level *binding_level;
/* The head of the names list that was current when the label was
defined, or the inner scope popped. These are the decls that will
be skipped when jumping to the label. */
tree names_in_scope;
/* A tree list of all decls from all binding levels that would be
crossed by a backward branch to the label. */
tree bad_decls;
struct named_label_list *next;
unsigned int in_try_scope : 1;
unsigned int in_catch_scope : 1;
/* A list of uses of the label, before the label is defined. */
struct named_label_use_entry *uses;
/* The following bits are set after the label is defined, and are
updated as scopes are popped. They indicate that a backward jump
to the label will illegally enter a scope of the given flavour. */
bool in_try_scope;
bool in_catch_scope;
bool in_omp_scope;
};
#define named_labels cp_function_chain->x_named_labels
@ -372,23 +387,47 @@ pop_label (tree label, tree old_value)
go out of scope. BLOCK is the top-level block for the
function. */
static int
pop_labels_1 (void **slot, void *data)
{
struct named_label_entry *ent = (struct named_label_entry *) *slot;
tree block = (tree) data;
pop_label (ent->label_decl, NULL_TREE);
/* Put the labels into the "variables" of the top-level block,
so debugger can see them. */
TREE_CHAIN (ent->label_decl) = BLOCK_VARS (block);
BLOCK_VARS (block) = ent->label_decl;
htab_clear_slot (named_labels, slot);
return 1;
}
static void
pop_labels (tree block)
{
struct named_label_list *link;
/* Clear out the definitions of all label names, since their scopes
end here. */
for (link = named_labels; link; link = link->next)
if (named_labels)
{
pop_label (link->label_decl, link->old_value);
/* Put the labels into the "variables" of the top-level block,
so debugger can see them. */
TREE_CHAIN (link->label_decl) = BLOCK_VARS (block);
BLOCK_VARS (block) = link->label_decl;
htab_traverse (named_labels, pop_labels_1, block);
named_labels = NULL;
}
}
named_labels = NULL;
/* At the end of a block with local labels, restore the outer definition. */
static void
pop_local_label (tree label, tree old_value)
{
struct named_label_entry dummy;
void **slot;
pop_label (label, old_value);
dummy.label_decl = label;
slot = htab_find_slot (named_labels, &dummy, NO_INSERT);
htab_clear_slot (named_labels, slot);
}
/* The following two routines are used to interface to Objective-C++.
@ -426,6 +465,57 @@ objc_mark_locals_volatile (void *enclosing_blk)
}
}
/* Update data for defined and undefined labels when leaving a scope. */
static int
poplevel_named_label_1 (void **slot, void *data)
{
struct named_label_entry *ent = (struct named_label_entry *) *slot;
struct cp_binding_level *bl = (struct cp_binding_level *) data;
struct cp_binding_level *obl = bl->level_chain;
if (ent->binding_level == bl)
{
tree decl;
for (decl = ent->names_in_scope; decl; decl = TREE_CHAIN (decl))
if (decl_jump_unsafe (decl))
ent->bad_decls = tree_cons (NULL, decl, ent->bad_decls);
ent->binding_level = obl;
ent->names_in_scope = obl->names;
switch (bl->kind)
{
case sk_try:
ent->in_try_scope = true;
break;
case sk_catch:
ent->in_catch_scope = true;
break;
case sk_omp:
ent->in_omp_scope = true;
break;
default:
break;
}
}
else if (ent->uses)
{
struct named_label_use_entry *use;
for (use = ent->uses; use ; use = use->next)
if (use->binding_level == bl)
{
use->binding_level = obl;
use->names_in_scope = obl->names;
if (bl->kind == sk_omp)
use->in_omp_scope = true;
}
}
return 1;
}
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
@ -480,39 +570,9 @@ poplevel (int keep, int reverse, int functionbody)
/* Any uses of undefined labels, and any defined labels, now operate
under constraints of next binding contour. */
if (cfun && !functionbody)
{
struct cp_binding_level *level_chain;
level_chain = current_binding_level->level_chain;
if (level_chain)
{
struct named_label_use_list *uses;
struct named_label_list *labels;
for (labels = named_labels; labels; labels = labels->next)
if (labels->binding_level == current_binding_level)
{
tree decl;
if (current_binding_level->kind == sk_try)
labels->in_try_scope = 1;
if (current_binding_level->kind == sk_catch)
labels->in_catch_scope = 1;
for (decl = labels->names_in_scope; decl;
decl = TREE_CHAIN (decl))
if (decl_jump_unsafe (decl))
labels->bad_decls = tree_cons (NULL_TREE, decl,
labels->bad_decls);
labels->binding_level = level_chain;
labels->names_in_scope = level_chain->names;
}
for (uses = named_label_uses; uses; uses = uses->next)
if (uses->binding_level == current_binding_level)
{
uses->binding_level = level_chain;
uses->names_in_scope = level_chain->names;
}
}
}
if (cfun && !functionbody && named_labels)
htab_traverse (named_labels, poplevel_named_label_1,
current_binding_level);
/* Get the decls in the order they were written.
Usually current_binding_level->names is in reverse order.
@ -660,7 +720,7 @@ poplevel (int keep, int reverse, int functionbody)
for (link = current_binding_level->shadowed_labels;
link;
link = TREE_CHAIN (link))
pop_label (TREE_VALUE (link), TREE_PURPOSE (link));
pop_local_label (TREE_VALUE (link), TREE_PURPOSE (link));
/* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
list if a `using' declaration put them there. The debugging
@ -1585,6 +1645,18 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
|= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
/* Merge the threadprivate attribute from OLDDECL into NEWDECL. */
if (DECL_LANG_SPECIFIC (olddecl)
&& CP_DECL_THREADPRIVATE_P (olddecl))
{
/* Allocate a LANG_SPECIFIC structure for NEWDECL, if needed. */
if (!DECL_LANG_SPECIFIC (newdecl))
retrofit_lang_decl (newdecl);
DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl);
CP_DECL_THREADPRIVATE_P (newdecl) = 1;
}
}
/* Do this after calling `merge_types' so that default
@ -2039,7 +2111,10 @@ redeclaration_error_message (tree newdecl, tree olddecl)
return NULL;
}
else if (TREE_CODE (newdecl) == VAR_DECL
&& DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl))
&& DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)
&& (! DECL_LANG_SPECIFIC (olddecl)
|| ! CP_DECL_THREADPRIVATE_P (olddecl)
|| DECL_THREAD_LOCAL_P (newdecl)))
{
/* Only variables can be thread-local, and all declarations must
agree on this property. */
@ -2070,11 +2145,30 @@ redeclaration_error_message (tree newdecl, tree olddecl)
}
}
/* Hash and equality functions for the named_label table. */
static hashval_t
named_label_entry_hash (const void *data)
{
const struct named_label_entry *ent = (const struct named_label_entry *) data;
return DECL_UID (ent->label_decl);
}
static int
named_label_entry_eq (const void *a, const void *b)
{
const struct named_label_entry *ent_a = (const struct named_label_entry *) a;
const struct named_label_entry *ent_b = (const struct named_label_entry *) b;
return ent_a->label_decl == ent_b->label_decl;
}
/* Create a new label, named ID. */
static tree
make_label_decl (tree id, int local_p)
{
struct named_label_entry *ent;
void **slot;
tree decl;
decl = build_decl (LABEL_DECL, id, void_type_node);
@ -2090,32 +2184,24 @@ make_label_decl (tree id, int local_p)
/* Record the fact that this identifier is bound to this label. */
SET_IDENTIFIER_LABEL_VALUE (id, decl);
/* Create the label htab for the function on demand. */
if (!named_labels)
named_labels = htab_create_ggc (13, named_label_entry_hash,
named_label_entry_eq, NULL);
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
IDENTIFIER_LABEL_VALUE before the new label is declared. */
ent = GGC_CNEW (struct named_label_entry);
ent->label_decl = decl;
slot = htab_find_slot (named_labels, ent, INSERT);
gcc_assert (*slot == NULL);
*slot = ent;
return decl;
}
/* Record this label on the list of used labels so that we can check
at the end of the function to see whether or not the label was
actually defined, and so we can check when the label is defined whether
this use is valid. */
static void
use_label (tree decl)
{
if (named_label_uses == NULL
|| named_label_uses->names_in_scope != current_binding_level->names
|| named_label_uses->label_decl != decl)
{
struct named_label_use_list *new_ent;
new_ent = GGC_NEW (struct named_label_use_list);
new_ent->label_decl = decl;
new_ent->names_in_scope = current_binding_level->names;
new_ent->binding_level = current_binding_level;
new_ent->o_goto_locus = input_location;
new_ent->next = named_label_uses;
named_label_uses = new_ent;
}
}
/* Look for a label named ID in the current function. If one cannot
be found, create one. (We keep track of used, but undefined,
labels, and complain about them at the end of a function.) */
@ -2124,7 +2210,6 @@ tree
lookup_label (tree id)
{
tree decl;
struct named_label_list *ent;
timevar_push (TV_NAME_LOOKUP);
/* You can't use labels at global scope. */
@ -2139,20 +2224,7 @@ lookup_label (tree id)
if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
IDENTIFIER_LABEL_VALUE before the new label is declared. */
ent = GGC_CNEW (struct named_label_list);
ent->old_value = IDENTIFIER_LABEL_VALUE (id);
ent->next = named_labels;
named_labels = ent;
/* We need a new label. */
decl = make_label_decl (id, /*local_p=*/0);
/* Now fill in the information we didn't have before. */
ent->label_decl = decl;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
@ -2161,18 +2233,16 @@ lookup_label (tree id)
tree
declare_local_label (tree id)
{
tree decl;
tree decl, shadow;
/* Add a new entry to the SHADOWED_LABELS list so that when we leave
this scope we can restore the old value of
IDENTIFIER_TYPE_VALUE. */
current_binding_level->shadowed_labels
= tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
current_binding_level->shadowed_labels);
/* Look for the label. */
this scope we can restore the old value of IDENTIFIER_TYPE_VALUE. */
shadow = tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
current_binding_level->shadowed_labels);
current_binding_level->shadowed_labels = shadow;
decl = make_label_decl (id, /*local_p=*/1);
/* Now fill in the information we didn't have before. */
TREE_VALUE (current_binding_level->shadowed_labels) = decl;
TREE_VALUE (shadow) = decl;
return decl;
}
@ -2199,42 +2269,55 @@ decl_jump_unsafe (tree decl)
return 1;
}
/* A subroutine of check_previous_goto_1 to identify a branch to the user. */
static void
identify_goto (tree decl, const location_t *locus)
{
if (decl)
pedwarn ("jump to label %qD", decl);
else
pedwarn ("jump to case label");
if (locus)
pedwarn ("%H from here", locus);
}
/* Check that a single previously seen jump to a newly defined label
is OK. DECL is the LABEL_DECL or 0; LEVEL is the binding_level for
the jump context; NAMES are the names in scope in LEVEL at the jump
context; FILE and LINE are the source position of the jump or 0. */
context; LOCUS is the source position of the jump or 0. Returns
true if all is well. */
static void
check_previous_goto_1 (tree decl,
struct cp_binding_level* level,
tree names, const location_t *locus)
static bool
check_previous_goto_1 (tree decl, struct cp_binding_level* level, tree names,
bool exited_omp, const location_t *locus)
{
int identified = 0;
int saw_eh = 0;
struct cp_binding_level *b = current_binding_level;
for (; b; b = b->level_chain)
struct cp_binding_level *b;
bool identified = false, saw_eh = false, saw_omp = false;
if (exited_omp)
{
tree new_decls = b->names;
tree old_decls = (b == level ? names : NULL_TREE);
for (; new_decls != old_decls;
identify_goto (decl, locus);
error (" exits OpenMP structured block");
identified = saw_omp = true;
}
for (b = current_binding_level; b ; b = b->level_chain)
{
tree new_decls, old_decls = (b == level ? names : NULL_TREE);
for (new_decls = b->names; new_decls != old_decls;
new_decls = TREE_CHAIN (new_decls))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
continue;
if (! identified)
if (!identified)
{
if (decl)
pedwarn ("jump to label %qD", decl);
else
pedwarn ("jump to case label");
if (locus)
pedwarn ("%H from here", locus);
identified = 1;
identify_goto (decl, locus);
identified = true;
}
if (problem > 1)
error (" crosses initialization of %q+#D", new_decls);
else
@ -2243,63 +2326,46 @@ check_previous_goto_1 (tree decl,
if (b == level)
break;
if ((b->kind == sk_try || b->kind == sk_catch) && ! saw_eh)
if ((b->kind == sk_try || b->kind == sk_catch) && !saw_eh)
{
if (! identified)
if (!identified)
{
if (decl)
pedwarn ("jump to label %qD", decl);
else
pedwarn ("jump to case label");
if (locus)
pedwarn ("%H from here", locus);
identified = 1;
identify_goto (decl, locus);
identified = true;
}
if (b->kind == sk_try)
error (" enters try block");
else
error (" enters catch block");
saw_eh = 1;
saw_eh = true;
}
if (b->kind == sk_omp && !saw_omp)
{
if (!identified)
{
identify_goto (decl, locus);
identified = true;
}
error (" enters OpenMP structured block");
saw_omp = true;
}
}
return !identified;
}
static void
check_previous_goto (struct named_label_use_list* use)
check_previous_goto (tree decl, struct named_label_use_entry *use)
{
check_previous_goto_1 (use->label_decl, use->binding_level,
use->names_in_scope, &use->o_goto_locus);
check_previous_goto_1 (decl, use->binding_level,
use->names_in_scope, use->in_omp_scope,
&use->o_goto_locus);
}
static void
static bool
check_switch_goto (struct cp_binding_level* level)
{
check_previous_goto_1 (NULL_TREE, level, level->names, NULL);
}
/* Check that any previously seen jumps to a newly defined label DECL
are OK. Called by define_label. */
static void
check_previous_gotos (tree decl)
{
struct named_label_use_list **usep;
if (! TREE_USED (decl))
return;
for (usep = &named_label_uses; *usep; )
{
struct named_label_use_list *use = *usep;
if (use->label_decl == decl)
{
check_previous_goto (use);
*usep = use->next;
}
else
usep = &(use->next);
}
return check_previous_goto_1 (NULL_TREE, level, level->names, false, NULL);
}
/* Check that a new jump to a label DECL is OK. Called by
@ -2308,57 +2374,114 @@ check_previous_gotos (tree decl)
void
check_goto (tree decl)
{
int identified = 0;
struct named_label_entry *ent, dummy;
bool saw_catch = false, identified = false;
tree bad;
struct named_label_list *lab;
/* We can't know where a computed goto is jumping. So we assume
that it's OK. */
if (! DECL_P (decl))
/* We can't know where a computed goto is jumping.
So we assume that it's OK. */
if (TREE_CODE (decl) != LABEL_DECL)
return;
/* We didn't record any information about this label when we created it,
and there's not much point since it's trivial to analyze as a return. */
if (decl == cdtor_label)
return;
dummy.label_decl = decl;
ent = (struct named_label_entry *) htab_find (named_labels, &dummy);
gcc_assert (ent != NULL);
/* If the label hasn't been defined yet, defer checking. */
if (! DECL_INITIAL (decl))
{
use_label (decl);
struct named_label_use_entry *new_use;
/* Don't bother creating another use if the last goto had the
same data, and will therefore create the same set of errors. */
if (ent->uses
&& ent->uses->names_in_scope == current_binding_level->names)
return;
new_use = GGC_NEW (struct named_label_use_entry);
new_use->binding_level = current_binding_level;
new_use->names_in_scope = current_binding_level->names;
new_use->o_goto_locus = input_location;
new_use->in_omp_scope = false;
new_use->next = ent->uses;
ent->uses = new_use;
return;
}
for (lab = named_labels; lab; lab = lab->next)
if (decl == lab->label_decl)
break;
/* If the label is not on named_labels it's a gcc local label, so
it must be in an outer scope, so jumping to it is always OK. */
if (lab == 0)
return;
if ((lab->in_try_scope || lab->in_catch_scope || lab->bad_decls)
&& !identified)
if (ent->in_try_scope || ent->in_catch_scope
|| ent->in_omp_scope || ent->bad_decls)
{
pedwarn ("jump to label %q+D", decl);
pedwarn (" from here");
identified = 1;
identified = true;
}
for (bad = lab->bad_decls; bad; bad = TREE_CHAIN (bad))
for (bad = ent->bad_decls; bad; bad = TREE_CHAIN (bad))
{
tree b = TREE_VALUE (bad);
int u = decl_jump_unsafe (b);
if (u > 1 && DECL_ARTIFICIAL (b))
/* Can't skip init of __exception_info. */
error ("%J enters catch block", b);
{
/* Can't skip init of __exception_info. */
error ("%J enters catch block", b);
saw_catch = true;
}
else if (u > 1)
error (" skips initialization of %q+#D", b);
else
pedwarn (" enters scope of non-POD %q+#D", b);
}
if (lab->in_try_scope)
if (ent->in_try_scope)
error (" enters try block");
else if (lab->in_catch_scope)
else if (ent->in_catch_scope && !saw_catch)
error (" enters catch block");
if (ent->in_omp_scope)
error (" enters OpenMP structured block");
else if (flag_openmp)
{
struct cp_binding_level *b;
for (b = current_binding_level; b ; b = b->level_chain)
{
if (b == ent->binding_level)
break;
if (b->kind == sk_omp)
{
if (!identified)
{
pedwarn ("jump to label %q+D", decl);
pedwarn (" from here");
identified = true;
}
error (" exits OpenMP structured block");
break;
}
}
}
}
/* Check that a return is ok wrt OpenMP structured blocks.
Called by finish_return_stmt. Returns true if all is well. */
bool
check_omp_return (void)
{
struct cp_binding_level *b;
for (b = current_binding_level; b ; b = b->level_chain)
if (b->kind == sk_omp)
{
error ("invalid exit from OpenMP structured block");
return false;
}
return true;
}
/* Define a label, specifying the location in the source file.
@ -2367,14 +2490,17 @@ check_goto (tree decl)
tree
define_label (location_t location, tree name)
{
tree decl = lookup_label (name);
struct named_label_list *ent;
struct named_label_entry *ent, dummy;
struct cp_binding_level *p;
tree decl;
timevar_push (TV_NAME_LOOKUP);
for (ent = named_labels; ent; ent = ent->next)
if (ent->label_decl == decl)
break;
decl = lookup_label (name);
dummy.label_decl = decl;
ent = (struct named_label_entry *) htab_find (named_labels, &dummy);
gcc_assert (ent != NULL);
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
@ -2390,16 +2516,19 @@ define_label (location_t location, tree name)
error ("duplicate label %qD", decl);
else
{
struct named_label_use_entry *use;
/* Mark label as having been defined. */
DECL_INITIAL (decl) = error_mark_node;
/* Say where in the source. */
DECL_SOURCE_LOCATION (decl) = location;
if (ent)
{
ent->names_in_scope = current_binding_level->names;
ent->binding_level = current_binding_level;
}
check_previous_gotos (decl);
ent->binding_level = current_binding_level;
ent->names_in_scope = current_binding_level->names;
for (use = ent->uses; use ; use = use->next)
check_previous_goto (decl, use);
ent->uses = NULL;
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
@ -2486,11 +2615,12 @@ finish_case_label (tree low_value, tree high_value)
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
if (!check_switch_goto (switch_stack->level))
return error_mark_node;
r = c_add_case_label (switch_stack->cases, cond, TREE_TYPE (cond),
low_value, high_value);
check_switch_goto (switch_stack->level);
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
for (p = current_binding_level;
@ -10589,7 +10719,6 @@ save_function_data (tree decl)
/* Clear out the bits we don't need. */
f->base.x_stmt_tree.x_cur_stmt_list = NULL_TREE;
f->x_named_label_uses = NULL;
f->bindings = NULL;
f->x_local_names = NULL;
}
@ -10955,7 +11084,6 @@ finish_function (int flags)
}
/* Clear out the bits we don't need. */
local_names = NULL;
named_label_uses = NULL;
/* We're leaving the context of this function, so zap cfun. It's still in
DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation. */

View File

@ -1278,6 +1278,7 @@ begin_scope (scope_kind kind, tree entity)
case sk_for:
case sk_class:
case sk_function_parms:
case sk_omp:
scope->keep = keep_next_level_flag;
break;

View File

@ -106,7 +106,7 @@ typedef enum scope_kind {
contents to zero, and the default scope kind
is "sk_block". */
sk_cleanup, /* A scope for (pseudo-)scope for cleanup. It is
peusdo in that it is transparent to name lookup
pseudo in that it is transparent to name lookup
activities. */
sk_try, /* A try-block. */
sk_catch, /* A catch-block. */
@ -117,10 +117,11 @@ typedef enum scope_kind {
sk_namespace, /* The scope containing the members of a
namespace, including the global scope. */
sk_template_parms, /* A scope for template parameters. */
sk_template_spec /* Like sk_template_parms, but for an explicit
sk_template_spec, /* Like sk_template_parms, but for an explicit
specialization. Since, by definition, an
explicit specialization is introduced by
"template <>", this scope is always empty. */
sk_omp /* An OpenMP structured block. */
} scope_kind;
/* The scope where the class/struct/union/enum tag applies. */

File diff suppressed because it is too large Load Diff

View File

@ -8081,6 +8081,47 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
}
/* Like tsubst_copy, but specifically for OpenMP clauses. */
static tree
tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
tree in_decl)
{
tree new_clauses = NULL, nc, oc;
for (oc = clauses; oc ; oc = OMP_CLAUSE_CHAIN (oc))
{
nc = copy_node (oc);
OMP_CLAUSE_CHAIN (nc) = new_clauses;
new_clauses = nc;
switch (OMP_CLAUSE_CODE (nc))
{
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl);
break;
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
break;
default:
gcc_unreachable ();
}
}
return finish_omp_clauses (nreverse (new_clauses));
}
/* Like tsubst_copy_and_build, but unshare TREE_LIST nodes. */
static tree
@ -8400,6 +8441,84 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
break;
case OMP_PARALLEL:
tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
args, complain, in_decl);
stmt = begin_omp_parallel ();
tsubst_expr (OMP_PARALLEL_BODY (t), args, complain, in_decl);
finish_omp_parallel (tmp, stmt);
break;
case OMP_FOR:
{
tree clauses, decl, init, cond, incr, body, pre_body;
clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
args, complain, in_decl);
init = OMP_FOR_INIT (t);
gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
decl = tsubst_expr (TREE_OPERAND (init, 0), args, complain, in_decl);
init = tsubst_expr (TREE_OPERAND (init, 1), args, complain, in_decl);
cond = tsubst_expr (OMP_FOR_COND (t), args, complain, in_decl);
incr = tsubst_expr (OMP_FOR_INCR (t), args, complain, in_decl);
stmt = begin_omp_structured_block ();
pre_body = push_stmt_list ();
tsubst_expr (OMP_FOR_PRE_BODY (t), args, complain, in_decl);
pre_body = pop_stmt_list (pre_body);
body = push_stmt_list ();
tsubst_expr (OMP_FOR_BODY (t), args, complain, in_decl);
body = pop_stmt_list (body);
t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
pre_body);
if (t)
OMP_FOR_CLAUSES (t) = clauses;
add_stmt (finish_omp_structured_block (stmt));
}
break;
case OMP_SECTIONS:
case OMP_SINGLE:
tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl);
stmt = push_stmt_list ();
tsubst_expr (OMP_BODY (t), args, complain, in_decl);
stmt = pop_stmt_list (stmt);
t = copy_node (t);
OMP_BODY (t) = stmt;
OMP_CLAUSES (t) = tmp;
add_stmt (t);
break;
case OMP_SECTION:
case OMP_CRITICAL:
case OMP_MASTER:
case OMP_ORDERED:
stmt = push_stmt_list ();
tsubst_expr (OMP_BODY (t), args, complain, in_decl);
stmt = pop_stmt_list (stmt);
t = copy_node (t);
OMP_BODY (t) = stmt;
add_stmt (t);
break;
case OMP_ATOMIC:
{
tree op0, op1;
op0 = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl);
op1 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl);
if (OMP_ATOMIC_DEPENDENT_P (t))
c_finish_omp_atomic (OMP_ATOMIC_CODE (t), op0, op1);
else
add_stmt (build2 (OMP_ATOMIC, void_type_node, op0, op1));
}
break;
default:
gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));

View File

@ -743,6 +743,9 @@ finish_return_stmt (tree expr)
bool no_warning;
expr = check_return_expr (expr, &no_warning);
if (flag_openmp && !check_omp_return ())
return error_mark_node;
if (!processing_template_decl)
{
if (DECL_DESTRUCTOR_P (current_function_decl)
@ -3219,9 +3222,619 @@ finalize_nrv (tree *tp, tree var, tree result)
walk_tree (tp, finalize_nrv_r, &data, 0);
htab_delete (data.visited);
}
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
/* Perform initialization related to this module. */
tree
finish_omp_clauses (tree clauses)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
tree c, t, *pc = &clauses;
const char *name;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_SHARED:
name = "shared";
goto check_dup_generic;
case OMP_CLAUSE_PRIVATE:
name = "private";
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
name = "reduction";
goto check_dup_generic;
case OMP_CLAUSE_COPYPRIVATE:
name = "copyprivate";
goto check_dup_generic;
case OMP_CLAUSE_COPYIN:
name = "copyin";
goto check_dup_generic;
check_dup_generic:
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl)
break;
error ("%qE is not a variable in clause %qs", t, name);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t))
|| bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
{
error ("%qE appears more than once in data clauses", t);
remove = true;
}
else
bitmap_set_bit (&generic_head, DECL_UID (t));
break;
case OMP_CLAUSE_FIRSTPRIVATE:
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl)
break;
error ("%qE is not a variable in clause %<firstprivate%>", t);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
error ("%qE appears more than once in data clauses", t);
remove = true;
}
else
bitmap_set_bit (&firstprivate_head, DECL_UID (t));
break;
case OMP_CLAUSE_LASTPRIVATE:
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl)
break;
error ("%qE is not a variable in clause %<lastprivate%>", t);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
{
error ("%qE appears more than once in data clauses", t);
remove = true;
}
else
bitmap_set_bit (&lastprivate_head, DECL_UID (t));
break;
case OMP_CLAUSE_IF:
t = OMP_CLAUSE_IF_EXPR (c);
t = maybe_convert_cond (t);
if (t == error_mark_node)
remove = true;
OMP_CLAUSE_IF_EXPR (c) = t;
break;
case OMP_CLAUSE_NUM_THREADS:
t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
if (t == error_mark_node)
remove = true;
else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
&& !type_dependent_expression_p (t))
{
error ("num_threads expression must be integral");
remove = true;
}
break;
case OMP_CLAUSE_SCHEDULE:
t = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c);
if (t == NULL)
;
else if (t == error_mark_node)
remove = true;
else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
&& !type_dependent_expression_p (t))
{
error ("schedule chunk size expression must be integral");
remove = true;
}
break;
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
break;
default:
gcc_unreachable ();
}
if (remove)
*pc = OMP_CLAUSE_CHAIN (c);
else
pc = &OMP_CLAUSE_CHAIN (c);
}
for (pc = &clauses, c = clauses; c ; c = *pc)
{
enum tree_code c_kind = OMP_CLAUSE_CODE (c);
bool remove = false;
bool need_complete_non_reference = false;
bool need_default_ctor = false;
bool need_copy_ctor = false;
bool need_copy_assignment = false;
bool need_implicitly_determined = false;
tree type, inner_type;
switch (c_kind)
{
case OMP_CLAUSE_SHARED:
name = "shared";
need_implicitly_determined = true;
break;
case OMP_CLAUSE_PRIVATE:
name = "private";
need_complete_non_reference = true;
need_default_ctor = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_FIRSTPRIVATE:
name = "firstprivate";
need_complete_non_reference = true;
need_copy_ctor = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_LASTPRIVATE:
name = "lastprivate";
need_complete_non_reference = true;
need_copy_assignment = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_REDUCTION:
name = "reduction";
need_implicitly_determined = true;
break;
case OMP_CLAUSE_COPYPRIVATE:
name = "copyprivate";
need_copy_assignment = true;
break;
case OMP_CLAUSE_COPYIN:
name = "copyin";
need_copy_assignment = true;
break;
default:
pc = &OMP_CLAUSE_CHAIN (c);
continue;
}
t = OMP_CLAUSE_DECL (c);
if (processing_template_decl
&& TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
pc = &OMP_CLAUSE_CHAIN (c);
continue;
}
switch (c_kind)
{
case OMP_CLAUSE_LASTPRIVATE:
if (!bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
need_default_ctor = true;
break;
case OMP_CLAUSE_REDUCTION:
if (AGGREGATE_TYPE_P (TREE_TYPE (t))
|| POINTER_TYPE_P (TREE_TYPE (t)))
{
error ("%qE has invalid type for %<reduction%>", t);
remove = true;
}
else if (FLOAT_TYPE_P (TREE_TYPE (t)))
{
enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
switch (r_code)
{
case PLUS_EXPR:
case MULT_EXPR:
case MINUS_EXPR:
break;
default:
error ("%qE has invalid type for %<reduction(%s)%>",
t, operator_name_info[r_code].name);
remove = true;
}
}
break;
case OMP_CLAUSE_COPYIN:
if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t))
{
error ("%qE must be %<threadprivate%> for %<copyin%>", t);
remove = true;
}
break;
default:
break;
}
if (need_complete_non_reference)
{
t = require_complete_type (t);
if (t == error_mark_node)
remove = true;
else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
{
error ("%qE has reference type for %qs", t, name);
remove = true;
}
}
if (need_implicitly_determined)
{
const char *share_name = NULL;
if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
share_name = "threadprivate";
else switch (cxx_omp_predetermined_sharing (t))
{
case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
break;
case OMP_CLAUSE_DEFAULT_SHARED:
share_name = "shared";
break;
case OMP_CLAUSE_DEFAULT_PRIVATE:
share_name = "private";
break;
default:
gcc_unreachable ();
}
if (share_name)
{
error ("%qE is predetermined %qs for %qs",
t, share_name, name);
remove = true;
}
}
/* We're interested in the base element, not arrays. */
inner_type = type = TREE_TYPE (t);
while (TREE_CODE (inner_type) == ARRAY_TYPE)
inner_type = TREE_TYPE (inner_type);
/* Check for special function availablity by building a call to one.
Save the results, because later we won't be in the right context
for making these queries. */
if (CLASS_TYPE_P (inner_type)
&& (need_default_ctor || need_copy_ctor || need_copy_assignment))
{
int save_errorcount = errorcount;
tree info;
/* Always allocate 3 elements for simplicity. These are the
function decls for the ctor, dtor, and assignment op.
This layout is known to the three lang hooks,
cxx_omp_clause_default_init, cxx_omp_clause_copy_init,
and cxx_omp_clause_assign_op. */
info = make_tree_vec (3);
CP_OMP_CLAUSE_INFO (c) = info;
if (need_default_ctor
|| (need_copy_ctor
&& !TYPE_HAS_TRIVIAL_INIT_REF (inner_type)))
{
if (need_default_ctor)
t = NULL;
else
{
t = build_int_cst (build_pointer_type (inner_type), 0);
t = build1 (INDIRECT_REF, inner_type, t);
t = build_tree_list (NULL, t);
}
t = build_special_member_call (NULL_TREE,
complete_ctor_identifier,
t, inner_type, LOOKUP_NORMAL);
t = get_callee_fndecl (t);
TREE_VEC_ELT (info, 0) = t;
}
if ((need_default_ctor || need_copy_ctor)
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_type))
{
t = build_int_cst (build_pointer_type (inner_type), 0);
t = build1 (INDIRECT_REF, inner_type, t);
t = build_special_member_call (t, complete_dtor_identifier,
NULL, inner_type, LOOKUP_NORMAL);
t = get_callee_fndecl (t);
TREE_VEC_ELT (info, 1) = t;
}
if (need_copy_assignment
&& !TYPE_HAS_TRIVIAL_ASSIGN_REF (inner_type))
{
t = build_int_cst (build_pointer_type (inner_type), 0);
t = build1 (INDIRECT_REF, inner_type, t);
t = build_special_member_call (t, ansi_assopname (NOP_EXPR),
build_tree_list (NULL, t),
inner_type, LOOKUP_NORMAL);
/* We'll have called convert_from_reference on the call, which
may well have added an indirect_ref. It's unneeded here,
and in the way, so kill it. */
if (TREE_CODE (t) == INDIRECT_REF)
t = TREE_OPERAND (t, 0);
t = get_callee_fndecl (t);
TREE_VEC_ELT (info, 2) = t;
}
if (errorcount != save_errorcount)
remove = true;
}
if (remove)
*pc = OMP_CLAUSE_CHAIN (c);
else
pc = &OMP_CLAUSE_CHAIN (c);
}
bitmap_obstack_release (NULL);
return clauses;
}
/* For all variables in the tree_list VARS, mark them as thread local. */
void
finish_omp_threadprivate (tree vars)
{
tree t;
/* Mark every variable in VARS to be assigned thread local storage. */
for (t = vars; t; t = TREE_CHAIN (t))
{
tree v = TREE_PURPOSE (t);
/* If V had already been marked threadprivate, it doesn't matter
whether it had been used prior to this point. */
if (TREE_USED (v)
&& (DECL_LANG_SPECIFIC (v) == NULL
|| !CP_DECL_THREADPRIVATE_P (v)))
error ("%qE declared %<threadprivate%> after first use", v);
else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
error ("automatic variable %qE cannot be %<threadprivate%>", v);
else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
error ("%<threadprivate%> %qE has incomplete type", v);
else if (TREE_STATIC (v) && TYPE_P (CP_DECL_CONTEXT (v)))
error ("%<threadprivate%> %qE is not file, namespace "
"or block scope variable", v);
else
{
/* Allocate a LANG_SPECIFIC structure for V, if needed. */
if (DECL_LANG_SPECIFIC (v) == NULL)
{
retrofit_lang_decl (v);
/* Make sure that DECL_DISCRIMINATOR_P continues to be true
after the allocation of the lang_decl structure. */
if (DECL_DISCRIMINATOR_P (v))
DECL_LANG_SPECIFIC (v)->decl_flags.u2sel = 1;
}
if (! DECL_THREAD_LOCAL_P (v))
{
DECL_TLS_MODEL (v) = decl_default_tls_model (v);
/* If rtl has been already set for this var, call
make_decl_rtl once again, so that encode_section_info
has a chance to look at the new decl flags. */
if (DECL_RTL_SET_P (v))
make_decl_rtl (v);
}
CP_DECL_THREADPRIVATE_P (v) = 1;
}
}
}
/* Build an OpenMP structured block. */
tree
begin_omp_structured_block (void)
{
return do_pushlevel (sk_omp);
}
tree
finish_omp_structured_block (tree block)
{
return do_poplevel (block);
}
/* Similarly, except force the retension of the BLOCK. */
tree
begin_omp_parallel (void)
{
keep_next_level (true);
return begin_omp_structured_block ();
}
tree
finish_omp_parallel (tree clauses, tree body)
{
tree stmt;
body = finish_omp_structured_block (body);
stmt = make_node (OMP_PARALLEL);
TREE_TYPE (stmt) = void_type_node;
OMP_PARALLEL_CLAUSES (stmt) = clauses;
OMP_PARALLEL_BODY (stmt) = body;
return add_stmt (stmt);
}
/* Build and validate an OMP_FOR statement. CLAUSES, BODY, COND, INCR
are directly for their associated operands in the statement. DECL
and INIT are a combo; if DECL is NULL then INIT ought to be a
MODIFY_EXPR, and the DECL should be extracted. PRE_BODY are
optional statements that need to go before the loop into its
sk_omp scope. */
tree
finish_omp_for (location_t locus, tree decl, tree init, tree cond,
tree incr, tree body, tree pre_body)
{
if (decl == NULL)
{
if (init != NULL)
switch (TREE_CODE (init))
{
case MODIFY_EXPR:
decl = TREE_OPERAND (init, 0);
init = TREE_OPERAND (init, 1);
break;
case MODOP_EXPR:
if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR)
{
decl = TREE_OPERAND (init, 0);
init = TREE_OPERAND (init, 2);
}
break;
default:
break;
}
if (decl == NULL)
{
error ("expected iteration declaration or initialization");
return NULL;
}
}
if (type_dependent_expression_p (decl)
|| type_dependent_expression_p (init)
|| (cond && type_dependent_expression_p (cond))
|| (incr && type_dependent_expression_p (incr)))
{
tree stmt;
if (cond == NULL)
{
error ("%Hmissing controlling predicate", &locus);
return NULL;
}
if (incr == NULL)
{
error ("%Hmissing increment expression", &locus);
return NULL;
}
stmt = make_node (OMP_FOR);
/* This is really just a place-holder. We'll be decomposing this
again and going through the build_modify_expr path below when
we instantiate the thing. */
init = build2 (MODIFY_EXPR, void_type_node, decl, init);
TREE_TYPE (stmt) = void_type_node;
OMP_FOR_INIT (stmt) = init;
OMP_FOR_COND (stmt) = cond;
OMP_FOR_INCR (stmt) = incr;
OMP_FOR_BODY (stmt) = body;
OMP_FOR_PRE_BODY (stmt) = pre_body;
SET_EXPR_LOCATION (stmt, locus);
return add_stmt (stmt);
}
if (!DECL_P (decl))
{
error ("expected iteration declaration or initialization");
return NULL;
}
if (pre_body == NULL || IS_EMPTY_STMT (pre_body))
pre_body = NULL;
else if (! processing_template_decl)
{
add_stmt (pre_body);
pre_body = NULL;
}
init = build_modify_expr (decl, NOP_EXPR, init);
return c_finish_omp_for (locus, decl, init, cond, incr, body, pre_body);
}
void
finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
{
/* If either of the operands are dependent, we can't do semantic
processing yet. Stuff the values away for now. We cheat a bit
and use the same tree code for this, even though the operands
are of totally different form, thus we need to remember which
statements are which, thus the lang_flag bit. */
/* ??? We ought to be using type_dependent_expression_p, but the
invocation of build_modify_expr in c_finish_omp_atomic can result
in the creation of CONVERT_EXPRs, which are not handled by
tsubst_copy_and_build. */
if (uses_template_parms (lhs) || uses_template_parms (rhs))
{
tree stmt = build2 (OMP_ATOMIC, void_type_node, lhs, rhs);
OMP_ATOMIC_DEPENDENT_P (stmt) = 1;
OMP_ATOMIC_CODE (stmt) = code;
add_stmt (stmt);
}
else
c_finish_omp_atomic (code, lhs, rhs);
}
void
finish_omp_barrier (void)
{
tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
tree stmt = finish_call_expr (fn, NULL, false, false);
finish_expr_stmt (stmt);
}
void
finish_omp_flush (void)
{
tree fn = built_in_decls[BUILT_IN_SYNCHRONIZE];
tree stmt = finish_call_expr (fn, NULL, false, false);
finish_expr_stmt (stmt);
}
/* True if OpenMP sharing attribute of DECL is predetermined. */
enum omp_clause_default_kind
cxx_omp_predetermined_sharing (tree decl)
{
enum omp_clause_default_kind kind;
kind = c_omp_predetermined_sharing (decl);
if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
return kind;
/* Static data members are predetermined as shared. */
if (TREE_STATIC (decl))
{
tree ctx = CP_DECL_CONTEXT (decl);
if (TYPE_P (ctx) && IS_AGGR_TYPE (ctx))
return OMP_CLAUSE_DEFAULT_SHARED;
}
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
void
init_cp_semantics (void)
{

View File

@ -1,3 +1,8 @@
2006-03-09 Diego Novillo <dnovillo@redhat.com>
* gcc/testsuite/g++.dg/gomp: New directory.
* gcc/testsuite/g++.dg/dg.exp: Gather tests in gomp/.
2006-03-09 Roger Sayle <roger@eyesopen.com>
Eric Botcazou <ebotcazou@libertysurf.fr>

View File

@ -40,6 +40,7 @@ set tests [prune $tests $srcdir/$subdir/pch/*]
set tests [prune $tests $srcdir/$subdir/special/*]
set tests [prune $tests $srcdir/$subdir/tls/*]
set tests [prune $tests $srcdir/$subdir/vect/*]
set tests [prune $tests $srcdir/$subdir/gomp/*]
# Main loop.
dg-runtest $tests "" $DEFAULT_CXXFLAGS

View File

@ -0,0 +1,99 @@
/* { dg-do compile } */
int x;
volatile int y;
volatile unsigned char z;
void f1(void)
{
#pragma omp atomic
x++;
#pragma omp atomic
x--;
#pragma omp atomic
++x;
#pragma omp atomic
--x;
#pragma omp atomic
x += 1;
#pragma omp atomic
x -= y;
#pragma omp atomic
x |= 1;
#pragma omp atomic
x &= 1;
#pragma omp atomic
x ^= 1;
#pragma omp atomic
x *= 3;
#pragma omp atomic
x /= 3;
#pragma omp atomic
x /= 3;
#pragma omp atomic
x <<= 3;
#pragma omp atomic
x >>= 3;
}
void f2(void)
{
#pragma omp atomic
y++;
#pragma omp atomic
y--;
#pragma omp atomic
++y;
#pragma omp atomic
--y;
#pragma omp atomic
y += 1;
#pragma omp atomic
y -= x;
#pragma omp atomic
y |= 1;
#pragma omp atomic
y &= 1;
#pragma omp atomic
y ^= 1;
#pragma omp atomic
y *= 3;
#pragma omp atomic
y /= 3;
#pragma omp atomic
y /= 3;
#pragma omp atomic
y <<= 3;
#pragma omp atomic
y >>= 3;
}
void f3(void)
{
#pragma omp atomic
z++;
#pragma omp atomic
z--;
#pragma omp atomic
++z;
#pragma omp atomic
--z;
#pragma omp atomic
z += 1;
#pragma omp atomic
z |= 1;
#pragma omp atomic
z &= 1;
#pragma omp atomic
z ^= 1;
#pragma omp atomic
z *= 3;
#pragma omp atomic
z /= 3;
#pragma omp atomic
z /= 3;
#pragma omp atomic
z <<= 3;
#pragma omp atomic
z >>= 3;
}

View File

@ -0,0 +1,23 @@
/* { dg-do compile } */
float x, y;
void f1(void)
{
#pragma omp atomic
x++;
#pragma omp atomic
x--;
#pragma omp atomic
++x;
#pragma omp atomic
--x;
#pragma omp atomic
x += 1;
#pragma omp atomic
x -= y;
#pragma omp atomic
x *= 3;
#pragma omp atomic
x /= 3;
}

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-gimple" } */
int *xyzzy;
void f1(void)
{
#pragma omp atomic
xyzzy++;
}
/* { dg-final { scan-tree-dump-times "xyzzy, 4" 1 "gimple" { target i?86-*-* x86_64-*-* ia64-*-* powerpc*-*-* alpha*-*-* } } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */

View File

@ -0,0 +1,24 @@
/* { dg-do compile } */
int a[4];
int *p;
struct S { int x; int y[4]; } s;
int *bar(void);
void f1(void)
{
#pragma omp atomic
a[4] += 1;
#pragma omp atomic
*p += 1;
#pragma omp atomic
s.x += 1;
#pragma omp atomic
s.y[*p] += 1;
#pragma omp atomic
s.y[*p] *= 42;
#pragma omp atomic
*bar() += 1;
#pragma omp atomic
*bar() *= 42;
}

View File

@ -0,0 +1,34 @@
/* { dg-do compile } */
int x;
const int y = 0;
int bar(void);
void f1(void)
{
#pragma omp atomic
x %= 2; /* { dg-error "invalid operator" } */
#pragma omp atomic
x = x + 1; /* { dg-error "invalid operator" } */
#pragma omp atomic
x = 1; /* { dg-error "invalid operator" } */
#pragma omp atomic
++y; /* { dg-error "read-only variable" } */
#pragma omp atomic
y--; /* { dg-error "read-only variable" } */
#pragma omp atomic
y += 1; /* { dg-error "read-only variable" } */
#pragma omp atomic
bar(); /* { dg-error "invalid operator" } */
#pragma omp atomic
bar() += 1; /* { dg-error "lvalue required" } */
#pragma omp atomic a /* { dg-error "expected end of line" } */
x++;
#pragma omp atomic
; /* { dg-error "expected primary-expression" } */
#pragma omp atomic
#pragma omp atomic /* { dg-error "not allowed" } */
;
/* Check that we didn't get stuck on the pragma eol marker. */
undef; /* { dg-error "" } */
}

View File

@ -0,0 +1,11 @@
// { dg-do compile }
// { dg-options "-w -fopenmp" }
int x[10], z;
double y[10];
void f1(void)
{
#pragma omp atomic
x[z] /= y[z];
}

View File

@ -0,0 +1,23 @@
/* { dg-do compile } */
double x, y;
void f2(void)
{
#pragma omp atomic
y++;
#pragma omp atomic
y--;
#pragma omp atomic
++y;
#pragma omp atomic
--y;
#pragma omp atomic
y += 1;
#pragma omp atomic
y -= x;
#pragma omp atomic
y *= 3;
#pragma omp atomic
y /= 3;
}

View File

@ -0,0 +1,21 @@
/* { dg-do compile } */
long double z;
void f3(void)
{
#pragma omp atomic
z++;
#pragma omp atomic
z--;
#pragma omp atomic
++z;
#pragma omp atomic
--z;
#pragma omp atomic
z += 1;
#pragma omp atomic
z *= 3;
#pragma omp atomic
z /= 3;
}

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-gimple" } */
volatile int *bar(void);
void f1(void)
{
#pragma omp atomic
*bar() += 1;
}
/* { dg-final { scan-tree-dump-times "__sync_fetch_and_add" 1 "gimple" { target i?86-*-* x86_64-*-* ia64-*-* powerpc*-*-* alpha*-*-* } } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */

View File

@ -0,0 +1,18 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-gimple" } */
void f1(void)
{
#pragma omp barrier
}
void f2(bool p)
{
if (p)
{
#pragma omp barrier
}
}
/* { dg-final { scan-tree-dump-times "GOMP_barrier" 2 "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */

View File

@ -0,0 +1,12 @@
// { dg-do compile }
void f1(void)
{
#pragma omp barrier a // { dg-error "expected end of line" }
}
void f3(bool p)
{
if (p)
#pragma omp barrier // { dg-error "compound statements" }
} // { dg-error "" }

View File

@ -0,0 +1,33 @@
// { dg-do compile }
// { dg-options "-fopenmp -fdump-tree-omplower" }
void bar();
void foo()
{
#pragma omp critical
bar ();
#pragma omp master
bar ();
#pragma omp single
bar ();
#pragma omp for
for (int i = 0; i < 10; ++i)
bar ();
#pragma omp sections
{ bar(); }
#pragma omp parallel
bar ();
#pragma omp parallel for
for (int i = 0; i < 10; ++i)
bar ();
#pragma omp parallel sections
{
bar ();
bar ();
#pragma omp section
bar ();
}
}
// { dg-final { scan-tree-dump-times "terminate" 8 "omplower" } }
// { dg-final { cleanup-tree-dump "omplower" } }

View File

@ -0,0 +1,22 @@
// { dg-do compile }
void foo()
{
bad1: // { dg-error "jump to label" }
#pragma omp parallel
goto bad1; // { dg-error "from here|exits OpenMP" }
goto bad2; // { dg-error "from here" }
#pragma omp parallel
{
bad2: ; // { dg-error "jump to label|enters OpenMP" }
}
#pragma omp parallel
{
int i;
goto ok1;
for (i = 0; i < 10; ++i)
{ ok1: break; }
}
}

View File

@ -0,0 +1,40 @@
// { dg-do compile }
void foo(int i)
{
int j;
switch (i)
{
#pragma omp parallel
{ case 0:; } // { dg-error "jump|enters" }
}
switch (i)
{
#pragma omp for
for (j = 0; j < 10; ++ j)
{ case 1:; } // { dg-error "jump|enters" }
}
switch (i)
{
#pragma omp critical
{ case 2:; } // { dg-error "jump|enters" }
}
switch (i)
{
#pragma omp master
{ case 3:; } // { dg-error "jump|enters" }
}
switch (i)
{
#pragma omp sections
{ case 4:; // { dg-error "jump|enters" }
#pragma omp section
{ case 5:; } // { dg-error "jump|enters" }
}
}
switch (i)
{
#pragma omp ordered
{ default:; } // { dg-error "jump|enters" }
}
}

View File

@ -0,0 +1,19 @@
/* PR c++/24516 */
/* { dg-do compile } */
void
bar (int *p)
{
int m;
#pragma omp parallel for
for (m = 0; m < 1000; ++m)
switch (p[m])
{
case 1:
p[m] = 2;
break;
default:
p[m] = 3;
break;
}
}

View File

@ -0,0 +1,32 @@
// { dg-do compile }
void foo()
{
int i, j;
#pragma omp for
for (i = 0; i < 10; ++i)
break; // { dg-error "break" }
bad1: // { dg-error "jump to label" }
#pragma omp for
for (i = 0; i < 10; ++i)
goto bad1; // { dg-error "from here|exits OpenMP" }
goto bad2; // { dg-error "from here" }
#pragma omp for
for (i = 0; i < 10; ++i)
{
bad2: ; // { dg-error "jump|enters OpenMP" }
}
#pragma omp for
for (i = 0; i < 10; ++i)
for (j = 0; j < 10; ++j)
if (i == j)
break;
#pragma omp for
for (i = 0; i < 10; ++i)
continue;
}

View File

@ -0,0 +1,57 @@
// { dg-do compile }
extern int test(int);
void foo()
{
int i;
for (i = 0; i < 10; ++i)
{
#pragma omp sections
{
continue; // { dg-error "invalid exit" }
}
}
#pragma omp sections
{
#pragma omp section
{ bad1: ; } // { dg-error "jump to label" }
#pragma omp section
goto bad1; // { dg-error "from here|enters OpenMP" }
}
#pragma omp sections
{
goto bad2; // { dg-error "from here" }
}
bad2:; // { dg-error "jump|exits OpenMP" }
goto bad3; // { dg-error "from here" }
#pragma omp sections
{
bad3: ; // { dg-error "jump|enters OpenMP" }
}
#pragma omp sections
{
goto ok1;
ok1:;
#pragma omp section
for (i = 0; i < 10; ++i)
if (test(i))
break;
else
continue;
#pragma omp section
switch (i)
{
case 0:
break;
default:
test(i);
}
}
}

View File

@ -0,0 +1,9 @@
// { dg-do compile }
void foo()
{
#pragma omp critical
{
return; // { dg-error "invalid exit" }
}
}

View File

@ -0,0 +1,15 @@
// { dg-do compile }
void foo()
{
#pragma omp master
{
goto bad1; // { dg-error "from here" }
}
#pragma omp master
{
bad1: // { dg-error "jump|exits OpenMP" }
return; // { dg-error "invalid exit" }
}
}

View File

@ -0,0 +1,9 @@
// { dg-do compile }
void foo()
{
#pragma omp ordered
{
return; // { dg-error "invalid exit" }
}
}

View File

@ -0,0 +1,20 @@
// { dg-do compile }
void foo()
{
int i, j;
for (i = 0; i < 10; ++i)
{
#pragma omp for
for (j = ({ continue; 0; }); // { dg-error "invalid exit" }
j < ({ continue; 10; }); // { dg-error "invalid exit" }
j += ({ continue; 1; })) // { dg-error "invalid exit" }
continue;
#pragma omp for
for (j = ({ break; 0; }); // { dg-error "invalid exit" }
j < ({ break; 10; }); // { dg-error "invalid exit" }
j += ({ break; 1; })) // { dg-error "invalid exit" }
break; // { dg-error "break" }
}
}

View File

@ -0,0 +1,11 @@
// { dg-do compile }
// PR 24451
int foo()
{
int i;
#pragma omp parallel for
for (i = 0; i < 10; ++i)
return 0; // { dg-error "invalid exit" }
}

View File

@ -0,0 +1,25 @@
// { dg-do compile }
void foo(int i)
{
int j;
switch (i)
{
#pragma omp parallel
{ case 0:; } // { dg-error "jump|enters" }
#pragma omp for
for (j = 0; j < 10; ++ j)
{ case 1:; } // { dg-error "jump|enters" }
#pragma omp critical
{ case 2:; } // { dg-error "jump|enters" }
#pragma omp master
{ case 3:; } // { dg-error "jump|enters" }
#pragma omp sections
{ case 4:; // { dg-error "jump|enters" }
#pragma omp section
{ case 5:; } // { dg-error "jump|enters" }
}
#pragma omp ordered
{ default:; } // { dg-error "jump|enters" }
}
}

View File

@ -0,0 +1,32 @@
// { dg-do compile }
struct T
{
int n;
void test();
};
void T::test()
{
#pragma omp parallel private(n) // { dg-error "T::n" }
n = 1;
#pragma omp parallel shared(n) // { dg-error "T::n" }
n = 1;
#pragma omp parallel firstprivate(n) // { dg-error "T::n" }
n = 1;
#pragma omp sections lastprivate(n) // { dg-error "T::n" }
{ n = 1; }
#pragma omp parallel reduction(+:n) // { dg-error "T::n" }
n = 1;
#pragma omp single copyprivate(n) // { dg-error "T::n" }
n = 1;
#pragma omp parallel copyin(n) // { dg-error "T::n" }
n = 1;
}

View File

@ -0,0 +1,38 @@
// { dg-do compile }
struct A { int a; };
struct B { B(); };
struct C { C(); C(const C&); };
struct D { D& operator=(const D&); };
class E { private: E(); public: E(int); }; // { dg-error "private" }
class F { private: F(const F&); public: F(); }; // { dg-error "private" }
class G { private: G& operator=(const G&); }; // { dg-error "private" }
void bar();
void foo()
{
A a; B b; C c; D d; E e(0); F f; G g;
#pragma omp parallel shared(a, b, c, d, e, f, g)
bar();
#pragma omp parallel private(a, b, c, d, f, g)
bar();
#pragma omp parallel private(e) // { dg-error "context" }
bar();
#pragma omp parallel firstprivate(a, b, c, d, e, g)
bar();
#pragma omp parallel firstprivate(f) // { dg-error "context" }
bar();
#pragma omp parallel sections lastprivate(a, b, d, c, f)
{ bar(); }
#pragma omp parallel sections lastprivate(e) // { dg-error "context" }
{ bar(); }
#pragma omp parallel sections lastprivate(g) // { dg-error "context" }
{ bar(); }
#pragma omp parallel sections firstprivate(e) lastprivate(e)
{ bar(); }
}

View File

@ -0,0 +1,94 @@
// { dg-do compile }
// { dg-require-effective-target tls }
#define p parallel
extern void bar (void);
extern char q[]; // { dg-error "has incomplete type" }
int t;
#pragma omp threadprivate (t)
void
foo (int x)
{
char *p;
struct S { int i; int j; } s;
char a[32];
double d;
int i;
const int c = 8;
#pragma omp p shared (x, x) // { dg-error "more than once" }
;
#pragma omp p private (x) private (x) // { dg-error "more than once" }
;
#pragma omp p shared (x) firstprivate (x) // { dg-error "more than once" }
;
#pragma omp p firstprivate (x, x) // { dg-error "more than once" }
;
#pragma omp p for shared (x) lastprivate (x) // { dg-error "more than once" }
for (i = 0; i < 10; i++)
;
#pragma omp p for private (x) lastprivate (x) // { dg-error "more than once" }
for (i = 0; i < 10; i++)
;
#pragma omp p for lastprivate (x, x) // { dg-error "more than once" }
for (i = 0; i < 10; i++)
;
#pragma omp single private (x) copyprivate (x) // { dg-error "more than once" }
;
#pragma omp p shared (bar) // { dg-error "is not a variable" }
;
#pragma omp p private (bar) // { dg-error "is not a variable" }
;
#pragma omp p firstprivate (bar) // { dg-error "is not a variable" }
;
#pragma omp p reduction (+:p) // { dg-error "has invalid type for" }
;
#pragma omp p reduction (*:s) // { dg-error "has invalid type for" }
;
#pragma omp p reduction (-:a) // { dg-error "has invalid type for" }
;
d = 0;
#pragma omp p reduction (*:d)
;
#pragma omp p reduction (|:d) // { dg-error "has invalid type for" }
;
#pragma omp p reduction (&&:d) // { dg-error "has invalid type for" }
;
#pragma omp p copyin (d) // { dg-error "must be 'threadprivate'" }
;
#pragma omp p copyin (x) // { dg-error "must be 'threadprivate'" }
;
#pragma omp p for firstprivate (x) lastprivate (x)
for (i = 0; i < 10; i++)
;
#pragma omp p private (q) // { dg-error "unspecified bounds" }
;
#pragma omp p firstprivate (q) // { dg-error "unspecified bounds" }
;
#pragma omp p for lastprivate (q) // { dg-error "unspecified bounds" }
for (i = 0; i < 10; i++)
;
#pragma omp p shared (t) // { dg-error "predetermined 'threadprivate'" }
;
#pragma omp p private (t) // { dg-error "predetermined 'threadprivate'" }
;
#pragma omp p firstprivate (t) // { dg-error "predetermined 'threadprivate'" }
;
#pragma omp p for lastprivate (t) // { dg-error "predetermined 'threadpriv" }
for (i = 0; i < 10; i++)
;
#pragma omp p reduction (*:t) // { dg-error "predetermined 'threadprivate'" }
;
#pragma omp p shared (c) // { dg-error "predetermined 'shared'" }
;
#pragma omp p private (c) // { dg-error "predetermined 'shared'" }
;
#pragma omp p firstprivate (c) // { dg-error "predetermined 'shared'" }
;
#pragma omp p for lastprivate (c) // { dg-error "predetermined 'shared'" }
for (i = 0; i < 10; i++)
;
#pragma omp p reduction (*:c) // { dg-error "predetermined 'shared'" }
;
}

View File

@ -0,0 +1,27 @@
// { dg-do compile }
// { dg-require-effective-target tls }
int i, j;
#pragma omp threadprivate (i)
void bar(void);
void foo(void)
{
int k;
extern int l;
extern int m;
#pragma omp threadprivate (m)
#pragma omp parallel copyin(i)
bar();
#pragma omp parallel copyin(j) // { dg-error "threadprivate" }
bar();
#pragma omp parallel copyin(k) // { dg-error "threadprivate" }
bar();
#pragma omp parallel copyin(l) // { dg-error "threadprivate" }
bar();
#pragma omp parallel copyin(m)
bar();
}

View File

@ -0,0 +1,28 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-omplower" } */
extern void bar(int);
void foo (void)
{
#pragma omp critical
bar(0);
/* Note that "name" is in its own namespace, thus this foo is not
the same as the function. */
#pragma omp critical(foo)
{
bar(1);
bar(2);
}
#pragma omp critical
#pragma omp critical(foo)
bar(3);
}
/* { dg-final { scan-tree-dump-times "GOMP_critical_start" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "GOMP_critical_end" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "GOMP_critical_name_start" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "GOMP_critical_name_end" 2 "omplower" } } */
/* { dg-final { cleanup-tree-dump "omplower" } } */

View File

@ -0,0 +1,12 @@
// { dg-do compile }
void f1(void)
{
#pragma omp critical a // { dg-error "expected" }
;
#pragma omp critical ( // { dg-error "expected identifier" }
;
#pragma omp critical (a // { dg-error "expected .\\)." }
;
#pragma omp critical (a b) // { dg-error "expected .\\)." }
} // { dg-error "" }

View File

@ -0,0 +1,25 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-gimple" } */
void f1(void)
{
#pragma omp flush
}
int x;
void f2(bool p)
{
int z;
if (p)
{
#pragma omp flush (x)
}
else
{
#pragma omp flush (x, z, p)
}
}
/* { dg-final { scan-tree-dump-times "__sync_synchronize" 3 "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */

View File

@ -0,0 +1,10 @@
// { dg-do compile }
void f1(void)
{
#pragma omp flush a // { dg-error "expected" }
#pragma omp flush ( // { dg-error "expected" }
#pragma omp flush (b // { dg-error "declared|expected" }
#pragma omp flush (c d) // { dg-error "declared|expected" }
#pragma omp flush (e) // { dg-error "declared" }
}

View File

@ -0,0 +1,49 @@
// { dg-do compile }
extern void baz(int);
void foo (int j, int k)
{
int i;
/* Valid loops. */
#pragma omp for
for (i = 0; i < 10; i++)
baz (i);
#pragma omp for
for (i = j; i <= 10; i+=4)
baz (i);
#pragma omp for
for (i = j; i > 0; i = i - 1)
baz (j);
#pragma omp for
for (i = j; i >= k; i--)
baz (i);
// Malformed parallel loops.
#pragma omp for
i = 0; // { dg-error "for statement expected" }
for ( ; i < 10; )
{
baz (i);
i++;
}
#pragma omp for
for (i = 0; ; i--) // { dg-error "missing controlling predicate" }
{
if (i >= 10)
break; // { dg-error "break" }
baz (i);
}
#pragma omp for
for (i = 0; i < 10 && j > 4; i-=3) // { dg-error "invalid controlling predicate" }
baz (i);
#pragma omp for
for (i = 0; i < 10; i-=3, j+=2) // { dg-error "invalid increment expression" }
baz (i);
}

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
extern void bar(int);
void foo (int n)
{
int i;
#pragma omp for schedule(runtime) ordered
for (i = 0; i < n; ++i)
bar(i);
}
/* { dg-final { scan-tree-dump-times "GOMP_loop_ordered_runtime_start" 1 "ompexp" } } */
/* { dg-final { scan-tree-dump-times "GOMP_loop_ordered_runtime_next" 1 "ompexp" } } */
/* { dg-final { cleanup-tree-dump "ompexp" } } */

View File

@ -0,0 +1,14 @@
// { dg-do compile }
extern void baz (int);
void foo (int j, int k)
{
#pragma omp for
for (int l = j; l < k; l++)
baz (l);
#pragma omp for
for (int i = 0, m = 0; m < 10; m++) // { dg-error "" }
baz (m);
}

View File

@ -0,0 +1,12 @@
int foo (void)
{
int i, a;
a = 30;
#pragma omp parallel for lastprivate (a)
for (i = 0; i < 10; i++)
a = a + i;
return a;
}

View File

@ -0,0 +1,18 @@
// At one point in development, a typo disabled the remapping of the
// for iteration variable as private.
// { dg-do compile }
// { dg-options "-fopenmp -fdump-tree-lower" }
extern void bar(int);
void foo(void)
{
int i;
#pragma omp parallel for default(none)
for (i = 0; i < 10; i++)
bar(i);
}
// { dg-final { scan-tree-dump-times "omp_data_o" 0 "lower" } }
// { dg-final { cleanup-tree-dump "lower" } }

View File

@ -0,0 +1,19 @@
// { dg-do compile }
extern int printf (const char *, ...);
extern void foo (int *);
int main (void)
{
double d = 6;
int i = 1, j = 6, k = 8;
#pragma omp parallel shared(d) private(i) num_threads (4)
{
i = 4;
#pragma omp for lastprivate(j)
for (j = 1; j <= k; j++)
printf ("%s %d %d %d %p %g\n", "Hello, World!", i, j, k, &j, d);
printf ("%s %d %g\n", "Hello, World!", i, d);
}
return 0;
}

View File

@ -0,0 +1,35 @@
// PR c++/24512
// { dg-do compile }
template<typename T> void foo ()
{
#pragma omp for
for (int i = 0; i < 10; i++);
#pragma omp for
for (int i = 0; i < 10; i++);
#pragma omp for
for (T j = 0; j < 10; j++);
#pragma omp for
for (T j = 0; j < 10; j++);
#pragma omp parallel for
for (int k = 0; k < 10; k++);
#pragma omp parallel for
for (int k = 0; k < 10; k++);
#pragma omp parallel for
for (T l = 0; l < 10; l++);
#pragma omp parallel for
for (T l = 0; l < 10; l++);
}
void bar ()
{
foo<int> ();
foo<long> ();
}

View File

@ -0,0 +1,33 @@
// { dg-do compile }
template<typename T>
void foo ()
{
#pragma omp for
for (unsigned int i = 0; i < 10; i++); // { dg-warning "is unsigned" }
#pragma omp for
for (int j = 0; ; j++); // { dg-error "missing controlling predicate" }
#pragma omp for
for (int k = 0; k == 1; k++); // { dg-error "invalid controlling predicate" }
#pragma omp for
for (int l = 0; l < 10; ); // { dg-error "missing increment expression" }
#pragma omp for
for (int m = 0; m < 10; m *= 3); // Error here is emitted only during
// instantiation
#pragma omp for
for (T n = 0; ; n++); // { dg-error "missing controlling predicate" }
#pragma omp for
for (T o = 0; o == 1; o++); // Error here is emitted only during
// instantiation
#pragma omp for
for (T p = 0; p < 10; ); // { dg-error "missing increment expression" }
#pragma omp for
for (T q = 0; q < 10; q *= 3); // Error here is emitted only during
// instantiation
}
void bar ()
{
#pragma omp for
for (int m = 0; m < 10; m *= 3); // { dg-error "invalid increment expression" }
}

View File

@ -0,0 +1,11 @@
/* { dg-do compile } */
void foo()
{
long n = 10;
int i;
#pragma omp for
for (i=0; i < n; ++i) ;
#pragma omp for
for (i=0; n > i; ++i) ;
}

View File

@ -0,0 +1,67 @@
// { dg-do compile }
extern int bar (int);
void
foo (void)
{
int j, k = 1, l = 30, m = 4;
long int o = 4;
long long int p = 0;
#pragma omp for
for (j = k; j <= l; j += m - 1)
;
#pragma omp for
for (j = k; j <= l; j += (m - 1))
;
#pragma omp for
for (j = k; j <= l; j += bar (m - 1))
;
#pragma omp for
for (j = k; j <= l; j = j + m - 1)
;
#pragma omp for
for (j = k; j <= l; j = j + (m - 1))
;
#pragma omp for
for (j = k; j <= l; j = j + bar (m - 1))
;
#pragma omp for
for (j = ({ int n; n = k; n; }); j <= l; j++)
;
#pragma omp for
for (j = k; j <= ({ int n; n = l; n; }); j++)
;
#pragma omp for
for (j = k; j <= l; j += ({ int n; n = 1; n; }))
;
#pragma omp for
for (j = k; j <= l; j += m + 1)
;
#pragma omp for
for (j = k; j <= l; j += o)
;
#pragma omp for
for (j = k; j <= l; j = j + o)
;
#pragma omp for
for (j = k; j <= l; j = o + 1 + j)
;
#pragma omp for
for (j = k; j <= l; j = o + m + j)
;
#pragma omp for
for (j = k; j <= l; j += o + p)
;
#pragma omp for
for (j = k; j <= l; j = j + o + p)
;
#pragma omp for
for (j = l; j >= k; j -= o)
;
#pragma omp for
for (j = l; j >= k; j -= p)
;
#pragma omp for
for (j = l; j >= k; j -= o + p)
;
}

View File

@ -0,0 +1,18 @@
/* { dg-do compile } */
void foo()
{
int i;
#pragma omp for nowait
for (i = 0; i < 10; ++i) ;
#pragma omp for nowait nowait /* { dg-error "too many" } */
for (i = 0; i < 10; ++i) ;
#pragma omp for ordered
for (i = 0; i < 10; ++i) ;
#pragma omp for ordered ordered /* { dg-error "too many" } */
for (i = 0; i < 10; ++i) ;
}

View File

@ -0,0 +1,62 @@
// { dg-do compile }
int bar ();
void foo()
{
int i;
#pragma omp for schedule // { dg-error "expected" }
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule static // { dg-error "expected" }
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( // { dg-error "invalid schedule kind" }
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( static // { dg-error "expected" }
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( static )
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( foo ) // { dg-error "invalid schedule kind" }
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( static 1 // { dg-error "expected" }
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( static 1 ) nowait // { dg-error "expected" }
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( static, 1 ) nowait
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( static, 1, 1 ) nowait // { dg-error "expected" }
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( static, 1 + 1 ) nowait
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule ( static, 1.0 ) // { dg-error "integral" }
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule (dynamic)
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule (dynamic, bar ())
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule (guided)
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule (guided, bar ())
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule (runtime)
for (i = 0; i < 10; ++i) ;
#pragma omp for schedule (runtime, bar ()) // { dg-error "does not take" }
for (i = 0; i < 10; ++i) ;
}

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
extern void bar(int);
void foo (int n)
{
int i;
#pragma omp for schedule(dynamic)
for (i = 0; i < n; ++i)
bar(i);
}
/* { dg-final { scan-tree-dump-times "GOMP_loop_dynamic_start" 1 "ompexp" } } */
/* { dg-final { scan-tree-dump-times "GOMP_loop_dynamic_next" 1 "ompexp" } } */
/* { dg-final { cleanup-tree-dump "ompexp" } } */

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
extern void bar(int);
void foo (int n)
{
int i;
#pragma omp for schedule(guided)
for (i = 0; i < n; ++i)
bar(i);
}
/* { dg-final { scan-tree-dump-times "GOMP_loop_guided_start" 1 "ompexp" } } */
/* { dg-final { scan-tree-dump-times "GOMP_loop_guided_next" 1 "ompexp" } } */
/* { dg-final { cleanup-tree-dump "ompexp" } } */

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
extern void bar(int);
void foo (int n)
{
int i;
#pragma omp for schedule(runtime)
for (i = 0; i < n; ++i)
bar(i);
}
/* { dg-final { scan-tree-dump-times "GOMP_loop_runtime_start" 1 "ompexp" } } */
/* { dg-final { scan-tree-dump-times "GOMP_loop_runtime_next" 1 "ompexp" } } */
/* { dg-final { cleanup-tree-dump "ompexp" } } */

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
extern void bar(int);
void foo (int n)
{
int i;
#pragma omp for schedule(static) ordered
for (i = 0; i < n; ++i)
bar(i);
}
/* { dg-final { scan-tree-dump-times "GOMP_loop_ordered_static_start" 1 "ompexp" } } */
/* { dg-final { scan-tree-dump-times "GOMP_loop_ordered_static_next" 1 "ompexp" } } */
/* { dg-final { cleanup-tree-dump "ompexp" } } */

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
extern void bar(int);
void foo (int n)
{
int i;
#pragma omp for schedule(dynamic) ordered
for (i = 0; i < n; ++i)
bar(i);
}
/* { dg-final { scan-tree-dump-times "GOMP_loop_ordered_dynamic_start" 1 "ompexp" } } */
/* { dg-final { scan-tree-dump-times "GOMP_loop_ordered_dynamic_next" 1 "ompexp" } } */
/* { dg-final { cleanup-tree-dump "ompexp" } } */

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
extern void bar(int);
void foo (int n)
{
int i;
#pragma omp for schedule(guided) ordered
for (i = 0; i < n; ++i)
bar(i);
}
/* { dg-final { scan-tree-dump-times "GOMP_loop_ordered_guided_start" 1 "ompexp" } } */
/* { dg-final { scan-tree-dump-times "GOMP_loop_ordered_guided_next" 1 "ompexp" } } */
/* { dg-final { cleanup-tree-dump "ompexp" } } */

View File

@ -0,0 +1,11 @@
# Load support procs.
load_lib g++-dg.exp
# Initialize `dg'.
dg-init
# Main loop.
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" "-fopenmp"
# All done.
dg-finish

View File

@ -0,0 +1,10 @@
// { dg-do compile }
#define N 10
extern void bar(void);
void foo(void)
{
#pragma omp parallel num_threads(N)
bar();
}

View File

@ -0,0 +1,14 @@
// { dg-do compile }
#define p parallel
#define s(x) shared(x##1, x##2)
#define d(x) default(x)
void bar(int, int, int, int);
void foo(void)
{
int a1, a2, b1, b2;
#pragma omp p s(a) s(b) d(none)
bar(a1, a2, b1, b2);
}

View File

@ -0,0 +1,22 @@
/* { dg-do compile } */
extern void bar(int);
void foo (void)
{
#pragma omp master
bar(0);
#pragma omp master
{
bar(1);
bar(2);
}
/* Yes, this is legal -- structured-block contains statement contains
openmp-construct contains master-construct. */
#pragma omp master
#pragma omp master
#pragma omp master
;
}

View File

@ -0,0 +1,7 @@
/* { dg-do compile } */
void f1(void)
{
#pragma omp master asdf /* { dg-error "expected" } */
#pragma omp master
} /* { dg-error "expected" } */

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-omplower" } */
extern void bar(int);
void foo (void)
{
#pragma omp master
bar(0);
}
/* { dg-final { scan-tree-dump-times "omp_get_thread_num" 1 "omplower" } } */
/* { dg-final { cleanup-tree-dump "omplower" } } */

View File

@ -0,0 +1,18 @@
/* PR c++/24513 */
/* { dg-do compile } */
struct S
{
void foo (int *p)
{
#pragma omp parallel for
for (int i = 0; i < 1000; ++i)
p[i]=0;
}
void bar ()
{
#pragma omp master
j = 2;
}
int j;
};

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-fopenmp -fdump-tree-omplower" } */
extern void bar(int);
void foo (void)
{
#pragma omp ordered
bar(0);
#pragma omp ordered
{
bar(1);
bar(2);
}
}
/* { dg-final { scan-tree-dump-times "GOMP_ordered_start" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "GOMP_ordered_end" 2 "omplower" } } */
/* { dg-final { cleanup-tree-dump "omplower" } } */

View File

@ -0,0 +1,7 @@
/* { dg-do compile } */
void f1(void)
{
#pragma omp ordered asdf /* { dg-error "expected" } */
#pragma omp ordered
} /* { dg-error "expected" } */

View File

@ -0,0 +1,17 @@
// { dg-do compile }
void foo()
{
int i;
#pragma omp parallel
{
#pragma omp parallel
{
#pragma omp parallel
{
i++;
}
}
}
}

View File

@ -0,0 +1,17 @@
// { dg-do compile }
void foo()
{
int i;
#pragma omp parallel default(none) // { dg-error "enclosing" }
{
#pragma omp parallel
{
#pragma omp parallel default(none) // { dg-error "enclosing" }
{
i++; // { dg-error "not specified" }
}
}
}
}

View File

@ -0,0 +1,15 @@
// { dg-do compile }
extern int printf (const char *, ...);
int main (void)
{
double d = 6;
int i = 1;
#pragma omp parallel shared(d) private(i) num_threads (4 + i)
{
i = 4;
printf ("%s %d %g\n", "Hello, World!", i, d);
}
return 0;
}

View File

@ -0,0 +1,24 @@
/* { dg-do compile } */
extern int foo(void);
extern void bar(void);
int main ()
{
/* Malformed uses of 'if' and 'num_threads'. */
#pragma omp parallel if (foo () > 10) if (foo () == 3) /* { dg-error "too many" } */
{
bar ();
}
#pragma omp parallel num_threads (3) num_threads (20) /* { dg-error "too many" } */
{
bar ();
}
/* Valid uses of 'if' and 'num_threads'. */
#pragma omp parallel if (foo () == 10) num_threads (foo ())
{
bar ();
}
}

View File

@ -0,0 +1,11 @@
// { dg-do compile }
extern void bar (void);
int main (void)
{
int i;
#pragma omp parallel for nowait /* { dg-error "'nowait'" } */
for (i = 0; i < 10; i++)
bar ();
}

View File

@ -0,0 +1,19 @@
/* { dg-do compile } */
template<typename T> struct Healpix_Map {
T *map;
int npix_;
void Import_nograde (const Healpix_Map<T> &orig) {
#pragma omp parallel
{
int m;
#pragma omp for schedule (dynamic)
for (m=0; m<npix_; ++m) map[m] = orig.map[m];
}
}
};
void foo(Healpix_Map<int> &a, Healpix_Map<int> &b) {
a.Import_nograde(b);
}

View File

@ -0,0 +1,23 @@
int foo();
struct wigner_d
{
void recurse () {
int dd;
for (int j=0; j<=1; ++j) {
#pragma omp parallel
dd=5;
}
}
};
template<typename T> void rotate_alm(T arg)
{
wigner_d rec;
rec.recurse();
#pragma omp parallel
foo();
}
template void rotate_alm(float arg);
template void rotate_alm(double arg);

View File

@ -0,0 +1,39 @@
/* { dg-do compile } */
extern void bar(int);
void f1(void)
{
#pragma omp sections nowait
{
bar (1);
#pragma omp section
bar (2);
#pragma omp section
bar (3);
#pragma omp section
bar (4);
#pragma omp section
bar (5);
}
}
void f2(void)
{
#pragma omp sections
{
#pragma omp section
{
bar (1);
bar (1);
}
#pragma omp section
bar (2);
#pragma omp section
bar (3);
#pragma omp section
bar (4);
#pragma omp section
bar (5);
}
}

View File

@ -0,0 +1,29 @@
/* { dg-do compile } */
extern void bar(int);
void foo(void)
{
#pragma omp sections
bar (0); // { dg-error "expected" }
#pragma omp sections
{
} // { dg-error "expected" }
#pragma omp sections
{
bar (1);
}
#pragma omp sections
{
#pragma omp section
bar(2);
bar(3); // { dg-error "expected" }
bar(4);
#pragma omp section
bar(5);
bar(6); // { dg-error "expected" }
bar(7);
}
}

View File

@ -0,0 +1,15 @@
// { dg-do compile }
extern void bar (void);
int main (void)
{
#pragma omp parallel sections nowait /* { dg-error "'nowait'" } */
{
#pragma omp section
{ bar(); }
#pragma omp section
{ bar(); }
}
}

View File

@ -0,0 +1,13 @@
/* PR c++/24613 */
/* { dg-compile } */
#pragma omp section /* { dg-error "may only be used in" } */
int i;
void
foo (void)
{
#pragma omp section /* { dg-error "may only be used in" } */
i++;
}

View File

@ -0,0 +1,77 @@
/* { dg-do compile } */
/* { dg-require-effective-target tls } */
int thrglobalvar;
#pragma omp threadprivate (thrglobalvar)
int globalvar;
const struct S
{
int x;
} constvar = { 8 };
struct T
{
static T t;
int i;
};
T T::t = { 6 };
/* const qualified type, but mutable member -> not predetermined. */
const struct U
{
int x;
mutable int y;
} constmutvar = { 6, 4 };
int
foo (int x)
{
return x;
}
int
bar (int *x)
{
return *x;
}
int
baz (U u)
{
return u.x;
}
int
main (void)
{
static int thrlocvar;
#pragma omp threadprivate (thrlocvar)
static int locvar;
static int *p;
int i, j, s, l;
p = new int;
*p = 7;
s = 6;
l = 0;
#pragma omp parallel for /* { dg-error "enclosing parallel" } */ \
default (none) private (p) shared (s)
for (i = 0; i < 64; i++)
{
int k = foo (0); /* Predetermined - private (automatic var declared */
k++; /* in scope of construct). */
thrglobalvar++; /* Predetermined - threadprivate. */
thrlocvar++; /* Predetermined - threadprivate. */
foo (i); /* Predetermined - private (omp for loop variable). */
foo (constvar.x); /* Predetermined - shared (const qualified type). */
foo (T::t.i); /* Predetermined - shared (static data member). */
foo (*p); /* *p predetermined - shared (heap allocated */
(*p)++; /* storage). */
bar (p); /* Explicitly determined - private. */
foo (s); /* Explicitly determined - shared. */
globalvar++; /* { dg-error "not specified in" } */
locvar++; /* { dg-error "not specified in" } */
l++; /* { dg-error "not specified in" } */
for (j = 0; j < 2; j++); /* { dg-error "not specified in" } */
baz (constmutvar);/* { dg-error "not specified in" } */
}
return 0;
}

View File

@ -0,0 +1,18 @@
// { dg-do compile }
// { dg-require-effective-target tls }
int tp1;
static int tp2;
extern int tp3;
int tp4 = 1;
static int tp5 = 1;
#pragma omp threadprivate (tp1, tp2, tp3, tp4, tp5)
#pragma omp threadprivate (undef) // { dg-error "declared" }
int tp6;
int foo(void) { return tp6; }
#pragma omp threadprivate (tp6) // { dg-error "after first use" }

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-require-effective-target tls } */
extern char buf[];
#pragma omp threadprivate (buf) /* { dg-error "has incomplete type" } */
void
foo (void)
{
int i;
#pragma omp threadprivate (i) /* { dg-error "automatic variable" } */
i = 0;
}

View File

@ -0,0 +1,25 @@
// { dg-do compile }
// { dg-require-effective-target tls }
#define thr threadprivate
int i;
#pragma omp thr (i)
namespace N
{
int j;
#pragma omp thr (j)
};
struct S
{
static int s;
#pragma omp thr (s) // { dg-error "is not file, namespace or block scope" }
};
int
foo ()
{
static int k;
#pragma omp thr (k)
return k++ + S::s;
}

View File

@ -0,0 +1,26 @@
// { dg-do compile }
int check;
template<typename T> void foo()
{
#pragma omp atomic
check |= sizeof(T);
}
template<typename T> void bar(T *x, T y)
{
#pragma omp atomic
*x += y;
}
void test ()
{
int i;
long l;
foo<char>();
foo<short>();
bar(&i, 4);
bar(&l, 8L);
}

View File

@ -0,0 +1,41 @@
// { dg-do compile }
struct S { int x; } s;
// Make sure we detect errors on non-type-dependent things
// even when the templates are never instantiated.
template<typename T> void f1()
{
#pragma omp atomic
s += 1; // { dg-error "invalid" }
}
template<typename T> void f2(float *f)
{
#pragma omp atomic
*f |= 1; // { dg-error "invalid|evaluation" }
}
// Here the rhs is dependent, but not type dependent.
// ??? Fails. See the comment in finish_omp_atomic.
template<typename T> void f3(float *f)
{
#pragma omp atomic
*f |= sizeof (T); // { dg-error "invalid|evaluation" "" { xfail *-*-* } }
}
// And the converse, no error here because we're never fed a T.
template<typename T> void f4(T *t)
{
#pragma omp atomic
*t += 1;
}
// Here we'll let it go, because the rhs is type dependent and
// we can't properly instantiate the statement, and we do most
// of the semantic analysis concurrent with that.
template<typename T> void f5(float *f)
{
#pragma omp atomic
*f |= (T)sizeof(T); // { dg-error "invalid|evaluation" "" { xfail *-*-* } }
}

View File

@ -0,0 +1,25 @@
// PR c++/24735
// { dg-do compile }
// { dg-options "-fopenmp -fdump-tree-gimple" }
template <int> void f1 ()
{
#pragma omp barrier
}
template <int> void f2 (bool p)
{
if (p)
{
#pragma omp barrier
}
}
void f3 ()
{
f1<0> ();
f2<0> (true);
}
// { dg-final { scan-tree-dump-times "GOMP_barrier" 2 "gimple" } }
// { dg-final { cleanup-tree-dump "gimple" } }

View File

@ -0,0 +1,17 @@
// { dg-do compile }
void foo(int);
void foo(long);
template<typename T> void bar()
{
#pragma omp for
for (T i = 0; i < 10; ++i)
foo(i);
}
void test()
{
bar<int>();
bar<long>();
}

View File

@ -0,0 +1,15 @@
// { dg-do compile }
void foo(int);
template<int A, int B, int C> void bar()
{
#pragma omp for
for (int i = A; i < B; i += C)
foo(i);
}
void test()
{
bar<0, 10, 2>();
}

View File

@ -0,0 +1,28 @@
// { dg-do compile }
void foo(int);
template<typename T> void bar()
{
#pragma omp parallel for
for (typename T::T i = 0; i < T::N; ++i)
foo(i);
}
struct A
{
typedef int T;
static T N;
};
struct B
{
typedef long T;
static T N;
};
void test()
{
bar<A>();
bar<B>();
}

View File

@ -0,0 +1,30 @@
// PR c++/24734
// { dg-do compile }
// { dg-options "-fopenmp -fdump-tree-gimple" }
int i;
template <int> void f1 ()
{
#pragma omp ordered
i++;
}
template <int> void f2 (bool p)
{
if (p)
{
#pragma omp master
i++;
}
}
void f3 ()
{
f1<0> ();
f2<0> (true);
}
// { dg-final { scan-tree-dump-times "#pragma omp ordered" 1 "gimple" } }
// { dg-final { scan-tree-dump-times "#pragma omp master" 1 "gimple" } }
// { dg-final { cleanup-tree-dump "gimple" } }

View File

@ -0,0 +1,24 @@
// { dg-do compile }
int check;
template<typename T> void foo()
{
check |= sizeof(T);
}
template<typename T>
void bar(void)
{
#pragma omp parallel if (0)
foo<T>();
}
int main()
{
bar<char>();
bar<short>();
if (check != (sizeof(char) | sizeof(short)))
__builtin_trap ();
return 0;
}

View File

@ -0,0 +1,20 @@
// { dg-do compile }
template<typename T>
struct S
{
T n;
void test();
void work();
};
template<typename T>
void S<T>::test()
{
#pragma omp parallel num_threads(n) // { dg-error "must be integral" }
work();
}
template struct S<int>;
template struct S<long>;
template struct S<float>; // { dg-error "instantiated from here" }

View File

@ -4736,6 +4736,8 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
if (uid >= dest_cfun->last_label_uid)
dest_cfun->last_label_uid = uid + 1;
}
remove_stmt_from_eh_region (stmt);
}
}

View File

@ -1,3 +1,7 @@
2006-03-09 Diego Novillo <dnovillo@redhat.com>
* testsuite/libgomp.c++: New directory.
2006-02-25 Shantonu Sen <ssen@opendarwin.org>
* config/posix/sem.h: Define BROKEN_POSIX_SEMAPHORES functions.

View File

@ -0,0 +1,20 @@
set lang_library_path "../libstdc++-v3/src/.libs"
set lang_test_file "${lang_library_path}/libstdc++.a"
set lang_link_flags "-lstdc++"
load_lib libgomp-dg.exp
# Initialize dg.
dg-init
if [file exists "${blddir}/${lang_test_file}"] {
# Gather a list of all tests.
set tests [lsort [glob -nocomplain $srcdir/$subdir/*.C]]
# Main loop.
gfortran-dg-runtest $tests ""
}
# All done.
dg-finish

View File

@ -0,0 +1,34 @@
// { dg-do run }
// { dg-require-effective-target tls_runtime }
#include <omp.h>
extern "C" void abort (void);
int thr = 32;
#pragma omp threadprivate (thr)
int
main (void)
{
int l = 0;
omp_set_dynamic (0);
omp_set_num_threads (6);
#pragma omp parallel copyin (thr) reduction (||:l)
{
l = thr != 32;
thr = omp_get_thread_num () + 11;
}
if (l || thr != 11)
abort ();
#pragma omp parallel reduction (||:l)
l = thr != omp_get_thread_num () + 11;
if (l)
abort ();
return 0;
}

Some files were not shown because too many files have changed in this diff Show More