[PATCH] New flag for dumping information about constexpr function calls memoization (GCC 5.2.0)

2016-01-28 Thread Andres Tiraboschi
Hi,

This patch adds a flag (-fdump-memoization-hits) in order to dump
information about wich constexpr functions calls are memoized.
This is patch is for gcc-5.2.0.
If OK, please commit it for me since I don't have write access.

patch:

diff --git a/gcc/common.opt b/gcc/common.opt
index 1218a71..bf0c7df 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1168,6 +1168,10 @@ fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes

+fdump-memoization-hits
+Common Var(flag_dump_memoization_hits) Init(0)
+Dump info about constexpr calls memoized.
+
 fdump-unnumbered
 Common Report Var(flag_dump_unnumbered)
 Suppress output of instruction numbers, line number notes and
addresses in debugging dumps
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index e250726..41ae5b3 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -42,6 +42,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "tree-inline.h"
 #include "ubsan.h"
+#include "tree-pretty-print.h"
+#include "dumpfile.h"

 static bool verify_constant (tree, bool, bool *, bool *);
 #define VERIFY_CONSTANT(X)\
@@ -1173,6 +1175,14 @@ cx_error_context (void)
   return r;
 }

+static void
+dump_memoization_hit (FILE *file, tree call, int flags)
+{
+  fprintf(file, "Memoized call:\n");
+  print_generic_decl(file, call, flags);
+  fprintf(file, "\n");
+}
+
 /* Subroutine of cxx_eval_constant_expression.
Evaluate the call expression tree T in the context of OLD_CALL expression
evaluation.  */
@@ -1338,7 +1348,11 @@ cxx_eval_call_expression (const constexpr_ctx
*ctx, tree t,
   entry->result = result = error_mark_node;
 }
   else
-result = entry->result;
+{
+  if (flag_dump_memoization_hits)
+  dump_memoization_hit(stderr, t, 0);
+  result = entry->result;
+}
 }

   if (!depth_ok)


Re: [PATCH] New flag for dumping information about constexpr function calls memoization (GCC 5.2.0)

2016-01-29 Thread Andres Tiraboschi
2016-01-28 17:54 GMT-03:00 Joseph Myers :
> Any patch adding a new option needs to add documentation for it to
> invoke.texi (both substantive documentation, and inclusion in the summary
> lists of options).
>
> --
> Joseph S. Myers
> jos...@codesourcery.com

Hi,

Thanks for the feedback, I've just updated the documentation.

patch:


diff --git a/gcc/common.opt b/gcc/common.opt
index 1218a71..bf0c7df 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1168,6 +1168,10 @@ fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes

+fdump-memoization-hits
+Common Var(flag_dump_memoization_hits) Init(0)
+Dump info about constexpr calls memoized.
+
 fdump-unnumbered
 Common Report Var(flag_dump_unnumbered)
 Suppress output of instruction numbers, line number notes and
addresses in debugging dumps
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index e250726..41ae5b3 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -42,6 +42,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "tree-inline.h"
 #include "ubsan.h"
+#include "tree-pretty-print.h"
+#include "dumpfile.h"

 static bool verify_constant (tree, bool, bool *, bool *);
 #define VERIFY_CONSTANT(X)\
@@ -1173,6 +1175,14 @@ cx_error_context (void)
   return r;
 }

+static void
+dump_memoization_hit (FILE *file, tree call, int flags)
+{
+  fprintf(file, "Memoized call:\n");
+  print_generic_decl(file, call, flags);
+  fprintf(file, "\n");
+}
+
 /* Subroutine of cxx_eval_constant_expression.
Evaluate the call expression tree T in the context of OLD_CALL expression
evaluation.  */
@@ -1338,7 +1348,11 @@ cxx_eval_call_expression (const constexpr_ctx
*ctx, tree t,
   entry->result = result = error_mark_node;
 }
   else
-result = entry->result;
+{
+  if (flag_dump_memoization_hits)
+  dump_memoization_hit(stderr, t, 0);
+  result = entry->result;
+}
 }

   if (!depth_ok)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index f84a199..b78bd4b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -322,6 +322,7 @@ Objective-C and Objective-C++ Dialects}.
 -fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
 -fdump-ipa-all -fdump-ipa-cgraph -fdump-ipa-inline @gol
 -fdump-passes @gol
+-fdump-memoization-hits @gol
 -fdump-statistics @gol
 -fdump-tree-all @gol
 -fdump-tree-original@r{[}-@var{n}@r{]}  @gol
@@ -6771,6 +6772,10 @@ Dump after function inlining.
 Dump the list of optimization passes that are turned on and off by
 the current command-line options.

+@item -fdump-memoization-hits
+@opindex fdump-memoization-hits
+Dump the list of constexpr function calls that were memoized.
+
 @item -fdump-statistics-@var{option}
 @opindex fdump-statistics
 Enable and control dumping of pass statistics in a separate file.  The


[PATCH] Fix 67064 - Register asm variable broken

2015-09-16 Thread Andres Tiraboschi
Hi, this patch fix the following bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67064 for gcc 5.2

It passes all the gcc tests except for this:
FAIL: g++.dg/cpp1y/auto-fn15.C  -std=gnu++14 (test for excess errors)

but this also happens without the patch.

This patch was implemented for gcc 5.2

changelog:


diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 949225b..62b8c2a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5131,8 +5131,6 @@ build_conditional_expr_1 (location_t loc, tree
arg1, tree arg2, tree arg3,
  lvalue, we must add a NON_LVALUE_EXPR.  */
   result = rvalue (result);
 }
-  else
-result = force_paren_expr (result);

   return result;
 }
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4e525e0..1f802b0 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5933,7 +5933,6 @@ extern tree finish_asm_stmt(int,
tree, tree, tree, tree,
 extern tree finish_label_stmt(tree);
 extern void finish_label_decl(tree);
 extern tree finish_parenthesized_expr(tree);
-extern tree force_paren_expr(tree);
 extern tree finish_non_static_data_member   (tree, tree, tree);
 extern tree begin_stmt_expr(void);
 extern tree finish_stmt_expr_expr(tree, tree);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 82ef642..005262d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1642,26 +1642,9 @@ finish_mem_initializers (tree mem_inits)
 emit_mem_initializers (mem_inits);
 }

-/* Obfuscate EXPR if it looks like an id-expression or member access so
-   that the call to finish_decltype in do_auto_deduction will give the
-   right result.  */
-
-tree
-force_paren_expr (tree expr)
+static void
+check_paren_expr(tree expr)
 {
-  /* This is only needed for decltype(auto) in C++14.  */
-  if (cxx_dialect < cxx14)
-return expr;
-
-  /* If we're in unevaluated context, we can't be deducing a
- return/initializer type, so we don't need to mess with this.  */
-  if (cp_unevaluated_operand)
-return expr;
-
-  if (!DECL_P (expr) && TREE_CODE (expr) != COMPONENT_REF
-  && TREE_CODE (expr) != SCOPE_REF)
-return expr;
-
   if (TREE_CODE (expr) == COMPONENT_REF)
 REF_PARENTHESIZED_P (expr) = true;
   else if (type_dependent_expression_p (expr))
@@ -1672,7 +1655,7 @@ force_paren_expr (tree expr)
   if ((kind & ~clk_class) != clk_none)
 {
   tree type = unlowered_expr_type (expr);
-  bool rval = !!(kind & clk_rvalueref);
+  bool rval = (kind & clk_rvalueref);
   type = cp_build_reference_type (type, rval);
   /* This inhibits warnings in, eg, cxx_mark_addressable
  (c++/60955).  */
@@ -1682,10 +1665,7 @@ force_paren_expr (tree expr)
 REF_PARENTHESIZED_P (expr) = true;
 }
 }
-
-  return expr;
 }
-
 /* Finish a parenthesized expression EXPR.  */

 tree
@@ -1704,8 +1684,6 @@ finish_parenthesized_expr (tree expr)
   if (TREE_CODE (expr) == STRING_CST)
 PAREN_STRING_LITERAL_P (expr) = 1;

-  expr = force_paren_expr (expr);
-
   return expr;
 }

@@ -7369,7 +7347,10 @@ finish_decltype_type (tree expr, bool
id_expression_or_member_access_p,
 type = strip_typedefs (type);

   if (clk != clk_none && !(clk & clk_class))
+  {
+check_paren_expr(expr);
 type = cp_build_reference_type (type, (clk & clk_rvalueref));
+  }
 }
 }


[PATCH] Optional escaped commas in macros

2015-10-27 Thread Andres Tiraboschi
This patch is for gcc-5.2.0 adds the XXX option to the preprocessor
that enables to escape
commas when passing macro arguments. This feature is useful in C++ when the
macro argument is a template with more than one argument, and adding extra
( ) is not possible, as shown in this example:

template  struct S;

#define Macro(arg) S arg

Macro();  // error: passing 2 arguments

Adding extra ( ) as a workaround doesn't work either:

Macro(());  // expands to struct S ()

Despite there are workarounds using variadic macros (as already discussed
in the C++' std-proposals mailing list) and using indirect macros (such as
defining a COMMA macro or alike), this patch enables to escape the
comma to prevent it behave as an argument separator, allowing to write
the example above as:

Macro();   // only one argument

Other people in the same mailing list proposed to teach the preprocessor to do
tokens balancing, but this approach is both more complicated and fails in the
following examples:

   #define IF(condition1, condition2) if(lower condition1 && condition2 upper)
   IF() return 1;

   #define BRACKET(x)  x] = 1
   BRACKET(a[1);


While we start a discussion with the C committee regarding the standarization
of this feature, we think that this is a useful nonstandard addition to be
early adopted.

I ran all the test and passed.


Thanks,
Andrés.

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 983f4a8..41fa9dd 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -181,6 +181,10 @@ A
 C ObjC C++ ObjC++ Joined Separate MissingArgError(assertion missing after %qs)
 -A=Assert the  to .  Putting
'-' before  disables the  to 

+fmacro-escaped-commas
+C ObjC C++ ObjC++ CPP(macro_escaped_commas)
Var(cpp_macro_escaped_commas) Init(0)
+Allows using escaped commas in macros arguments
+
 C
 C ObjC C++ ObjC++
 Do not discard comments
diff --git a/gcc/testsuite/gcc.dg/cpp/macro-escaped-commas.c
b/gcc/testsuite/gcc.dg/cpp/macro-escaped-commas.c
new file mode 100644
index 000..e56df04
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/macro-escaped-commas.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-fmacro-escaped-commas" } */
+
+#define MACRO_DEFINITION0(a, b) a + b
+#define MACRO_DEFINITION1(a) 0
+int main(void)
+{
+int a = MACRO_DEFINITION1({1\,2\,3});
+int b = MACRO_DEFINITION0(MACRO_DEFINITION1({1\,2\,3}), 1);
+return 0;
+}
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 5e08014..c3d404b 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -481,6 +481,9 @@ struct cpp_options
   /* True if dependencies should be restored from a precompiled header.  */
   bool restore_pch_deps;

+  /* True to use escaped commas in macros*/
+  bool macro_escaped_commas;
+
   /* True if warn about differences between C90 and C99.  */
   signed char cpp_warn_c90_c99_compat;

diff --git a/libcpp/macro.c b/libcpp/macro.c
index 1e0a0b5..f9eba81 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -811,6 +811,7 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
   source_location virt_loc;
   bool track_macro_expansion_p = CPP_OPTION (pfile, track_macro_expansion);
   unsigned num_args_alloced = 0;
+  const bool escaped_commas_p = CPP_OPTION(pfile, macro_escaped_commas);

   macro = node->value.macro;
   if (macro->paramc)
@@ -835,6 +836,8 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
  few.  Hence the slightly bizarre usage of "argc" and "arg".  */
   do
 {
+  bool prev_backslash_p = false;
+  bool token_taken_p = false;
   unsigned int paren_depth = 0;
   unsigned int ntokens = 0;
   unsigned virt_locs_capacity = DEFAULT_NUM_TOKENS_PER_MACRO_ARG;
@@ -867,8 +870,9 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
arg->virt_locs,
virt_locs_capacity);
 }
-
-  token = cpp_get_token_1 (pfile, &virt_loc);
+  //If a token wasn't already taken, get a token
+  if (!token_taken_p)
+token = cpp_get_token_1 (pfile, &virt_loc);

   if (token->type == CPP_PADDING)
 {
@@ -886,9 +890,12 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
   else if (token->type == CPP_COMMA)
 {
   /* A comma does not terminate an argument within
- parentheses or as part of a variable argument.  */
+ parentheses, as part of a variable argument or
+ if the macro_escaped_commas flag is on and
+ if its preceded by a backslash.  */
   if (paren_depth == 0
-  && ! (macro->variadic && argc == macro->paramc))
+  && ! (macro->variadic && argc == macro->paramc)
+  && ! (prev_backslash_p && escaped_commas_p))
 break;
 }
   else if (token->type == CPP_EOF
@@ -939,10 +946,32 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
   else
 continue;
 }
-  set_arg_token (arg, 

Re: [PATCH] Optional escaped commas in macros

2015-10-27 Thread Andres Tiraboschi
2015-10-27 16:35 GMT-03:00 Andres Tiraboschi
:
> This patch is for gcc-5.2.0 adds the XXX option to the preprocessor
Sorry I forgot to clarify that fmacro-escaped-commas is the option name.

Thanks,
Andrés.


[PATCH] New plugin events when evaluating constexpr expressions.

2015-11-03 Thread Andres Tiraboschi
 Hi
 This patch adds two plugins events when evaluated call expression and
an init or modify expression in constexpr.
 The goal of this patch is to allow the plugins to analyze and or
modify the evaluation of constant expressions.

 This patch also adds an event that is called when the parsing of a
file is finished.

Thanks,
Andrés.
diff --git a/gccOrig/gcc/cp/constexpr.c b/gccMod/gcc/cp/constexpr.c
index e250726..1c5431a 100644
--- a/gccOrig/gcc/cp/constexpr.c
+++ b/gccMod/gcc/cp/constexpr.c
@@ -42,6 +42,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "tree-inline.h"
 #include "ubsan.h"
+#include "plugin-api.h"
+#include "plugin.h"
 
 static bool verify_constant (tree, bool, bool *, bool *);
 #define VERIFY_CONSTANT(X) \
@@ -123,13 +125,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_hasher
 {
   static hashval_t hash (constexpr_fundef *);
@@ -855,67 +850,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_hasher
 {
   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 *values;
-  /* 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_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
@@ -1303,6 +1248,19 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
   bool non_constant_args = false;
   cxx_bind_parameters_in_call (ctx, t, &new_call,
   non_constant_p, overflow_p, &non_constant_args);
+  constexpr_call_info call_info;
+  call_info.function = t;
+  call_info.lval = lval;
+  call_info.call = &new_call;
+  call_info.call_stack = call_stack;
+  call_info.non_constant_args = &non_constant_args;
+  call_info.non_const_p = non_constant_p;
+  call_info.ctx = ctx;
+  call_info.result = NULL_TREE;
+  invoke_plugin_callbacks (PLUGIN_EVAL_CALL_CONSTEXPR, &call_info);
+  if (call_info.result != NULL_TREE)
+return unshare_expr (call_info.result);
+
   if (*non_constant_p)
 return t;
 
@@ -2636,6 +2594,19 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, 
tree t,
   target = cxx_eval_constant_expression (ctx, target,
 true,
 non_constant_p, overflow_p);
+
+  constexpr_modify_info mod_info;
+  mod_info.target = target;
+  mod_info.expr = t;
+  mod_info.ctx = ctx;
+  mod_info.init = init;
+  mod_info.overflow = overflow_p;
+  mod_info.non_c

[PATCH] plugin event for C/C++ function definitions

2015-05-18 Thread andres . tiraboschi
Hi, this patch adds two new plugin events PLUGIN_START_PARSE_FUNCTION and 
PLUGIN_FINISH_PARSE_FUNCTION. These events are invoked at start_function and 
finish_function in gcc/c/c-decl.c and gcc/cp/decl.c respectively in the C and 
C++ frontends. 
PLUGIN_START_PARSE_FUNCTION is called before parsing a function body.
PLUGIN_FINISH_PARSE_FUNCTION is called after parsing a function definition.
This patch has been implemented in gcc 5.1.0.

changelog:

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index e28a294..fcc849d 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -8235,6 +8235,7 @@ start_function (struct c_declspecs *declspecs, struct 
c_declarator *declarator,
 
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
  &attributes, NULL, NULL, DEPRECATED_NORMAL);
+  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
 
   /* If the declarator is not suitable for a function definition,
  cause a syntax error.  */
@@ -9050,6 +9051,7 @@ finish_function (void)
  It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
  tree_rest_of_compilation.  */
   set_cfun (NULL);
+  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, 
current_function_decl);
   current_function_decl = NULL;
 }
 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c4731ae..bde92cc 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13727,6 +13727,7 @@ start_function (cp_decl_specifier_seq *declspecs,
   tree decl1;
 
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
   if (decl1 == error_mark_node)
 return false;
   /* If the declarator is not suitable for a function definition,
@@ -14365,6 +14366,7 @@ finish_function (int flags)
   vec_free (deferred_mark_used_calls);
 }
 
+  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, fndecl);
   return fndecl;
 }
 
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index c6caa19..d50f25c 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -174,6 +174,8 @@ Callbacks can be invoked at the following pre-determined 
events:
 @smallexample
 enum plugin_event
 @{
+  PLUGIN_START_PARSE_FUNCTION,  /* Called before parsing the body of a 
function. */
+  PLUGIN_FINISH_PARSE_FUNCTION, /* After finishing parsing a function. */
   PLUGIN_PASS_MANAGER_SETUP,/* To hook into pass manager.  */
   PLUGIN_FINISH_TYPE,   /* After finishing parsing a type.  */
   PLUGIN_FINISH_DECL,   /* After finishing parsing a declaration. */
diff --git a/gcc/plugin.c b/gcc/plugin.c
index d924438..628833f 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -441,6 +441,8 @@ register_callback (const char *plugin_name,
return;
  }
   /* Fall through.  */
+  case PLUGIN_START_PARSE_FUNCTION:
+  case PLUGIN_FINISH_PARSE_FUNCTION:
   case PLUGIN_FINISH_TYPE:
   case PLUGIN_FINISH_DECL:
   case PLUGIN_START_UNIT:
@@ -519,6 +521,8 @@ 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_START_PARSE_FUNCTION:
+  case PLUGIN_FINISH_PARSE_FUNCTION:
   case PLUGIN_FINISH_TYPE:
   case PLUGIN_FINISH_DECL:
   case PLUGIN_START_UNIT:
diff --git a/gcc/plugin.def b/gcc/plugin.def
index 98c988a..2a7e4c2 100644
--- a/gcc/plugin.def
+++ b/gcc/plugin.def
@@ -17,6 +17,11 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+/* Called before parsing the body of a function.  */
+DEFEVENT (PLUGIN_START_PARSE_FUNCTION)
+
+/* After finishing parsing a function. */
+DEFEVENT (PLUGIN_FINISH_PARSE_FUNCTION)
 
 /* To hook into pass manager.  */
 DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
diff --git a/gcc/testsuite/g++.dg/plugin/def-plugin-test.C 
b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
new file mode 100644
index 000..b7f2d3d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
@@ -0,0 +1,13 @@
+int global = 12;
+
+int function1(void);
+
+int function2(int a) // { dg-warning "Start fndef function2" }
+{
+  return function1() + a;
+} //  { dg-warning "Finish fndef function2" }
+
+int function1(void) // { dg-warning "Start fndef function1" }
+{
+  return global + 1;
+} //  { dg-warning "Finish fndef function1" }
diff --git a/gcc/testsuite/g++.dg/plugin/def_plugin.c 
b/gcc/testsuite/g++.dg/plugin/def_plugin.c
new file mode 100644
index 000..63983c5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/def_plugin.c
@@ -0,0 +1,45 @@
+/* A plugin example that shows which function definitions are caught by 
PLUGIN_START_FUNCTION and PLUGIN_FINISH_FUNCTION */
+
+#include "gcc-plugin.h"
+#include 
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "diagnos

Re: [PATCH] plugin event for C/C++ function definitions

2015-05-19 Thread Andres Tiraboschi
2015-05-18 16:51 GMT-03:00  :
> Hi, this patch adds two new plugin events PLUGIN_START_PARSE_FUNCTION and 
> PLUGIN_FINISH_PARSE_FUNCTION. These events are invoked at start_function and 
> finish_function in gcc/c/c-decl.c and gcc/cp/decl.c respectively in the C and 
> C++ frontends.
> PLUGIN_START_PARSE_FUNCTION is called before parsing a function body.
> PLUGIN_FINISH_PARSE_FUNCTION is called after parsing a function definition.
> This patch has been implemented in gcc 5.1.0.
>
> changelog:
>
> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> index e28a294..fcc849d 100644
> --- a/gcc/c/c-decl.c
> +++ b/gcc/c/c-decl.c
> @@ -8235,6 +8235,7 @@ start_function (struct c_declspecs *declspecs, struct 
> c_declarator *declarator,
>
>decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
>   &attributes, NULL, NULL, DEPRECATED_NORMAL);
> +  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
>
>/* If the declarator is not suitable for a function definition,
>   cause a syntax error.  */
> @@ -9050,6 +9051,7 @@ finish_function (void)
>   It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
>   tree_rest_of_compilation.  */
>set_cfun (NULL);
> +  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, 
> current_function_decl);
>current_function_decl = NULL;
>  }
>
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index c4731ae..bde92cc 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -13727,6 +13727,7 @@ start_function (cp_decl_specifier_seq *declspecs,
>tree decl1;
>
>decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
> +  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
>if (decl1 == error_mark_node)
>  return false;
>/* If the declarator is not suitable for a function definition,
> @@ -14365,6 +14366,7 @@ finish_function (int flags)
>vec_free (deferred_mark_used_calls);
>  }
>
> +  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, fndecl);
>return fndecl;
>  }
>
> diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
> index c6caa19..d50f25c 100644
> --- a/gcc/doc/plugins.texi
> +++ b/gcc/doc/plugins.texi
> @@ -174,6 +174,8 @@ Callbacks can be invoked at the following pre-determined 
> events:
>  @smallexample
>  enum plugin_event
>  @{
> +  PLUGIN_START_PARSE_FUNCTION,  /* Called before parsing the body of a 
> function. */
> +  PLUGIN_FINISH_PARSE_FUNCTION, /* After finishing parsing a function. */
>PLUGIN_PASS_MANAGER_SETUP,/* To hook into pass manager.  */
>PLUGIN_FINISH_TYPE,   /* After finishing parsing a type.  */
>PLUGIN_FINISH_DECL,   /* After finishing parsing a declaration. */
> diff --git a/gcc/plugin.c b/gcc/plugin.c
> index d924438..628833f 100644
> --- a/gcc/plugin.c
> +++ b/gcc/plugin.c
> @@ -441,6 +441,8 @@ register_callback (const char *plugin_name,
> return;
>   }
>/* Fall through.  */
> +  case PLUGIN_START_PARSE_FUNCTION:
> +  case PLUGIN_FINISH_PARSE_FUNCTION:
>case PLUGIN_FINISH_TYPE:
>case PLUGIN_FINISH_DECL:
>case PLUGIN_START_UNIT:
> @@ -519,6 +521,8 @@ 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_START_PARSE_FUNCTION:
> +  case PLUGIN_FINISH_PARSE_FUNCTION:
>case PLUGIN_FINISH_TYPE:
>case PLUGIN_FINISH_DECL:
>case PLUGIN_START_UNIT:
> diff --git a/gcc/plugin.def b/gcc/plugin.def
> index 98c988a..2a7e4c2 100644
> --- a/gcc/plugin.def
> +++ b/gcc/plugin.def
> @@ -17,6 +17,11 @@ You should have received a copy of the GNU General Public 
> License
>  along with GCC; see the file COPYING3.  If not see
>  .  */
>
> +/* Called before parsing the body of a function.  */
> +DEFEVENT (PLUGIN_START_PARSE_FUNCTION)
> +
> +/* After finishing parsing a function. */
> +DEFEVENT (PLUGIN_FINISH_PARSE_FUNCTION)
>
>  /* To hook into pass manager.  */
>  DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
> diff --git a/gcc/testsuite/g++.dg/plugin/def-plugin-test.C 
> b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
> new file mode 100644
> index 000..b7f2d3d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
> @@ -0,0 +1,13 @@
> +int global = 12;
> +
> +int function1(void);
> +
> +int function2(int a) // { dg-warning "Start fndef function2" }
> +{
> +  return function1() + a;
> +} //  { dg-warning "Finish fndef function2" }
> +
> +int function1(void) // { dg-warning "Start fndef function1" }
> +{
> +  return global + 1;
> +} //  { dg-warning "Finish fndef function1" }
> diff --git a/gcc/testsuite/g++.dg/plugin/def_plugin.c 
> b/gcc/testsuite/g++.dg/plugin/def_plugin.c
> new file mode 100644
> index 000..63983c5
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/plugin/def_plugin.c
> @@ -0,0 +1,45 @@
> +/* A plugin example that shows w

[PATCH] plugin event for C/C++ function definitions

2014-11-13 Thread Andres Tiraboschi
Hi, this patch adds a new plugin event PLUGIN_START_FUNCTION and 
PLUGIN_FINISH_FUNCTION that are invoked at start_function and finish_function 
respectively in the C and C++ frontends. 
PLUGIN_START_FUNCTION is called before parsing the function body.
PLUGIN_FINISH_FUNCTION is called after parsing a function definition.

2014-11-04 Andrés Tiraboschi 

changelog:

 gcc/c/c-decl.c: Invoke callbacks in start_function and finish_function.

 gcc/cp/decl.c: Invoke callbacks in start_function and finish_function.

 gcc/doc/plugins.texi: Add documentation about PLUGIN_START_FUNCTION and 
PLUGIN_FINISH_FUNCTION
 gcc/plugin.def: Add events for start_function and finish_function. 
 
 gcc/plugin.c (register_callback, invoke_plugin_callbacks): Same.

 gcc/testsuite/g++.dg/plugin/def_plugin.c: New test plugin. 
 
 gcc/testsuite/g++.dg/plugin/def-plugin-test.C: Testcase for above plugin.
 gcc/testsuite/g++.dg/plugin/plugin.exp 

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index e23284a..b349a24 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -8073,6 +8073,7 @@ start_function (struct c_declspecs *declspecs, struct 
c_declarator *declarator,
 
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
  &attributes, NULL, NULL, DEPRECATED_NORMAL);
+  invoke_plugin_callbacks (PLUGIN_START_FUNCTION, decl1);
 
   /* If the declarator is not suitable for a function definition,
  cause a syntax error.  */
@@ -8886,6 +8887,7 @@ finish_function (void)
  It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
  tree_rest_of_compilation.  */
   set_cfun (NULL);
+  invoke_plugin_callbacks (PLUGIN_FINISH_FUNCTION, current_function_decl);
   current_function_decl = NULL;
 }
 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d4adbeb..a8c6ebe 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13631,6 +13631,7 @@ start_function (cp_decl_specifier_seq *declspecs,
   tree decl1;
 
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+  invoke_plugin_callbacks (PLUGIN_START_FUNCTION, decl1);
   if (decl1 == error_mark_node)
 return false;
   /* If the declarator is not suitable for a function definition,
@@ -14260,6 +14261,7 @@ finish_function (int flags)
   vec_free (deferred_mark_used_calls);
 }
 
+  invoke_plugin_callbacks (PLUGIN_FINISH_FUNCTION, fndecl);
   return fndecl;
 }
 
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index 4a839b8..b4a20e1 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -174,6 +174,8 @@ Callbacks can be invoked at the following pre-determined 
events:
 @smallexample
 enum plugin_event
 @{
+  PLUGIN_START_FUNCTION /* Called before parsing the body of a 
function. */
+  PLUGIN_FINISH_FUNCTION/* After finishing parsing a function. */
   PLUGIN_PASS_MANAGER_SETUP,/* To hook into pass manager.  */
   PLUGIN_FINISH_TYPE,   /* After finishing parsing a type.  */
   PLUGIN_FINISH_DECL,   /* After finishing parsing a declaration. */
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 8debc09..c048d93 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -433,6 +433,8 @@ register_callback (const char *plugin_name,
return;
  }
   /* Fall through.  */
+  case PLUGIN_START_FUNCTION:
+  case PLUGIN_FINISH_FUNCTION:
   case PLUGIN_FINISH_TYPE:
   case PLUGIN_FINISH_DECL:
   case PLUGIN_START_UNIT:
@@ -511,6 +513,8 @@ 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_START_FUNCTION:
+  case PLUGIN_FINISH_FUNCTION:
   case PLUGIN_FINISH_TYPE:
   case PLUGIN_FINISH_DECL:
   case PLUGIN_START_UNIT:
diff --git a/gcc/plugin.def b/gcc/plugin.def
index df5d383..a4131ad 100644
--- a/gcc/plugin.def
+++ b/gcc/plugin.def
@@ -17,6 +17,11 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+/* Called before parsing the body of a function.  */
+DEFEVENT (PLUGIN_START_FUNCTION)
+
+/* After finishing parsing a function definition. */
+DEFEVENT (PLUGIN_FINISH_FUNCTION)
 
 /* To hook into pass manager.  */
 DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
diff --git a/gcc/testsuite/g++.dg/plugin/def-plugin-test.C 
b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
new file mode 100644
index 000..b7f2d3d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
@@ -0,0 +1,13 @@
+int global = 12;
+
+int function1(void);
+
+int function2(int a) // { dg-warning "Start fndef function2" }
+{
+  return function1() + a;
+} //  { dg-warning "Finish fndef function2" }
+
+int function1(void) // { dg-warning "Start fndef function1" }
+{
+  return global + 1;
+} //  { dg-warning "Finish fndef f

Re: [PATCH] plugin event for C/C++ function definitions

2014-11-18 Thread Andres Tiraboschi
2014-11-14 7:08 GMT-03:00 Richard Biener :
> On Thu, Nov 13, 2014 at 6:42 PM, Andres Tiraboschi
>  wrote:
>> Hi, this patch adds a new plugin event PLUGIN_START_FUNCTION and 
>> PLUGIN_FINISH_FUNCTION that are invoked at start_function and 
>> finish_function respectively in the C and C++ frontends.
>> PLUGIN_START_FUNCTION is called before parsing the function body.
>> PLUGIN_FINISH_FUNCTION is called after parsing a function definition.
>
> Can you name them more specifically, like
> PLUGIN_START/FINISH_PARSE_FUNCTION please?
>
> Thanks,
> Richard.

Ok, I will do it


[PATCH V2] plugin event for C/C++ function definitions

2014-11-18 Thread Andres Tiraboschi
Hi, this patch adds a new plugin event PLUGIN_START_PARSE_FUNCTION and 
PLUGIN_FINISH_PARSE_FUNCTION that are invoked at start_function and 
finish_function respectively in the C and C++ frontends. 
PLUGIN_START_PARSE_FUNCTION is called before parsing the function body.
PLUGIN_FINISH_PARSE_FUNCTION is called after parsing a function definition.

changelog:

 gcc/c/c-decl.c: Invoke callbacks in start_function and finish_function.

 gcc/cp/decl.c: Invoke callbacks in start_function and finish_function.

 gcc/doc/plugins.texi: Add documentation about PLUGIN_START_FUNCTION and 
PLUGIN_FINISH_FUNCTION
 gcc/plugin.def: Add events for start_function and finish_function. 
 
 gcc/plugin.c (register_callback, invoke_plugin_callbacks): Same.

 gcc/testsuite/g++.dg/plugin/def_plugin.c: New test plugin. 
 
 gcc/testsuite/g++.dg/plugin/def-plugin-test.C: Testcase for above plugin.
 gcc/testsuite/g++.dg/plugin/plugin.exp 

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index e23284a..fea3334 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -8073,6 +8073,7 @@ start_function (struct c_declspecs *declspecs, struct 
c_declarator *declarator,
 
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
  &attributes, NULL, NULL, DEPRECATED_NORMAL);
+  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
 
   /* If the declarator is not suitable for a function definition,
  cause a syntax error.  */
@@ -8886,6 +8887,7 @@ finish_function (void)
  It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
  tree_rest_of_compilation.  */
   set_cfun (NULL);
+  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, 
current_function_decl);
   current_function_decl = NULL;
 }
 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d4adbeb..ce2f832 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13631,6 +13631,7 @@ start_function (cp_decl_specifier_seq *declspecs,
   tree decl1;
 
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
   if (decl1 == error_mark_node)
 return false;
   /* If the declarator is not suitable for a function definition,
@@ -14260,6 +14261,7 @@ finish_function (int flags)
   vec_free (deferred_mark_used_calls);
 }
 
+  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, fndecl);
   return fndecl;
 }
 
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index 4a839b8..1c9e074 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -174,6 +174,8 @@ Callbacks can be invoked at the following pre-determined 
events:
 @smallexample
 enum plugin_event
 @{
+  PLUGIN_START_PARSE_FUNCTION,  /* Called before parsing the body of a 
function. */
+  PLUGIN_FINISH_PARSE_FUNCTION, /* After finishing parsing a function. */
   PLUGIN_PASS_MANAGER_SETUP,/* To hook into pass manager.  */
   PLUGIN_FINISH_TYPE,   /* After finishing parsing a type.  */
   PLUGIN_FINISH_DECL,   /* After finishing parsing a declaration. */
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 8debc09..f7a8b64 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -433,6 +433,8 @@ register_callback (const char *plugin_name,
return;
  }
   /* Fall through.  */
+  case PLUGIN_START_PARSE_FUNCTION:
+  case PLUGIN_FINISH_PARSE_FUNCTION:
   case PLUGIN_FINISH_TYPE:
   case PLUGIN_FINISH_DECL:
   case PLUGIN_START_UNIT:
@@ -511,6 +513,8 @@ 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_START_PARSE_FUNCTION:
+  case PLUGIN_FINISH_PARSE_FUNCTION:
   case PLUGIN_FINISH_TYPE:
   case PLUGIN_FINISH_DECL:
   case PLUGIN_START_UNIT:
diff --git a/gcc/plugin.def b/gcc/plugin.def
index df5d383..04faec9 100644
--- a/gcc/plugin.def
+++ b/gcc/plugin.def
@@ -18,6 +18,12 @@ along with GCC; see the file COPYING3.  If not see
 .  */
 
 
+/* Called before parsing the body of a function.  */
+DEFEVENT (PLUGIN_START_PARSE_FUNCTION)
+
+/* After finishing parsing a function. */
+DEFEVENT (PLUGIN_FINISH_PARSE_FUNCTION)
+
 /* To hook into pass manager.  */
 DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
 
diff --git a/gcc/testsuite/g++.dg/plugin/def-plugin-test.C 
b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
new file mode 100644
index 000..b7f2d3d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
@@ -0,0 +1,13 @@
+int global = 12;
+
+int function1(void);
+
+int function2(int a) // { dg-warning "Start fndef function2" }
+{
+  return function1() + a;
+} //  { dg-warning "Finish fndef function2" }
+
+int function1(void) // { dg-warning "Start fndef function1" }
+{
+  return global + 1;
+} //  { dg-warning "Finish fndef function1" }
diff --gi

Re: [PATCH V2] plugin event for C/C++ function definitions

2014-11-19 Thread Andres Tiraboschi
I forgot to mention that i have no write privileges, please commit
this for me if it's OK


[PING][PATCH V2] plugin event for C/C++ function definitions

2014-12-02 Thread Andres Tiraboschi
Hi, this patch adds a new plugin event PLUGIN_START_PARSE_FUNCTION and 
PLUGIN_FINISH_PARSE_FUNCTION that are invoked at start_function and 
finish_function respectively in the C and C++ frontends. 
PLUGIN_START_PARSE_FUNCTION is called before parsing the function body.
PLUGIN_FINISH_PARSE_FUNCTION is called after parsing a function definition.

Since I have no write privileges please commit this for me if ok.

changelog:

 gcc/c/c-decl.c: Invoke callbacks in start_function and finish_function.

 gcc/cp/decl.c: Invoke callbacks in start_function and finish_function.

 gcc/doc/plugins.texi: Add documentation about PLUGIN_START_FUNCTION and 
PLUGIN_FINISH_FUNCTION
 gcc/plugin.def: Add events for start_function and finish_function. 
 
 gcc/plugin.c (register_callback, invoke_plugin_callbacks): Same.

 gcc/testsuite/g++.dg/plugin/def_plugin.c: New test plugin. 
 
 gcc/testsuite/g++.dg/plugin/def-plugin-test.C: Testcase for above plugin.
 gcc/testsuite/g++.dg/plugin/plugin.exp 

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 6413e6f..d9d922c 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -4449,6 +4449,7 @@ start_decl (struct c_declarator *declarator, struct 
c_declspecs *declspecs,
   decl = grokdeclarator (declarator, declspecs,
 NORMAL, initialized, NULL, &attributes, &expr, NULL,
 deprecated_state);
+  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl);
   if (!decl)
 return 0;
 
@@ -9031,6 +9032,7 @@ finish_function (void)
  It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
  tree_rest_of_compilation.  */
   set_cfun (NULL);
+  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, 
current_function_decl);
   current_function_decl = NULL;
 }
 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 716ab5f..6adf2e4 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13671,6 +13671,7 @@ start_function (cp_decl_specifier_seq *declspecs,
   tree decl1;
 
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
   if (decl1 == error_mark_node)
 return false;
   /* If the declarator is not suitable for a function definition,
@@ -14301,6 +14302,7 @@ finish_function (int flags)
   vec_free (deferred_mark_used_calls);
 }
 
+  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, fndecl);
   return fndecl;
 }
 
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index 4a839b8..1c9e074 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -174,6 +174,8 @@ Callbacks can be invoked at the following pre-determined 
events:
 @smallexample
 enum plugin_event
 @{
+  PLUGIN_START_PARSE_FUNCTION,  /* Called before parsing the body of a 
function. */
+  PLUGIN_FINISH_PARSE_FUNCTION, /* After finishing parsing a function. */
   PLUGIN_PASS_MANAGER_SETUP,/* To hook into pass manager.  */
   PLUGIN_FINISH_TYPE,   /* After finishing parsing a type.  */
   PLUGIN_FINISH_DECL,   /* After finishing parsing a declaration. */
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 8debc09..f7a8b64 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -433,6 +433,8 @@ register_callback (const char *plugin_name,
return;
  }
   /* Fall through.  */
+  case PLUGIN_START_PARSE_FUNCTION:
+  case PLUGIN_FINISH_PARSE_FUNCTION:
   case PLUGIN_FINISH_TYPE:
   case PLUGIN_FINISH_DECL:
   case PLUGIN_START_UNIT:
@@ -511,6 +513,8 @@ 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_START_PARSE_FUNCTION:
+  case PLUGIN_FINISH_PARSE_FUNCTION:
   case PLUGIN_FINISH_TYPE:
   case PLUGIN_FINISH_DECL:
   case PLUGIN_START_UNIT:
diff --git a/gcc/plugin.def b/gcc/plugin.def
index df5d383..4b7f6ef 100644
--- a/gcc/plugin.def
+++ b/gcc/plugin.def
@@ -17,6 +17,11 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+/* Called before parsing the body of a function.  */
+DEFEVENT (PLUGIN_START_PARSE_FUNCTION)
+
+/* After finishing parsing a function. */
+DEFEVENT (PLUGIN_FINISH_PARSE_FUNCTION)
 
 /* To hook into pass manager.  */
 DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
diff --git a/gcc/testsuite/g++.dg/plugin/def-plugin-test.C 
b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
new file mode 100644
index 000..b7f2d3d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/def-plugin-test.C
@@ -0,0 +1,13 @@
+int global = 12;
+
+int function1(void);
+
+int function2(int a) // { dg-warning "Start fndef function2" }
+{
+  return function1() + a;
+} //  { dg-warning "Finish fndef function2" }
+
+int function1(void) // { dg-warning "Start fndef function1" 

[PATCH] Adding warning for constexpr's

2015-06-12 Thread Andres Tiraboschi
Hi, this patch is for adding a warning when a constexpr cannot be evaluated at 
compile time.
This is a single case:
type var = fun(args...), with fun declared as a constexpr.

diff --git a/gcc/common.opt b/gcc/common.opt
index b49ac46..88374b1 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -581,6 +581,10 @@ Winline
 Common Var(warn_inline) Warning
 Warn when an inlined function cannot be inlined
 
+Wconstexpr
+Common Var(warn_constexpr) Warning
+Warn when a constexpr function is not evaluated at compile time
+
 Winvalid-memory-model
 Common Var(warn_invalid_memory_model) Init(1) Warning
 Warn when an atomic memory model parameter is known to be outside the valid 
range.
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 80a6939..e25c240 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -842,6 +842,15 @@ store_init_value (tree decl, tree init, vec** 
cleanups, int flags)
   DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init;
   TREE_CONSTANT (decl) = const_init && decl_maybe_constant_var_p (decl);
 }
+  else if (TREE_CODE(init) == CALL_EXPR)
+{
+  tree fn = TREE_OPERAND(CALL_EXPR_FN(init), 0);
+  if (DECL_DECLARED_CONSTEXPR_P(fn) && warn_constexpr)
+{
+  warning (OPT_Wconstexpr, "function %q+F cannot be evaluated at 
compile time", fn);
+  warning (OPT_Wconstexpr, "called from here");
+}
+}
 
   if (cxx_dialect >= cxx14)
 /* Handle aggregate NSDMI in non-constant initializers, too.  */


Re: [PATCH] Adding warning for constexpr's

2015-06-15 Thread Andres Tiraboschi
Hi, thanks for your answer. I was trying with warning_at this way
instead that I was doing before:

+  else if (TREE_CODE(init) == CALL_EXPR)
+{
+  tree fn = TREE_OPERAND(CALL_EXPR_FN(init), 0);
+  if (DECL_DECLARED_CONSTEXPR_P(fn) && warn_constexpr)
+  warning_at (DECL_SOURCE_LINE(decl), OPT_Wconstexpr,
"function %q+F cannot be evaluated at compile time", fn);
+

where "decl" is the declaration that is being initializated. For some
reason this isn't working. Checking with gdb I realised that
warning_at in this case is returnin false. I don't know if I am
missing something.

2015-06-12 18:35 GMT-03:00 Joseph Myers :
> On Fri, 12 Jun 2015, Andres Tiraboschi wrote:
>
>> Hi, this patch is for adding a warning when a constexpr cannot be evaluated 
>> at compile time.
>> This is a single case:
>> type var = fun(args...), with fun declared as a constexpr.
>
> All options need documenting in invoke.texi.  All diagnostics need
> testcases added to the testsuite.  C++-specific options go in c.opt and
> should be listed as C++ ObjC++, not Common.  All new diagnostics should
> use warning_at etc. with explicit locations passed, unless there is some
> strong reason it's hard to get the relevant location when the warning is
> given.
>
> --
> Joseph S. Myers
> jos...@codesourcery.com


Re: [PATCH] Adding warning for constexpr's

2015-06-15 Thread Andres Tiraboschi
2015-06-12 18:35 GMT-03:00 Joseph Myers :
> On Fri, 12 Jun 2015, Andres Tiraboschi wrote:
>
>> Hi, this patch is for adding a warning when a constexpr cannot be evaluated 
>> at compile time.
>> This is a single case:
>> type var = fun(args...), with fun declared as a constexpr.
>
> All options need documenting in invoke.texi.  All diagnostics need
> testcases added to the testsuite.  C++-specific options go in c.opt and
> should be listed as C++ ObjC++, not Common.  All new diagnostics should
> use warning_at etc. with explicit locations passed, unless there is some
> strong reason it's hard to get the relevant location when the warning is
> given.
>
> --
> Joseph S. Myers
> jos...@codesourcery.com

Hi, do you know where is the .exp file for the tests in
.../gcc/testsuite/g++.dg/warn?
I can't find it. Thanks again


[PATCH] New flag in order to dump information about template instantiations.

2016-03-29 Thread Andres Tiraboschi
Hi,
the attached patch adds a new compilation flag
'ftemplate-instantiations' in order
to allow dumping debug information for template instantiations.
This flag has 2 possible values: none(by default) and hreadable, that
prints witch
templates instantiations had been made in a human readable way.
This patch was also made in order to add options easily and to interact with
plugins.
  For example in a plugin can be defined a derived class for
template_instantiations_callbacks
implementing _function_instantiation, _class_instantiation, _using_instantiation
and then using add_template_instantiations_callbacks in order to
access information
about witch template instantiations had been made.

Changelog
2016-03-29  Andres Tiraboschi  

* gcc/c-family/c.opt (ftemplate-instantiations): New flag.
* gcc/flag-types.h (ti_dump_options): New type.
* gcc/cp/decl2.c (cp_write_global_declarations): Added code to
dump information.
* gcc/cp/cp-tree.h (template_instantiations_callbacks): New type.
(call_template_instantiation_callbacks): Declare.
(add_template_instantiations_callbacks): Likewise.
(clean_up_callbacks): Likewise.
* gcc/cp/pt.c (human_readable_template_instantiations): New type.
(instantiation_callbacks): Declare.
(call_template_instantiation_callback): New function.
(call_template_instantiation_callbacks): Likewise.
(add_template_instantiations_callbacks): Likewise.
(initialize_instantiations_callbacks): Likewise.
(clean_up_callbacks): Likewise.
(init_template_processing): Added code to initialize instatiation_callbacks.
(register_specialization): Added code to dump information.
* gcc/doc/invoke.texi (ftemplate-instantiations): Added documentation.


diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 7c5f6c7..a0ebcdc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1487,6 +1487,19 @@ fstats
 C++ ObjC++ Var(flag_detailed_statistics)
 Display statistics accumulated during compilation.

+ftemplate-instantiations=
+C++ Joined RejectNegative Enum(ti_dump_options) Var(ti_dump_option)
Init(TI_NONE)
+Dump information about wich templates have been instantiated
+
+Enum
+Name(ti_dump_options) Type(enum ti_dump_options)
UnknownError(unrecognized template instantiation dumping option %qs)
+
+EnumValue
+Enum(ti_dump_options) String(none) Value(TI_NONE)
+
+EnumValue
+Enum(ti_dump_options) String(hreadable) Value(TI_HREADABLE)
+
 fstrict-enums
 C++ ObjC++ Optimization Var(flag_strict_enums)
 Assume that values of enumeration type are always within the minimum
range of that type.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 15b004d..f682b4a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4816,6 +4816,61 @@ struct local_specialization_stack
   hash_map *saved;
 };

+class template_instantiations_callbacks
+{
+public:
+  template_instantiations_callbacks () : next(NULL){}
+
+  void function_instantiation (tree tmpl, tree args, tree spec)
+  {
+_function_instantiation (tmpl, args, spec);
+if (next != NULL)
+  next->function_instantiation (tmpl, args, spec);
+  }
+
+  void class_instantiation (tree tmpl, tree args, tree spec)
+  {
+_class_instantiation (tmpl, args, spec);
+if (next != NULL)
+  next->class_instantiation (tmpl, args, spec);
+  }
+
+  void using_instantiation (tree tmpl, tree args, tree spec)
+  {
+_using_instantiation (tmpl, args, spec);
+if (next != NULL)
+  next->using_instantiation (tmpl, args, spec);
+  }
+
+  void add_callbacks (template_instantiations_callbacks* new_next)
+  {
+if (next)
+  next->add_callbacks (new_next);
+else
+  next = new_next;
+  }
+
+  virtual ~template_instantiations_callbacks ()
+  {
+delete next;
+  }
+
+private:
+  template_instantiations_callbacks* next;
+
+  virtual void _function_instantiation (tree, tree, tree)
+  {
+  }
+
+  virtual void _class_instantiation (tree, tree, tree)
+  {
+  }
+
+  virtual void _using_instantiation (tree, tree, tree)
+  {
+  }
+};
+
 /* in class.c */

 extern int current_class_depth;
@@ -6199,6 +6254,9 @@ extern void register_local_specialization
(tree, tree);
 extern tree retrieve_local_specialization   (tree);
 extern tree extract_fnparm_pack (tree, tree *);
 extern tree template_parm_to_arg(tree);
+extern void call_template_instantiation_callbacks (void);
+extern void add_template_instantiations_callbacks
(template_instantiations_callbacks* new_callback);
+extern void clean_up_callbacks (void);

 /* in repo.c */
 extern void init_repo(void);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 73b0d28..097e3564 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4914,6 +4914,9 @@ c_parse_final_cleanups (void)
   dump_time_statistics ();
 }

+  call_template_instantiation_callbacks ();
+  clean_up_callbacks ();
+
   timevar_stop (TV_PHASE_DEFERRED);
   timevar_start (TV_PHASE_PARSING);

diff --git a/gcc/cp/pt

[PATCH] New plugin event when evaluating a constexpr call

2016-03-30 Thread Andres Tiraboschi
Hi
 This patch adds a plugin event when evaluating a call expression in constexpr.
 The goal of this patch is to allow the plugins to analyze and or
modify the evaluation of constant expressions.


Changelog 2016-3-30  Andres Tiraboschi

*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/cp-tree.h.
*gcc/cp/constexpr.c (constexpr_call): Ditto.
*gcc/cp/constexpr.c (constexpr_ctx): Ditto.
*gcc/cp/constexpr.c (cxx_eval_constant_expression): Not static anymore.
*gcc/pc/cp-tree.h (constexpr_call_info): New Type.
*gcc/pc/cp-tree.h (constexpr_fundef): Moved type from gcc/cp/constexpr.c.
*gcc/pc/cp-tree.h (constexpr_call): Ditto.
*gcc/pc/cp-tree.h (constexpr_ctx): Ditto.
*gcc/pc/cp-tree.h (cxx_eval_constant_expression): Declared.




diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 5f97c9d..5562e44 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -31,6 +31,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "tree-inline.h"
 #include "ubsan.h"
+#include "plugin-api.h"
+#include "plugin.h"

 static bool verify_constant (tree, bool, bool *, bool *);
 #define VERIFY_CONSTANT(X)\
@@ -112,13 +114,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
 {
   static hashval_t hash (constexpr_fundef *);
@@ -856,62 +851,12 @@ 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
 {
   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 *values;
-  /* SAVE_EXPRs that we've seen within the current LOOP_EXPR.  NULL if we
- aren't inside a loop.  */
-  hash_set *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.  */

@@ -1303,6 +1248,22 @@ cxx_eval_call_expression (const constexpr_ctx
*ctx, tree t,
   bool non_constant_args = false;
   cxx_bind_parameters_in_call (ctx, t, &new_call,
non_constant_p, overflow_p, &non_constant_args);
+
+  constexpr_call_info call_info;
+  call_info.function = t;
+  call_info.lval = lval;
+  call_info.call = &new_call;
+  call_info.call_stack = call_stack;
+  call_info.non_constant_args = &non_constant_args;
+  call_info.non_const_p = non_constant_p;
+  call_info.ctx = ctx;
+  call_info.result = NULL_TREE;
+  invoke_plugin_callbacks (PLUGIN_EVAL_CALL_CONSTEXPR, &call_info);
+  if (call_info.result != NULL_TREE)
+{
+  return call_info.result;
+}
+
   if (*non_constant_p)
 return t;

diff -

Re: [PATCH] New flag in order to dump information about template instantiations.

2016-03-30 Thread Andres Tiraboschi
2016-03-29 12:07 GMT-03:00 Andres Tiraboschi
:
> Hi,
> the attached patch adds a new compilation flag
> 'ftemplate-instantiations' in order
> to allow dumping debug information for template instantiations.
> This flag has 2 possible values: none(by default) and hreadable, that
> prints witch
> templates instantiations had been made in a human readable way.
> This patch was also made in order to add options easily and to interact with
> plugins.
>   For example in a plugin can be defined a derived class for
> template_instantiations_callbacks
> implementing _function_instantiation, _class_instantiation, 
> _using_instantiation
> and then using add_template_instantiations_callbacks in order to
> access information
> about witch template instantiations had been made.
>
> Changelog
> 2016-03-29  Andres Tiraboschi  
>
> * gcc/c-family/c.opt (ftemplate-instantiations): New flag.
> * gcc/flag-types.h (ti_dump_options): New type.
> * gcc/cp/decl2.c (cp_write_global_declarations): Added code to
> dump information.
> * gcc/cp/cp-tree.h (template_instantiations_callbacks): New type.
> (call_template_instantiation_callbacks): Declare.
> (add_template_instantiations_callbacks): Likewise.
> (clean_up_callbacks): Likewise.
> * gcc/cp/pt.c (human_readable_template_instantiations): New type.
> (instantiation_callbacks): Declare.
> (call_template_instantiation_callback): New function.
> (call_template_instantiation_callbacks): Likewise.
> (add_template_instantiations_callbacks): Likewise.
> (initialize_instantiations_callbacks): Likewise.
> (clean_up_callbacks): Likewise.
> (init_template_processing): Added code to initialize 
> instatiation_callbacks.
> (register_specialization): Added code to dump information.
> * gcc/doc/invoke.texi (ftemplate-instantiations): Added documentation.
>
>
> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index 7c5f6c7..a0ebcdc 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -1487,6 +1487,19 @@ fstats
>  C++ ObjC++ Var(flag_detailed_statistics)
>  Display statistics accumulated during compilation.
>
> +ftemplate-instantiations=
> +C++ Joined RejectNegative Enum(ti_dump_options) Var(ti_dump_option)
> Init(TI_NONE)
> +Dump information about wich templates have been instantiated
> +
> +Enum
> +Name(ti_dump_options) Type(enum ti_dump_options)
> UnknownError(unrecognized template instantiation dumping option %qs)
> +
> +EnumValue
> +Enum(ti_dump_options) String(none) Value(TI_NONE)
> +
> +EnumValue
> +Enum(ti_dump_options) String(hreadable) Value(TI_HREADABLE)
> +
>  fstrict-enums
>  C++ ObjC++ Optimization Var(flag_strict_enums)
>  Assume that values of enumeration type are always within the minimum
> range of that type.
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 15b004d..f682b4a 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -4816,6 +4816,61 @@ struct local_specialization_stack
>hash_map *saved;
>  };
>
> +class template_instantiations_callbacks
> +{
> +public:
> +  template_instantiations_callbacks () : next(NULL){}
> +
> +  void function_instantiation (tree tmpl, tree args, tree spec)
> +  {
> +_function_instantiation (tmpl, args, spec);
> +if (next != NULL)
> +  next->function_instantiation (tmpl, args, spec);
> +  }
> +
> +  void class_instantiation (tree tmpl, tree args, tree spec)
> +  {
> +_class_instantiation (tmpl, args, spec);
> +if (next != NULL)
> +  next->class_instantiation (tmpl, args, spec);
> +  }
> +
> +  void using_instantiation (tree tmpl, tree args, tree spec)
> +  {
> +_using_instantiation (tmpl, args, spec);
> +if (next != NULL)
> +  next->using_instantiation (tmpl, args, spec);
> +  }
> +
> +  void add_callbacks (template_instantiations_callbacks* new_next)
> +  {
> +if (next)
> +  next->add_callbacks (new_next);
> +else
> +  next = new_next;
> +  }
> +
> +  virtual ~template_instantiations_callbacks ()
> +  {
> +delete next;
> +  }
> +
> +private:
> +  template_instantiations_callbacks* next;
> +
> +  virtual void _function_instantiation (tree, tree, tree)
> +  {
> +  }
> +
> +  virtual void _class_instantiation (tree, tree, tree)
> +  {
> +  }
> +
> +  virtual void _using_instantiation (tree, tree, tree)
> +  {
> +  }
> +};
> +
>  /* in class.c */
>
>  extern int current_class_depth;
> @@ -6199,6 +6254,9 @@ extern void register_local_specialization
> (tree, tree);
>  extern tree retrieve_local_specialization   (tree);
>  extern tree extract_fnparm_

[PING][PATCH] New plugin event when evaluating a constexpr call

2016-04-25 Thread Andres Tiraboschi
Hi
 This patch adds a plugin event when evaluating a call expression in constexpr.
 The goal of this patch is to allow the plugins to analyze and or
modify the evaluation of constant expressions.


Changelog 2016-4-25  Andres Tiraboschi

*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/cp-tree.h.
*gcc/cp/constexpr.c (constexpr_call): Ditto.
*gcc/cp/constexpr.c (constexpr_ctx): Ditto.
*gcc/cp/constexpr.c (cxx_eval_constant_expression): Not static anymore.
*gcc/pc/cp-tree.h (constexpr_call_info): New Type.
*gcc/pc/cp-tree.h (constexpr_fundef): Moved type from gcc/cp/constexpr.c.
*gcc/pc/cp-tree.h (constexpr_call): Ditto.
*gcc/pc/cp-tree.h (constexpr_ctx): Ditto.
*gcc/pc/cp-tree.h (cxx_eval_constant_expression): Declared.




diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 5f97c9d..5562e44 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -31,6 +31,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "tree-inline.h"
 #include "ubsan.h"
+#include "plugin-api.h"
+#include "plugin.h"

 static bool verify_constant (tree, bool, bool *, bool *);
 #define VERIFY_CONSTANT(X)\
@@ -112,13 +114,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
 {
   static hashval_t hash (constexpr_fundef *);
@@ -856,62 +851,12 @@ 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
 {
   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 *values;
-  /* SAVE_EXPRs that we've seen within the current LOOP_EXPR.  NULL if we
- aren't inside a loop.  */
-  hash_set *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.  */

@@ -1303,6 +1248,22 @@ cxx_eval_call_expression (const constexpr_ctx
*ctx, tree t,
   bool non_constant_args = false;
   cxx_bind_parameters_in_call (ctx, t, &new_call,
non_constant_p, overflow_p, &non_constant_args);
+
+  constexpr_call_info call_info;
+  call_info.function = t;
+  call_info.lval = lval;
+  call_info.call = &new_call;
+  call_info.call_stack = call_stack;
+  call_info.non_constant_args = &non_constant_args;
+  call_info.non_const_p = non_constant_p;
+  call_info.ctx = ctx;
+  call_info.result = NULL_TREE;
+  invoke_plugin_callbacks (PLUGIN_EVAL_CALL_CONSTEXPR, &call_info);
+  if (call_info.result != NULL_TREE)
+{
+  return call_info.result;
+}
+
   if (*non_constant_p)
 return t;

diff -

Re: [PING][PATCH] New plugin event when evaluating a constexpr call

2016-04-26 Thread Andres Tiraboschi
Hi, thanks for answering,

2016-04-25 16:21 GMT-03:00 Jason Merrill :
> Let's create a constexpr.h rather than expose constexpr internals to all of
> the front end.  Really, I'd prefer to avoid exposing them at all. Why does
> what you want to do require all this implementation detail?

Ok, you are right, I'll make a constexpr.h.

> This is a curious place to invoke the callback.  Why before the
> *non_constant_p?  More generally, why between evaluating the arguments and
> evaluating the function body?

That was because I was interested just in the functions and its
arguments, but you are right, I'll do the callback at the beginning of
the function.

Regards,
Andrés.


Re: [PING][PATCH] New plugin event when evaluating a constexpr call

2016-05-02 Thread Andres Tiraboschi
2016-04-26 10:41 GMT-03:00 Andres Tiraboschi
:
> Hi, thanks for answering,
>
> 2016-04-25 16:21 GMT-03:00 Jason Merrill :
>> Let's create a constexpr.h rather than expose constexpr internals to all of
>> the front end.  Really, I'd prefer to avoid exposing them at all. Why does
>> what you want to do require all this implementation detail?
>
> Ok, you are right, I'll make a constexpr.h.
>
>> This is a curious place to invoke the callback.  Why before the
>> *non_constant_p?  More generally, why between evaluating the arguments and
>> evaluating the function body?
>
> That was because I was interested just in the functions and its
> arguments, but you are right, I'll do the callback at the beginning of
> the function.
>
> Regards,
> Andrés.

Hi
 I made the the corrections to the patch.


Changelog 2016-5-2  Andres Tiraboschi

*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 (cxx_eval_constant_expression): Not static anymore.
*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/config-lang.in (gtfiles): Added \$(srcdir)/cp/constexpr.h
*gcc/cp/Make-lang.in (CP_PLUGIN_HEADERS): Added constexpr.h.
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 8770f6f..aa8811c 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..8b62d86 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_con

Re: [PING][PATCH] New plugin event when evaluating a constexpr call

2016-05-05 Thread Andres Tiraboschi
Hi,
thanks for the feedback, I'll do the changes.

2016-05-04 13:16 GMT-03:00 Jason Merrill :
> 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
>


Re: [PING][PATCH] New plugin event when evaluating a constexpr call

2016-05-06 Thread Andres Tiraboschi
Hi
 I made the corrections to the patch.

Changelog 2016-5-6  Andres Tiraboschi

*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
:
> Hi,
> thanks for the feedback, I'll do the changes.
>
> 2016-05-04 13:16 GMT-03:00 Jason Merrill :
>> 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"

Question regarding bug 70584

2016-05-20 Thread Andres Tiraboschi
While analysing this bug we arrived to the following code at
tree.c:145 (lvalue_kind):

case VAR_DECL:
  if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
  && DECL_LANG_SPECIFIC (ref)
  && DECL_IN_AGGR_P (ref))
return clk_none;

That condition fails so a fall-through to the next case labels causes
to return clk_ordinary, whereas this is about a constexpr value
(rather than a reference).

As an experiment, we forced the condition above to return clk_none and
the bug is not reproduced.

We are suspecting either that the condition is too restrictive or a
fall-through is not intended. Why is the condition requiring
DECL_IN_AGGR_P?

Thank,

Andres.


Re: [PING][PATCH V2] plugin event for C/C++ function definitions

2014-12-12 Thread Andres Tiraboschi
PING, request for maintainer please

2014-12-02 15:15 GMT-03:00 Andres Tiraboschi
:
> Hi, this patch adds a new plugin event PLUGIN_START_PARSE_FUNCTION and 
> PLUGIN_FINISH_PARSE_FUNCTION that are invoked at start_function and 
> finish_function respectively in the C and C++ frontends.
> PLUGIN_START_PARSE_FUNCTION is called before parsing the function body.
> PLUGIN_FINISH_PARSE_FUNCTION is called after parsing a function definition.
>
> Since I have no write privileges please commit this for me if ok.
>
> changelog:
>
>  gcc/c/c-decl.c: Invoke callbacks in start_function and finish_function.
>  gcc/cp/decl.c: Invoke callbacks in start_function and finish_function.
>
>  gcc/doc/plugins.texi: Add documentation about PLUGIN_START_FUNCTION and 
> PLUGIN_FINISH_FUNCTION
>  gcc/plugin.def: Add events for start_function and finish_function.
>  gcc/plugin.c (register_callback, invoke_plugin_callbacks): Same.
>
>  gcc/testsuite/g++.dg/plugin/def_plugin.c: New test plugin.
>  gcc/testsuite/g++.dg/plugin/def-plugin-test.C: Testcase for above plugin.
>  gcc/testsuite/g++.dg/plugin/plugin.exp
>
> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> index 6413e6f..d9d922c 100644
> --- a/gcc/c/c-decl.c
> +++ b/gcc/c/c-decl.c
> @@ -4449,6 +4449,7 @@ start_decl (struct c_declarator *declarator, struct 
> c_declspecs *declspecs,
>decl = grokdeclarator (declarator, declspecs,
>  NORMAL, initialized, NULL, &attributes, &expr, NULL,
>  deprecated_state);
> +  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl);
>if (!decl)
>  return 0;
>
> @@ -9031,6 +9032,7 @@ finish_function (void)
>   It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
>   tree_rest_of_compilation.  */
>set_cfun (NULL);
> +  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, 
> current_function_decl);
>current_function_decl = NULL;
>  }
>
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index 716ab5f..6adf2e4 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -13671,6 +13671,7 @@ start_function (cp_decl_specifier_seq *declspecs,
>tree decl1;
>
>decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
> +  invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
>if (decl1 == error_mark_node)
>  return false;
>/* If the declarator is not suitable for a function definition,
> @@ -14301,6 +14302,7 @@ finish_function (int flags)
>vec_free (deferred_mark_used_calls);
>  }
>
> +  invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, fndecl);
>return fndecl;
>  }
>
> diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
> index 4a839b8..1c9e074 100644
> --- a/gcc/doc/plugins.texi
> +++ b/gcc/doc/plugins.texi
> @@ -174,6 +174,8 @@ Callbacks can be invoked at the following pre-determined 
> events:
>  @smallexample
>  enum plugin_event
>  @{
> +  PLUGIN_START_PARSE_FUNCTION,  /* Called before parsing the body of a 
> function. */
> +  PLUGIN_FINISH_PARSE_FUNCTION, /* After finishing parsing a function. */
>PLUGIN_PASS_MANAGER_SETUP,/* To hook into pass manager.  */
>PLUGIN_FINISH_TYPE,   /* After finishing parsing a type.  */
>PLUGIN_FINISH_DECL,   /* After finishing parsing a declaration. */
> diff --git a/gcc/plugin.c b/gcc/plugin.c
> index 8debc09..f7a8b64 100644
> --- a/gcc/plugin.c
> +++ b/gcc/plugin.c
> @@ -433,6 +433,8 @@ register_callback (const char *plugin_name,
> return;
>   }
>/* Fall through.  */
> +  case PLUGIN_START_PARSE_FUNCTION:
> +  case PLUGIN_FINISH_PARSE_FUNCTION:
>case PLUGIN_FINISH_TYPE:
>case PLUGIN_FINISH_DECL:
>case PLUGIN_START_UNIT:
> @@ -511,6 +513,8 @@ 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_START_PARSE_FUNCTION:
> +  case PLUGIN_FINISH_PARSE_FUNCTION:
>case PLUGIN_FINISH_TYPE:
>case PLUGIN_FINISH_DECL:
>case PLUGIN_START_UNIT:
> diff --git a/gcc/plugin.def b/gcc/plugin.def
> index df5d383..4b7f6ef 100644
> --- a/gcc/plugin.def
> +++ b/gcc/plugin.def
> @@ -17,6 +17,11 @@ 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 before parsing the body of a function.  */
> +DEFEVENT (PLUGIN_START_PARSE_FUNCTION)
> +
> +/* After finishing parsing a function. */
> +DEFEVENT (PLUGIN_FINISH_PARSE_FUNCTION)
>
&g