Hi I made the corrections to the patch. Changelog 2016-5-6 Andres Tiraboschi <andres.tirabos...@tallertechnologies.com> *gcc/plugin.c (PLUGIN_EVAL_CALL_CONSTEXPR): New event. *gcc/plugin.def (PLUGIN_EVAL_CALL_CONSTEXPR): New event. *gcc/cp/constexpr.c (constexpr_fundef): Moved to gcc/cp/constexpr.h. *gcc/cp/constexpr.c (constexpr_call): Ditto. *gcc/cp/constexpr.c (constexpr_ctx): Ditto. *gcc/cp/constexpr.c (eval_call_pugin_callback): New Function. *gcc/cp/constexpr.c (cxx_eval_constant_expression): Added a call to eval_call_pugin_callback. *gcc/cp/constexpr.c (cxx_eval_constant_expression): Not static anymore. *gcc/cp/constexpr.c (cxx_bind_parameters_in_call): Ditto. *gcc/cp/constexpr.h: New file. *gcc/cp/constexpr.h (constexpr_call_info): New Type. *gcc/cp/constexpr.h (constexpr_fundef): Moved type from gcc/cp/constexpr.c. *gcc/cp/constexpr.h (constexpr_call): Ditto. *gcc/cp/constexpr.h (constexpr_ctx): Ditto. *gcc/cp/constexpr.h (cxx_eval_constant_expression): Declared. *gcc/cp/constexpr.h (cxx_bind_parameters_in_call): Declared *gcc/cp/config-lang.in (gtfiles): Added \$(srcdir)/cp/constexpr.h *gcc/cp/Make-lang.in (CP_PLUGIN_HEADERS): Added constexpr.h.
2016-05-05 10:29 GMT-03:00 Andres Tiraboschi <andres.tirabos...@tallertechnologies.com>: > Hi, > thanks for the feedback, I'll do the changes. > > 2016-05-04 13:16 GMT-03:00 Jason Merrill <ja...@redhat.com>: >> On 05/02/2016 03:28 PM, Andres Tiraboschi wrote: >>> >>> + constexpr_call_info call_info; >>> + call_info.function = t; >>> + call_info.call_stack = call_stack; >>> + call_info.ctx = ctx; >>> + call_info.lval_p = lval; >>> + call_info.non_constant_p = non_constant_p; >>> + call_info.overflow_p = overflow_p; >>> + call_info.result = NULL_TREE; >>> + >>> + invoke_plugin_callbacks (PLUGIN_EVAL_CALL_CONSTEXPR, &call_info); >> >> >> Let's move this into a separate function so that it doesn't increase the >> stack footprint of cxx_eval_call_expression. >> >> Jason >>
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 625a77c..025ebc1 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -39,7 +39,7 @@ CXX_INSTALL_NAME := $(shell echo c++|sed '$(program_transform_name)') GXX_INSTALL_NAME := $(shell echo g++|sed '$(program_transform_name)') CXX_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo c++|sed '$(program_transform_name)') GXX_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo g++|sed '$(program_transform_name)') -CP_PLUGIN_HEADERS := cp-tree.h cxx-pretty-print.h name-lookup.h type-utils.h +CP_PLUGIN_HEADERS := cp-tree.h cxx-pretty-print.h name-lookup.h type-utils.h constexpr.h # # Define the names for selecting c++ in LANGUAGES. diff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in index 276fc1d..2ca4d03 100644 --- a/gcc/cp/config-lang.in +++ b/gcc/cp/config-lang.in @@ -29,4 +29,4 @@ compilers="cc1plus\$(exeext)" target_libs="target-libstdc++-v3" -gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c" +gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.h \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c" diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 6054d1a..7c50b06 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -31,6 +31,9 @@ along with GCC; see the file COPYING3. If not see #include "builtins.h" #include "tree-inline.h" #include "ubsan.h" +#include "constexpr.h" +#include "plugin-api.h" +#include "plugin.h" static bool verify_constant (tree, bool, bool *, bool *); #define VERIFY_CONSTANT(X) \ @@ -112,13 +115,6 @@ ensure_literal_type_for_constexpr_object (tree decl) return decl; } -/* Representation of entries in the constexpr function definition table. */ - -struct GTY((for_user)) constexpr_fundef { - tree decl; - tree body; -}; - struct constexpr_fundef_hasher : ggc_ptr_hash<constexpr_fundef> { static hashval_t hash (constexpr_fundef *); @@ -856,70 +852,17 @@ explain_invalid_constexpr_fn (tree fun) input_location = save_loc; } -/* Objects of this type represent calls to constexpr functions - along with the bindings of parameters to their arguments, for - the purpose of compile time evaluation. */ - -struct GTY((for_user)) constexpr_call { - /* Description of the constexpr function definition. */ - constexpr_fundef *fundef; - /* Parameter bindings environment. A TREE_LIST where each TREE_PURPOSE - is a parameter _DECL and the TREE_VALUE is the value of the parameter. - Note: This arrangement is made to accommodate the use of - iterative_hash_template_arg (see pt.c). If you change this - representation, also change the hash calculation in - cxx_eval_call_expression. */ - tree bindings; - /* Result of the call. - NULL means the call is being evaluated. - error_mark_node means that the evaluation was erroneous; - otherwise, the actuall value of the call. */ - tree result; - /* The hash of this call; we remember it here to avoid having to - recalculate it when expanding the hash table. */ - hashval_t hash; -}; - struct constexpr_call_hasher : ggc_ptr_hash<constexpr_call> { static hashval_t hash (constexpr_call *); static bool equal (constexpr_call *, constexpr_call *); }; -/* The constexpr expansion context. CALL is the current function - expansion, CTOR is the current aggregate initializer, OBJECT is the - object being initialized by CTOR, either a VAR_DECL or a _REF. VALUES - is a map of values of variables initialized within the expression. */ - -struct constexpr_ctx { - /* The innermost call we're evaluating. */ - constexpr_call *call; - /* Values for any temporaries or local variables within the - constant-expression. */ - hash_map<tree,tree> *values; - /* SAVE_EXPRs that we've seen within the current LOOP_EXPR. NULL if we - aren't inside a loop. */ - hash_set<tree> *save_exprs; - /* The CONSTRUCTOR we're currently building up for an aggregate - initializer. */ - tree ctor; - /* The object we're building the CONSTRUCTOR for. */ - tree object; - /* Whether we should error on a non-constant expression or fail quietly. */ - bool quiet; - /* Whether we are strictly conforming to constant expression rules or - trying harder to get a constant value. */ - bool strict; -}; - /* A table of all constexpr calls that have been evaluated by the compiler in this translation unit. */ static GTY (()) hash_table<constexpr_call_hasher> *constexpr_call_table; -static tree cxx_eval_constant_expression (const constexpr_ctx *, tree, - bool, bool *, bool *, tree * = NULL); - /* Compute a hash value for a constexpr call representation. */ inline hashval_t @@ -1167,7 +1110,7 @@ unshare_constructor (tree t) all arguments and bind their values to correspondings parameters, making up the NEW_CALL context. */ -static void +void cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, constexpr_call *new_call, bool *non_constant_p, bool *overflow_p, @@ -1255,6 +1198,24 @@ cx_error_context (void) return r; } +static tree +eval_call_plugin_callback (const constexpr_ctx *ctx, tree fun, + bool lval, bool *non_constant_p, bool *overflow_p) +{ + constexpr_call_info call_info; + call_info.function = fun; + call_info.call_stack = call_stack; + call_info.ctx = ctx; + call_info.lval_p = lval; + call_info.non_constant_p = non_constant_p; + call_info.overflow_p = overflow_p; + call_info.result = NULL_TREE; + + invoke_plugin_callbacks (PLUGIN_EVAL_CALL_CONSTEXPR, &call_info); + + return call_info.result; +} + /* Subroutine of cxx_eval_constant_expression. Evaluate the call expression tree T in the context of OLD_CALL expression evaluation. */ @@ -1268,6 +1229,13 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, tree fun = get_function_named_in_call (t); constexpr_call new_call = { NULL, NULL, NULL, 0 }; bool depth_ok; + const tree callback_result = eval_call_plugin_callback (ctx, t, lval, + non_constant_p, + overflow_p); + + if (callback_result != NULL_TREE) + return callback_result; + if (fun == NULL_TREE) switch (CALL_EXPR_IFN (t)) @@ -3461,7 +3429,7 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t, /* FIXME unify with c_fully_fold */ /* FIXME overflow_p is too global */ -static tree +tree cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, bool *non_constant_p, bool *overflow_p, diff --git a/gcc/cp/constexpr.h b/gcc/cp/constexpr.h new file mode 100644 index 0000000..411c57b --- /dev/null +++ b/gcc/cp/constexpr.h @@ -0,0 +1,117 @@ +/* Structures and functions for constexpr processing. + Copyright (C) 2016 Free Software Foundation, Inc. + +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/>. */ + +#ifndef GCC_CONSTEXPR_H +#define GCC_CONSTEXPR_H + +#include "cp-tree.h" + +/* Representation of entries in the constexpr function definition table. */ + +struct GTY((for_user)) constexpr_fundef { + tree decl; + tree body; +}; + +/* Objects of this type represent calls to constexpr functions + along with the bindings of parameters to their arguments, for + the purpose of compile time evaluation. */ + +struct GTY((for_user)) constexpr_call { + /* Description of the constexpr function definition. */ + constexpr_fundef *fundef; + /* Parameter bindings environment. A TREE_LIST where each TREE_PURPOSE + is a parameter _DECL and the TREE_VALUE is the value of the parameter. + Note: This arrangement is made to accommodate the use of + iterative_hash_template_arg (see pt.c). If you change this + representation, also change the hash calculation in + cxx_eval_call_expression. */ + tree bindings; + /* Result of the call. + NULL means the call is being evaluated. + error_mark_node means that the evaluation was erroneous; + otherwise, the actuall value of the call. */ + tree result; + /* The hash of this call; we remember it here to avoid having to + recalculate it when expanding the hash table. */ + hashval_t hash; +}; + +/* The constexpr expansion context. CALL is the current function + expansion, CTOR is the current aggregate initializer, OBJECT is the + object being initialized by CTOR, either a VAR_DECL or a _REF. VALUES + is a map of values of variables initialized within the expression. */ + +struct constexpr_ctx { + /* The innermost call we're evaluating. */ + constexpr_call *call; + /* Values for any temporaries or local variables within the + constant-expression. */ + hash_map<tree,tree> *values; + /* SAVE_EXPRs that we've seen within the current LOOP_EXPR. NULL if we + aren't inside a loop. */ + hash_set<tree> *save_exprs; + /* The CONSTRUCTOR we're currently building up for an aggregate + initializer. */ + tree ctor; + /* The object we're building the CONSTRUCTOR for. */ + tree object; + /* Whether we should error on a non-constant expression or fail quietly. */ + bool quiet; + /* Whether we are strictly conforming to constant expression rules or + trying harder to get a constant value. */ + bool strict; +}; + +/* This type represents a function call into a constant expression.*/ +struct constexpr_call_info +{ + /* Function named in call. */ + tree function; + /* Current call stack.*/ + vec<tree> call_stack; + /* constexpr expansion context. */ + const constexpr_ctx* ctx; + bool lval_p; + /* Is constant. */ + bool* non_constant_p; + bool* overflow_p; + /* Function call result. */ + tree result; + +}; + + +/* Attempt to reduce the expression T to a constant value. + On failure, issue diagnostic and return error_mark_node. */ +tree cxx_eval_constant_expression (const constexpr_ctx *, tree, + bool, bool *, bool *, tree * = NULL); + + +/* Subroutine of cxx_eval_call_expression. + We are processing a call expression (either CALL_EXPR or + AGGR_INIT_EXPR) in the context of CTX. Evaluate + all arguments and bind their values to correspondings + parameters, making up the NEW_CALL context. */ +void cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, + constexpr_call *new_call, + bool *non_constant_p, bool *overflow_p, + bool *non_constant_args); + +#endif /* ! GCC_CONSTEXPR_H */ diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 8cfee4f..b9e29cf 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "langhooks-def.h" #include "cp-objcp-common.h" +#include "constexpr.h" enum c_language_kind c_language = clk_cxx; static void cp_init_ts (void); diff --git a/gcc/plugin.c b/gcc/plugin.c index 60081a5..34c60ed 100644 --- a/gcc/plugin.c +++ b/gcc/plugin.c @@ -427,6 +427,7 @@ register_callback (const char *plugin_name, return; } /* Fall through. */ + case PLUGIN_EVAL_CALL_CONSTEXPR: case PLUGIN_START_PARSE_FUNCTION: case PLUGIN_FINISH_PARSE_FUNCTION: case PLUGIN_FINISH_TYPE: @@ -507,6 +508,7 @@ invoke_plugin_callbacks_full (int event, void *gcc_data) gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC); gcc_assert (event < event_last); /* Fall through. */ + case PLUGIN_EVAL_CALL_CONSTEXPR: case PLUGIN_START_PARSE_FUNCTION: case PLUGIN_FINISH_PARSE_FUNCTION: case PLUGIN_FINISH_TYPE: diff --git a/gcc/plugin.def b/gcc/plugin.def index c926d41..824f807 100644 --- a/gcc/plugin.def +++ b/gcc/plugin.def @@ -17,6 +17,9 @@ 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/>. */ +/* Called when evaluating a constexpr call. */ +DEFEVENT (PLUGIN_EVAL_CALL_CONSTEXPR) + /* Called before parsing the body of a function. */ DEFEVENT (PLUGIN_START_PARSE_FUNCTION)