parent
f8fe05458d
commit
1799e5d5ca
|
@ -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
|
||||
|
|
497
gcc/cp/ChangeLog
497
gcc/cp/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
572
gcc/cp/decl.c
572
gcc/cp/decl.c
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
1336
gcc/cp/parser.c
1336
gcc/cp/parser.c
File diff suppressed because it is too large
Load Diff
119
gcc/cp/pt.c
119
gcc/cp/pt.c
|
@ -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)));
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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" } } */
|
|
@ -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;
|
||||
}
|
|
@ -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 "" } */
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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 "" }
|
|
@ -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" } }
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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" }
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// { dg-do compile }
|
||||
|
||||
void foo()
|
||||
{
|
||||
#pragma omp critical
|
||||
{
|
||||
return; // { dg-error "invalid exit" }
|
||||
}
|
||||
}
|
|
@ -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" }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// { dg-do compile }
|
||||
|
||||
void foo()
|
||||
{
|
||||
#pragma omp ordered
|
||||
{
|
||||
return; // { dg-error "invalid exit" }
|
||||
}
|
||||
}
|
|
@ -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" }
|
||||
}
|
||||
}
|
|
@ -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" }
|
||||
}
|
|
@ -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" }
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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(); }
|
||||
}
|
|
@ -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'" }
|
||||
;
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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" } } */
|
|
@ -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 "" }
|
|
@ -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" } } */
|
|
@ -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" }
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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" } } */
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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" } }
|
|
@ -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;
|
||||
}
|
|
@ -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> ();
|
||||
}
|
|
@ -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" }
|
||||
}
|
|
@ -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) ;
|
||||
}
|
|
@ -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)
|
||||
;
|
||||
}
|
|
@ -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) ;
|
||||
}
|
|
@ -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) ;
|
||||
}
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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
|
|
@ -0,0 +1,10 @@
|
|||
// { dg-do compile }
|
||||
|
||||
#define N 10
|
||||
|
||||
extern void bar(void);
|
||||
void foo(void)
|
||||
{
|
||||
#pragma omp parallel num_threads(N)
|
||||
bar();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/* { dg-do compile } */
|
||||
|
||||
void f1(void)
|
||||
{
|
||||
#pragma omp master asdf /* { dg-error "expected" } */
|
||||
#pragma omp master
|
||||
} /* { dg-error "expected" } */
|
|
@ -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" } } */
|
|
@ -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;
|
||||
};
|
|
@ -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" } } */
|
|
@ -0,0 +1,7 @@
|
|||
/* { dg-do compile } */
|
||||
|
||||
void f1(void)
|
||||
{
|
||||
#pragma omp ordered asdf /* { dg-error "expected" } */
|
||||
#pragma omp ordered
|
||||
} /* { dg-error "expected" } */
|
|
@ -0,0 +1,17 @@
|
|||
// { dg-do compile }
|
||||
|
||||
void foo()
|
||||
{
|
||||
int i;
|
||||
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp parallel
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 ();
|
||||
}
|
||||
}
|
|
@ -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 ();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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(); }
|
||||
}
|
||||
}
|
|
@ -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++;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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" }
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 *-*-* } }
|
||||
}
|
|
@ -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" } }
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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" } }
|
|
@ -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;
|
||||
}
|
|
@ -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" }
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue