Reorder IDENTIFIER flags gcc/cp/ * cp-tree.h (enum cp_identifier_kind): New. (IDENTIFIER_KIND_BIT_0, IDENTIFIER_KIND_BIT_1, IDENTIFIER_KIND_BIT_2): New. (IDENTIFIER_MARKED): Move to TREE_LANG_FLAG_4. (IDENTIFIER_VIRTUAL_P, IDENTIFIER_REPO_CHOSEN): Add IDENTIFIER_CHECK. (C_IS_RESERVED_WORD): Replace with ... (IDENTIFIER_KEYWORD_P): ... this. (IDENTIFIER_CTOR_OR_DTOR_P): Replace with ... (IDENTIFIER_CDTOR_P): ... this. (IDENTIFIER_CTOR_P, IDENTIFIER_DTOR_P): New. (IDENTIFIER_OPNAME_P): Replace with ... (IDENTIFIER_ANY_OP_P): ... this. (IDENTIFIER_ASSIGN_OP_P): New. (IDENTIFIER_TYPENAME_P): Replace with ... (IDENTIFIER_CONV_OP_P): ... this. (NEW_DELETE_OPNAME_P): Replace with ... (IDENTIFIER_NEWDEL_OP_P): ... this. (DECL_CONV_FN_P, DECL_OVERLOADED_OPERATOR_P): Adjust. (get_identifier_kind_name, set_identifier_kind): Declare. * lex.c (get_identifier_kind_name, set_identifier_kind): New. (init_operators): Adjust to avoid keywords, use set_identifier_kind. Copy TYPE_EXPR slot. (init_reswords): Call set_identifier_kind. (unqualified_name_lookup_error): Adjust. * operators.def (TYPE_EXPR): Remove. * decl.c (struct predefined_identifier): Move into ... (initialize_predefined_identifiers): ... here. Call set_identifier_kind. (grokfndecl, check_var_type, grokdeclarator): Adjust. (grok_op_properties): Use IDENTIFIER_ANY_ASSIGN_OP to halve search space. Adjust. * call.c (name_as_c_string): Adjust. (build_new_method_call_1): Likewise. * cp-cilkplus.c (is_conversion_operator_function_decl_p): Likewise. * cxx-pretty-print.c (pp_cxx_unqualified_id): Adjust. * dump.c (cp_dump_tree): Adjust. * error.c (dump_decl_name): Adjust. * mangle.c (write_unqualified_id, write_member_name) write_expression): Adjust. (mangle_conv_op_name_for_type): Use set_identifier_kind. * name-lookup.c (do_class_using_decl): Adjust. (lookup_name_fuzzy, lookup_name_real_1): Likewise. * parser.c (cp_lexer_get_preprocessor_token) cp_parser_direct_declarator): Likewise. * pt.c (push_template_decl_real, tsubst_decl, tsubst_baselink) tsubst_copy, tsubst_copy_and_build): Adjust. * ptree.c (cxx_print_identifier): Print identifier kind. * search.c (lookup_field_r, lookup_member) lookup_fnfields_idx_nolazy): Adjust. * semantics.c (finish_id_expression): Adjust.. * typeck.c (cp_build_addr_expr_1): Adjust. From-SVN: r249571
241 lines
7.1 KiB
C
241 lines
7.1 KiB
C
/* This file is part of the Intel(R) Cilk(TM) Plus support
|
|
This file contains routines to handle Cilk Plus specific
|
|
routines for the C++ Compiler.
|
|
Copyright (C) 2013-2017 Free Software Foundation, Inc.
|
|
Contributed by Aldy Hernandez <aldyh@redhat.com>.
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "cp-tree.h"
|
|
#include "tree-iterator.h"
|
|
#include "cilk.h"
|
|
#include "c-family/c-common.h"
|
|
|
|
/* Return TRUE if T is a FUNCTION_DECL for a type-conversion operator. */
|
|
|
|
static bool
|
|
is_conversion_operator_function_decl_p (tree t)
|
|
{
|
|
if (TREE_CODE (t) != FUNCTION_DECL)
|
|
return false;
|
|
|
|
return DECL_CONV_FN_P (t);
|
|
}
|
|
|
|
/* Recursively traverse EXP to search for a CILK_SPAWN_STMT subtree.
|
|
Return the CILK_SPAWN_STMT subtree if found; otherwise, the last subtree
|
|
searched. */
|
|
|
|
static tree
|
|
find_spawn (tree exp)
|
|
{
|
|
/* Happens with C++ TARGET_EXPR. */
|
|
if (exp == NULL_TREE)
|
|
return exp;
|
|
|
|
if (cilk_ignorable_spawn_rhs_op (exp))
|
|
return find_spawn (TREE_OPERAND (exp, 0));
|
|
|
|
switch (TREE_CODE (exp))
|
|
{
|
|
case AGGR_INIT_EXPR:
|
|
{
|
|
/* Check for initialization via a constructor call that represents
|
|
implicit conversion. */
|
|
if (AGGR_INIT_VIA_CTOR_P (exp) && aggr_init_expr_nargs (exp) == 2)
|
|
return find_spawn (AGGR_INIT_EXPR_ARG (exp, 1));
|
|
|
|
/* Check for initialization via a call to a type-conversion
|
|
operator. */
|
|
tree fn = AGGR_INIT_EXPR_FN (exp);
|
|
if (TREE_CODE (fn) == ADDR_EXPR
|
|
&& is_conversion_operator_function_decl_p (TREE_OPERAND (fn, 0))
|
|
&& aggr_init_expr_nargs (exp) == 1)
|
|
return find_spawn (AGGR_INIT_EXPR_ARG (exp, 0));
|
|
}
|
|
break;
|
|
|
|
case CALL_EXPR:
|
|
{
|
|
/* Check for a call to a type-conversion operator. */
|
|
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
|
|
if (is_conversion_operator_function_decl_p (fndecl)
|
|
&& call_expr_nargs (exp) == 1)
|
|
return find_spawn (CALL_EXPR_ARG (exp, 0));
|
|
}
|
|
break;
|
|
|
|
case TARGET_EXPR:
|
|
return find_spawn (TARGET_EXPR_INITIAL (exp));
|
|
|
|
case CLEANUP_POINT_EXPR:
|
|
case COMPOUND_EXPR:
|
|
case EXPR_STMT:
|
|
return find_spawn (TREE_OPERAND (exp, 0));
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return exp;
|
|
}
|
|
|
|
/* Return true if *EXP0 is a recognized form of spawn. Recognized forms
|
|
are, after conversion to void, a call expression at outer level or an
|
|
assignment at outer level with the right hand side being a spawned call.
|
|
In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the
|
|
CALL_EXPR that is being spawned.
|
|
|
|
Note that `=' in C++ may turn into a CALL_EXPR rather than a
|
|
MODIFY_EXPR. */
|
|
|
|
bool
|
|
cilk_cp_detect_spawn_and_unwrap (tree *exp0)
|
|
{
|
|
tree exp = *exp0;
|
|
|
|
if (!TREE_SIDE_EFFECTS (exp))
|
|
return false;
|
|
|
|
/* Strip off any conversion to void. It does not affect whether spawn
|
|
is supported here. */
|
|
if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp)))
|
|
exp = TREE_OPERAND (exp, 0);
|
|
|
|
if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR)
|
|
exp = TREE_OPERAND (exp, 1);
|
|
|
|
exp = find_spawn (exp);
|
|
if (exp == NULL_TREE)
|
|
return false;
|
|
|
|
/* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around
|
|
it, or return false. */
|
|
return cilk_recognize_spawn (exp, exp0);
|
|
}
|
|
|
|
/* Callback for cp_walk_tree to validate the body of a pragma simd loop
|
|
or _cilk_for loop.
|
|
|
|
This function is passed in as a function pointer to walk_tree. *TP is
|
|
the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
|
|
recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
|
|
is set to false if an error has occurred. */
|
|
|
|
static tree
|
|
cpp_validate_cilk_plus_loop_aux (tree *tp, int *walk_subtrees, void *data)
|
|
{
|
|
bool *valid = (bool *) data;
|
|
|
|
if (!tp || !*tp)
|
|
return NULL_TREE;
|
|
|
|
location_t loc = EXPR_LOCATION (*tp);
|
|
if (TREE_CODE (*tp) == THROW_EXPR)
|
|
{
|
|
error_at (loc, "throw expressions are not allowed inside loops "
|
|
"marked with pragma simd");
|
|
*walk_subtrees = 0;
|
|
*valid = false;
|
|
}
|
|
else if (TREE_CODE (*tp) == TRY_BLOCK)
|
|
{
|
|
error_at (loc, "try statements are not allowed inside loops marked "
|
|
"with #pragma simd");
|
|
*valid = false;
|
|
*walk_subtrees = 0;
|
|
}
|
|
return NULL_TREE;
|
|
}
|
|
|
|
|
|
/* Walks through all the subtrees of BODY using walk_tree to make sure
|
|
invalid statements/expressions are not found inside BODY. Returns
|
|
false if any invalid statements are found. */
|
|
|
|
bool
|
|
cpp_validate_cilk_plus_loop (tree body)
|
|
{
|
|
bool valid = true;
|
|
cp_walk_tree (&body, cpp_validate_cilk_plus_loop_aux,
|
|
(void *) &valid, NULL);
|
|
return valid;
|
|
}
|
|
|
|
/* Sets the EXCEPTION bit (0x10) in the FRAME.flags field. */
|
|
|
|
static tree
|
|
set_cilk_except_flag (tree frame)
|
|
{
|
|
tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, 0);
|
|
|
|
flags = build2 (MODIFY_EXPR, void_type_node, flags,
|
|
build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags,
|
|
build_int_cst (TREE_TYPE (flags),
|
|
CILK_FRAME_EXCEPTING)));
|
|
return flags;
|
|
}
|
|
|
|
/* Sets the frame.EXCEPT_DATA field to the head of the exception pointer. */
|
|
|
|
static tree
|
|
set_cilk_except_data (tree frame)
|
|
{
|
|
tree except_data = cilk_dot (frame, CILK_TI_FRAME_EXCEPTION, 0);
|
|
tree uresume_fn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
|
|
tree ret_expr;
|
|
uresume_fn = build_call_expr (uresume_fn, 1,
|
|
build_int_cst (integer_type_node, 0));
|
|
ret_expr = build2 (MODIFY_EXPR, void_type_node, except_data, uresume_fn);
|
|
return ret_expr;
|
|
}
|
|
|
|
/* Installs BODY into function FNDECL with appropriate exception handling
|
|
code. WD holds information of wrapper function used to pass into the
|
|
outlining function, cilk_outline. */
|
|
|
|
void
|
|
cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
|
|
{
|
|
tree frame = make_cilk_frame (fndecl);
|
|
tree dtor = create_cilk_function_exit (frame, false, false);
|
|
add_local_decl (cfun, frame);
|
|
|
|
cfun->language = ggc_cleared_alloc<language_function> ();
|
|
|
|
location_t loc = EXPR_LOCATION (orig_body);
|
|
tree list = alloc_stmt_list ();
|
|
DECL_SAVED_TREE (fndecl) = list;
|
|
tree body = alloc_stmt_list ();
|
|
cilk_outline (fndecl, &orig_body, (struct wrapper_data *) wd);
|
|
append_to_statement_list (orig_body, &body);
|
|
if (flag_exceptions)
|
|
{
|
|
tree except_flag = set_cilk_except_flag (frame);
|
|
tree except_data = set_cilk_except_data (frame);
|
|
tree catch_list = alloc_stmt_list ();
|
|
append_to_statement_list (except_flag, &catch_list);
|
|
append_to_statement_list (except_data, &catch_list);
|
|
body = create_try_catch_expr (body, catch_list);
|
|
}
|
|
append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, body, dtor),
|
|
&list);
|
|
}
|