]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libcc1/libcp1plugin.cc
Fix find_always_executed_bbs handling of infinite loops
[thirdparty/gcc.git] / libcc1 / libcp1plugin.cc
index 24582c74a86daea3d908789170af113cd45cfdd5..8d394c0cfdb804ae81619d91f42b9be6b5a97648 100644 (file)
@@ -1,5 +1,5 @@
 /* Library interface to C++ front end.
-   Copyright (C) 2014-2020 Free Software Foundation, Inc.
+   Copyright (C) 2014-2023 Free Software Foundation, Inc.
 
    This file is part of GCC.  As it interacts with GDB through libcc1,
    they all become a single program as regards the GNU GPL's requirements.
 #undef PACKAGE_TARNAME
 #undef PACKAGE_VERSION
 
+#define INCLUDE_MEMORY
 #include "gcc-plugin.h"
 #include "system.h"
 #include "coretypes.h"
 #include "stringpool.h"
 
 #include "gcc-interface.h"
-#include "hash-set.h"
 #include "machmode.h"
 #include "vec.h"
 #include "double-int.h"
 #include "connection.hh"
 #include "marshall-cp.hh"
 #include "rpc.hh"
+#include "context.hh"
 
-#ifdef __GNUC__
-#pragma GCC visibility push(default)
-#endif
-int plugin_is_GPL_compatible;
-#ifdef __GNUC__
-#pragma GCC visibility pop
-#endif
+#include <vector>
 
-\f
-
-static int ATTRIBUTE_UNUSED
-check_symbol_mask[GCC_CP_SYMBOL_MASK >= GCC_CP_SYMBOL_END ? 1 : -1];
-
-// This is put into the lang hooks when the plugin starts.
-
-static void
-plugin_print_error_function (diagnostic_context *context, const char *file,
-                            diagnostic_info *diagnostic)
-{
-  if (current_function_decl != NULL_TREE
-      && DECL_NAME (current_function_decl) != NULL_TREE
-      && strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
-                GCC_FE_WRAPPER_FUNCTION) == 0)
-    return;
-  lhd_print_error_function (context, file, diagnostic);
-}
+using namespace cc1_plugin;
 
 \f
 
-static unsigned long long
-convert_out (tree t)
-{
-  return (unsigned long long) (uintptr_t) t;
-}
-
-static tree
-convert_in (unsigned long long v)
-{
-  return (tree) (uintptr_t) v;
-}
+static_assert (GCC_CP_SYMBOL_MASK >= GCC_CP_SYMBOL_END,
+              "GCC_CP_SYMBOL_MASK >= GCC_CP_SYMBOL_END");
 
 \f
 
-struct decl_addr_value
-{
-  tree decl;
-  tree address;
-};
-
-struct decl_addr_hasher : free_ptr_hash<decl_addr_value>
-{
-  static inline hashval_t hash (const decl_addr_value *);
-  static inline bool equal (const decl_addr_value *, const decl_addr_value *);
-};
-
-inline hashval_t
-decl_addr_hasher::hash (const decl_addr_value *e)
-{
-  return DECL_UID (e->decl);
-}
-
-inline bool
-decl_addr_hasher::equal (const decl_addr_value *p1, const decl_addr_value *p2)
-{
-  return p1->decl == p2->decl;
-}
-
-\f
-
-struct string_hasher : nofree_ptr_hash<const char>
-{
-  static inline hashval_t hash (const char *s)
-  {
-    return htab_hash_string (s);
-  }
-
-  static inline bool equal (const char *p1, const char *p2)
-  {
-    return strcmp (p1, p2) == 0;
-  }
-};
-
-\f
-
-struct plugin_context : public cc1_plugin::connection
-{
-  plugin_context (int fd);
-
-  // Map decls to addresses.
-  hash_table<decl_addr_hasher> address_map;
-
-  // A collection of trees that are preserved for the GC.
-  hash_table< nofree_ptr_hash<tree_node> > preserved;
-
-  // File name cache.
-  hash_table<string_hasher> file_names;
-
-  // Perform GC marking.
-  void mark ();
-
-  // Preserve a tree during the plugin's operation.
-  tree preserve (tree t)
-  {
-    tree_node **slot = preserved.find_slot (t, INSERT);
-    *slot = t;
-    return t;
-  }
-
-  location_t get_location_t (const char *filename,
-                            unsigned int line_number)
-  {
-    if (filename == NULL)
-      return UNKNOWN_LOCATION;
-
-    filename = intern_filename (filename);
-    linemap_add (line_table, LC_ENTER, false, filename, line_number);
-    location_t loc = linemap_line_start (line_table, line_number, 0);
-    linemap_add (line_table, LC_LEAVE, false, NULL, 0);
-    return loc;
-  }
-
-private:
-
-  // Add a file name to FILE_NAMES and return the canonical copy.
-  const char *intern_filename (const char *filename)
-  {
-    const char **slot = file_names.find_slot (filename, INSERT);
-    if (*slot == NULL)
-      {
-       /* The file name must live as long as the line map, which
-          effectively means as long as this compilation.  So, we copy
-          the string here but never free it.  */
-       *slot = xstrdup (filename);
-      }
-    return *slot;
-  }
-};
-
-static plugin_context *current_context;
-
-\f
-
-plugin_context::plugin_context (int fd)
-  : cc1_plugin::connection (fd),
-    address_map (30),
-    preserved (30),
-    file_names (30)
-{
-}
-
-void
-plugin_context::mark ()
-{
-  for (hash_table<decl_addr_hasher>::iterator it = address_map.begin ();
-       it != address_map.end ();
-       ++it)
-    {
-      ggc_mark ((*it)->decl);
-      ggc_mark ((*it)->address);
-    }
-
-  for (hash_table< nofree_ptr_hash<tree_node> >::iterator
-        it = preserved.begin (); it != preserved.end (); ++it)
-    ggc_mark (&*it);
-}
-
 static void
 plugin_binding_oracle (enum cp_oracle_request kind, tree identifier)
 {
@@ -353,8 +199,7 @@ supplement_binding (cxx_binding *binding, tree decl)
           /* If TARGET_BVAL is anticipated but has not yet been
              declared, pretend it is not there at all.  */
           || (TREE_CODE (target_bval) == FUNCTION_DECL
-              && DECL_ANTICIPATED (target_bval)
-              && !DECL_HIDDEN_FRIEND_P (target_bval)))
+              && DECL_IS_UNDECLARED_BUILTIN (target_bval)))
     binding->value = decl;
   else if (TREE_CODE (target_bval) == TYPE_DECL
           && DECL_ARTIFICIAL (target_bval)
@@ -407,7 +252,7 @@ supplement_binding (cxx_binding *binding, tree decl)
           && DECL_EXTERNAL (target_decl) && DECL_EXTERNAL (target_bval)
           && !DECL_CLASS_SCOPE_P (target_decl))
     {
-      duplicate_decls (decl, binding->value, /*newdecl_is_friend=*/false);
+      duplicate_decls (decl, binding->value);
       ok = false;
     }
   else if (TREE_CODE (decl) == NAMESPACE_DECL
@@ -697,7 +542,7 @@ record_decl_address (plugin_context *ctx, decl_addr_value value)
   **slot = value;
   /* We don't want GCC to warn about e.g. static functions
      without a code definition.  */
-  TREE_NO_WARNING (value.decl) = 1;
+  suppress_warning (value.decl);
   return *slot;
 }
 
@@ -785,14 +630,14 @@ safe_push_template_decl (tree decl)
 }
 
 static inline tree
-safe_pushtag (tree name, tree type, tag_scope scope)
+safe_pushtag (tree name, tree type)
 {
   void (*save_oracle) (enum cp_oracle_request, tree identifier);
 
   save_oracle = cp_binding_oracle;
   cp_binding_oracle = NULL;
 
-  tree ret = pushtag (name, type, scope);
+  tree ret = pushtag (name, type);
 
   cp_binding_oracle = save_oracle;
 
@@ -800,14 +645,14 @@ safe_pushtag (tree name, tree type, tag_scope scope)
 }
 
 static inline tree
-safe_pushdecl_maybe_friend (tree decl, bool is_friend)
+safe_pushdecl (tree decl)
 {
   void (*save_oracle) (enum cp_oracle_request, tree identifier);
 
   save_oracle = cp_binding_oracle;
   cp_binding_oracle = NULL;
 
-  tree ret = pushdecl (decl, is_friend);
+  tree ret = pushdecl (decl);
 
   cp_binding_oracle = save_oracle;
 
@@ -1514,7 +1359,7 @@ plugin_build_decl (cc1_plugin::connection *self,
   if (template_decl_p)
     {
       if (RECORD_OR_UNION_CODE_P (code))
-       safe_pushtag (identifier, TREE_TYPE (decl), ts_current);
+       safe_pushtag (identifier, TREE_TYPE (decl));
       else
        decl = safe_push_template_decl (decl);
 
@@ -1533,11 +1378,11 @@ plugin_build_decl (cc1_plugin::connection *self,
        finish_member_declaration (tdecl);
     }
   else if (RECORD_OR_UNION_CODE_P (code))
-    safe_pushtag (identifier, TREE_TYPE (decl), ts_current);
+    safe_pushtag (identifier, TREE_TYPE (decl));
   else if (class_member_p)
     finish_member_declaration (decl);
   else
-    decl = safe_pushdecl_maybe_friend (decl, false);
+    decl = safe_pushdecl (decl);
 
   if ((ctor || dtor)
       /* Don't crash after a duplicate declaration of a cdtor.  */
@@ -1650,7 +1495,7 @@ plugin_add_friend (cc1_plugin::connection * /* self */,
     make_friend_class (type, TREE_TYPE (decl), true);
   else
     {
-      DECL_FRIEND_P (decl) = true;
+      DECL_UNIQUE_FRIEND_P (decl) = true;
       add_friend (type, decl, true);
     }
 
@@ -1810,7 +1655,8 @@ plugin_start_closure_class_type (cc1_plugin::connection *self,
 
   /* Instead of calling record_lambda_scope, do this:  */
   LAMBDA_EXPR_EXTRA_SCOPE (lambda_expr) = extra_scope;
-  LAMBDA_EXPR_DISCRIMINATOR (lambda_expr) = discriminator;
+  LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda_expr) = discriminator;
+  LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda_expr) = discriminator;
 
   tree decl = TYPE_NAME (type);
   determine_visibility (decl);
@@ -1981,24 +1827,21 @@ plugin_build_function_type (cc1_plugin::connection *self,
                            const struct gcc_type_array *argument_types_in,
                            int is_varargs)
 {
-  tree *argument_types;
   tree return_type = convert_in (return_type_in);
   tree result;
 
-  argument_types = new tree[argument_types_in->n_elements];
+  std::vector<tree> argument_types (argument_types_in->n_elements);
   for (int i = 0; i < argument_types_in->n_elements; ++i)
     argument_types[i] = convert_in (argument_types_in->elements[i]);
 
   if (is_varargs)
     result = build_varargs_function_type_array (return_type,
                                                argument_types_in->n_elements,
-                                               argument_types);
+                                               argument_types.data ());
   else
     result = build_function_type_array (return_type,
                                        argument_types_in->n_elements,
-                                       argument_types);
-
-  delete[] argument_types;
+                                       argument_types.data ());
 
   plugin_context *ctx = static_cast<plugin_context *> (self);
   return convert_out (ctx->preserve (result));
@@ -2652,10 +2495,10 @@ plugin_build_dependent_expr (cc1_plugin::connection *self,
     }
   tree res = identifier;
   if (!scope)
-    res = lookup_name_real (res, LOOK_where::BLOCK_NAMESPACE, 0, 0, 0);
+    res = lookup_name (res, LOOK_where::BLOCK_NAMESPACE);
   else if (!TYPE_P (scope) || !dependent_scope_p (scope))
     {
-      res = lookup_qualified_name (scope, res, false, true);
+      res = lookup_qualified_name (scope, res, LOOK_want::NORMAL, true);
       /* We've already resolved the name in the scope, so skip the
         build_qualified_name call below.  */
       scope = NULL;
@@ -2807,7 +2650,7 @@ plugin_build_unary_expr (cc1_plugin::connection *self,
     case SIZEOF_EXPR:
     case ALIGNOF_EXPR:
       result = cxx_sizeof_or_alignof_expr (input_location,
-                                          op0, opcode, true);
+                                          op0, opcode, true, true);
       break;
 
     case DELETE_EXPR:
@@ -2828,7 +2671,7 @@ plugin_build_unary_expr (cc1_plugin::connection *self,
       break;
 
     default:
-      result = build_x_unary_op (/*loc=*/0, opcode, op0, tf_error);
+      result = build_x_unary_op (/*loc=*/0, opcode, op0, NULL_TREE, tf_error);
       break;
     }
 
@@ -2953,7 +2796,7 @@ plugin_build_binary_expr (cc1_plugin::connection *self,
 
     default:
       result = build_x_binary_op (/*loc=*/0, opcode, op0, ERROR_MARK,
-                                 op1, ERROR_MARK, NULL, tf_error);
+                                 op1, ERROR_MARK, NULL_TREE, NULL, tf_error);
       break;
     }
 
@@ -3294,7 +3137,7 @@ plugin_build_call_expr (cc1_plugin::connection *self,
          fn = STRIP_TEMPLATE (fn);
 
          if (!DECL_FUNCTION_MEMBER_P (fn)
-             && !DECL_LOCAL_FUNCTION_P (fn))
+             && !DECL_LOCAL_DECL_P (fn))
            koenig_p = true;
        }
     }
@@ -3608,7 +3451,7 @@ plugin_build_constant (cc1_plugin::connection *self, gcc_type type_in,
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
   cp_finish_decl (decl, cst, true, NULL, LOOKUP_ONLYCONVERTING);
-  safe_pushdecl_maybe_friend (decl, false);
+  safe_pushdecl (decl);
 
   return 1;
 }
@@ -3643,22 +3486,13 @@ plugin_add_static_assert (cc1_plugin::connection *self,
 
   bool member_p = at_class_scope_p ();
 
-  finish_static_assert (condition, message, loc, member_p);
+  finish_static_assert (condition, message, loc, member_p, false);
 
   return 1;
 }
 
 \f
 
-// Perform GC marking.
-
-static void
-gc_mark (void *, void *)
-{
-  if (current_context != NULL)
-    current_context->mark ();
-}
-
 #ifdef __GNUC__
 #pragma GCC visibility push(default)
 #endif
@@ -3667,90 +3501,56 @@ int
 plugin_init (struct plugin_name_args *plugin_info,
             struct plugin_gcc_version *)
 {
-  long fd = -1;
-  for (int i = 0; i < plugin_info->argc; ++i)
-    {
-      if (strcmp (plugin_info->argv[i].key, "fd") == 0)
-       {
-         char *tail;
-         errno = 0;
-         fd = strtol (plugin_info->argv[i].value, &tail, 0);
-         if (*tail != '\0' || errno != 0)
-           fatal_error (input_location,
-                        "%s: invalid file descriptor argument to plugin",
-                        plugin_info->base_name);
-         break;
-       }
-    }
-  if (fd == -1)
-    fatal_error (input_location,
-                "%s: required plugin argument %<fd%> is missing",
-                plugin_info->base_name);
-
-  current_context = new plugin_context (fd);
-
-  // Handshake.
-  cc1_plugin::protocol_int version;
-  if (!current_context->require ('H')
-      || ! ::cc1_plugin::unmarshall (current_context, &version))
-    fatal_error (input_location,
-                "%s: handshake failed", plugin_info->base_name);
-  if (version != GCC_CP_FE_VERSION_0)
-    fatal_error (input_location,
-                "%s: unknown version in handshake", plugin_info->base_name);
+  generic_plugin_init (plugin_info, GCC_CP_FE_VERSION_0);
 
   register_callback (plugin_info->base_name, PLUGIN_PRAGMAS,
                     plugin_init_extra_pragmas, NULL);
   register_callback (plugin_info->base_name, PLUGIN_PRE_GENERICIZE,
                     rewrite_decls_to_addresses, NULL);
-  register_callback (plugin_info->base_name, PLUGIN_GGC_MARKING,
-                    gc_mark, NULL);
-
-  lang_hooks.print_error_function = plugin_print_error_function;
 
 #define GCC_METHOD0(R, N)                      \
   {                                            \
     cc1_plugin::callback_ftype *fun            \
-      = cc1_plugin::callback<R, plugin_ ## N>; \
+      = cc1_plugin::invoker<R>::invoke<plugin_ ## N>;  \
     current_context->add_callback (# N, fun);  \
   }
 #define GCC_METHOD1(R, N, A)                           \
   {                                                    \
     cc1_plugin::callback_ftype *fun                    \
-      = cc1_plugin::callback<R, A, plugin_ ## N>;      \
+      = cc1_plugin::invoker<R, A>::invoke<plugin_ ## N>;       \
     current_context->add_callback (# N, fun);          \
   }
 #define GCC_METHOD2(R, N, A, B)                                \
   {                                                    \
     cc1_plugin::callback_ftype *fun                    \
-      = cc1_plugin::callback<R, A, B, plugin_ ## N>;   \
+      = cc1_plugin::invoker<R, A, B>::invoke<plugin_ ## N>;    \
     current_context->add_callback (# N, fun);          \
   }
 #define GCC_METHOD3(R, N, A, B, C)                     \
   {                                                    \
     cc1_plugin::callback_ftype *fun                    \
-      = cc1_plugin::callback<R, A, B, C, plugin_ ## N>;        \
+      = cc1_plugin::invoker<R, A, B, C>::invoke<plugin_ ## N>; \
     current_context->add_callback (# N, fun);          \
   }
 #define GCC_METHOD4(R, N, A, B, C, D)          \
   {                                            \
     cc1_plugin::callback_ftype *fun            \
-      = cc1_plugin::callback<R, A, B, C, D,    \
-                            plugin_ ## N>;     \
+      = cc1_plugin::invoker<R, A, B, C,                \
+                           D>::invoke<plugin_ ## N>;   \
     current_context->add_callback (# N, fun);  \
   }
 #define GCC_METHOD5(R, N, A, B, C, D, E)       \
   {                                            \
     cc1_plugin::callback_ftype *fun            \
-      = cc1_plugin::callback<R, A, B, C, D, E, \
-                            plugin_ ## N>;     \
+      = cc1_plugin::invoker<R, A, B, C,                \
+                           D, E>::invoke<plugin_ ## N>;        \
     current_context->add_callback (# N, fun);  \
   }
 #define GCC_METHOD7(R, N, A, B, C, D, E, F, G)         \
   {                                                    \
     cc1_plugin::callback_ftype *fun                    \
-      = cc1_plugin::callback<R, A, B, C, D, E, F, G,   \
-                            plugin_ ## N>;             \
+      = cc1_plugin::invoker<R, A, B, C,                        \
+                           D, E, F, G>::invoke<plugin_ ## N>;          \
     current_context->add_callback (# N, fun);          \
   }