/* Code to maintain a C++ template repository.
- Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright (C) 1995-2019 Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com)
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* My strategy here is as follows:
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
#include "cp-tree.h"
-#include "input.h"
-#include "obstack.h"
+#include "stringpool.h"
#include "toplev.h"
-#include "diagnostic.h"
-static char *extract_string (char **);
+static const char *extract_string (const char **);
static const char *get_base_filename (const char *);
-static void open_repo_file (const char *);
+static FILE *open_repo_file (const char *);
static char *afgets (FILE *);
-static void reopen_repo_file_for_write (void);
+static FILE *reopen_repo_file_for_write (void);
-static GTY(()) tree pending_repo;
+static GTY(()) vec<tree, va_gc> *pending_repo;
static char *repo_name;
-static FILE *repo_file;
static const char *old_args, *old_dir, *old_main;
/* Parse a reasonable subset of shell quoting syntax. */
-static char *
-extract_string (char **pp)
+static const char *
+extract_string (const char **pp)
{
- char *p = *pp;
+ const char *p = *pp;
int backquote = 0;
int inside = 0;
obstack_1grow (&temporary_obstack, '\0');
*pp = p;
- return obstack_finish (&temporary_obstack);
+ return (char *) obstack_finish (&temporary_obstack);
}
static const char *
get_base_filename (const char *filename)
{
- char *p = getenv ("COLLECT_GCC_OPTIONS");
- char *output = NULL;
+ const char *p = getenv ("COLLECT_GCC_OPTIONS");
+ const char *output = NULL;
int compiling = 0;
while (p && *p)
{
- char *q = extract_string (&p);
+ const char *q = extract_string (&p);
if (strcmp (q, "-o") == 0)
- output = extract_string (&p);
+ {
+ if (flag_compare_debug)
+ /* Just in case aux_base_name was based on a name with two
+ or more '.'s, add an arbitrary extension that will be
+ stripped by the caller. */
+ output = concat (aux_base_name, ".o", NULL);
+ else
+ output = extract_string (&p);
+ }
else if (strcmp (q, "-c") == 0)
compiling = 1;
}
if (p && ! compiling)
{
- warning (0, "-frepo must be used with -c");
+ warning (0, "%<-frepo%> must be used with %<-c%>");
flag_use_repository = 0;
return NULL;
}
return lbasename (filename);
}
-static void
+static FILE *
open_repo_file (const char *filename)
{
const char *p;
const char *s = get_base_filename (filename);
if (s == NULL)
- return;
+ return NULL;
p = lbasename (s);
p = strrchr (p, '.');
if (! p)
p = s + strlen (s);
- repo_name = xmalloc (p - s + 5);
+ repo_name = XNEWVEC (char, p - s + 5);
memcpy (repo_name, s, p - s);
memcpy (repo_name + (p - s), ".rpo", 5);
- repo_file = fopen (repo_name, "r");
+ return fopen (repo_name, "r");
}
static char *
if (obstack_object_size (&temporary_obstack) == 0)
return NULL;
obstack_1grow (&temporary_obstack, '\0');
- return obstack_finish (&temporary_obstack);
+ return (char *) obstack_finish (&temporary_obstack);
}
void
init_repo (void)
{
char *buf;
+ const char *p;
+ FILE *repo_file;
if (! flag_use_repository)
return;
if (!temporary_obstack_initialized_p)
gcc_obstack_init (&temporary_obstack);
- open_repo_file (main_input_filename);
+ repo_file = open_repo_file (main_input_filename);
if (repo_file == 0)
return;
obstack_free (&temporary_obstack, buf);
}
fclose (repo_file);
+
+ if (old_args && !get_random_seed (true)
+ && (p = strstr (old_args, "'-frandom-seed=")))
+ set_random_seed (extract_string (&p) + strlen ("-frandom-seed="));
}
-static void
+static FILE *
reopen_repo_file_for_write (void)
{
- repo_file = fopen (repo_name, "w");
+ FILE *repo_file = fopen (repo_name, "w");
if (repo_file == 0)
{
- error ("can't create repository information file %qs", repo_name);
+ error ("can%'t create repository information file %qs", repo_name);
flag_use_repository = 0;
}
+
+ return repo_file;
}
/* Emit any pending repos. */
void
finish_repo (void)
{
- tree t;
+ tree val;
char *dir, *args;
+ FILE *repo_file;
+ unsigned ix;
- if (!flag_use_repository)
+ if (!flag_use_repository || flag_compare_debug)
return;
- if (errorcount || sorrycount)
- goto out;
+ if (seen_error ())
+ return;
- reopen_repo_file_for_write ();
+ repo_file = reopen_repo_file_for_write ();
if (repo_file == 0)
goto out;
fprintf (repo_file, "D %s\n", dir);
args = getenv ("COLLECT_GCC_OPTIONS");
if (args)
- fprintf (repo_file, "A %s\n", args);
+ {
+ fprintf (repo_file, "A %s", args);
+ /* If -frandom-seed is not among the ARGS, then add the value
+ that we chose. That will ensure that the names of types from
+ anonymous namespaces will get the same mangling when this
+ file is recompiled. */
+ if (!strstr (args, "'-frandom-seed="))
+ fprintf (repo_file, " '-frandom-seed=" HOST_WIDE_INT_PRINT_HEX_PURE "'",
+ get_random_seed (false));
+ fprintf (repo_file, "\n");
+ }
- for (t = pending_repo; t; t = TREE_CHAIN (t))
+ FOR_EACH_VEC_SAFE_ELT_REVERSE (pending_repo, ix, val)
{
- tree val = TREE_VALUE (t);
tree name = DECL_ASSEMBLER_NAME (val);
char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
int
repo_emit_p (tree decl)
{
+ int ret = 0;
gcc_assert (TREE_PUBLIC (decl));
- gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL);
- gcc_assert (!DECL_REALLY_EXTERN (decl));
+ gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
+ gcc_assert (!DECL_REALLY_EXTERN (decl)
+ /* A clone might not have its linkage flags updated yet
+ because we call import_export_decl before
+ maybe_clone_body. */
+ || DECL_ABSTRACT_ORIGIN (decl));
/* When not using the repository, emit everything. */
if (!flag_use_repository)
is an artificial restriction; the code in the prelinker and here
will work fine if all entities with vague linkage are managed by
the repository. */
- if (TREE_CODE (decl) == VAR_DECL)
+ if (VAR_P (decl))
{
tree type = NULL_TREE;
if (DECL_VTABLE_OR_VTT_P (decl))
else if (DECL_TINFO_P (decl))
type = TREE_TYPE (DECL_NAME (decl));
if (!DECL_TEMPLATE_INSTANTIATION (decl)
- && !CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ && (!TYPE_LANG_SPECIFIC (type)
+ || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
return 2;
+ /* Const static data members initialized by constant expressions must
+ be processed where needed so that their definitions are
+ available. Still record them into *.rpo files, so if they
+ weren't actually emitted and collect2 requests them, they can
+ be provided. */
+ if (decl_maybe_constant_var_p (decl)
+ && DECL_CLASS_SCOPE_P (decl))
+ ret = 2;
}
else if (!DECL_TEMPLATE_INSTANTIATION (decl))
return 2;
+ if (DECL_EXPLICIT_INSTANTIATION (decl))
+ return 2;
+
/* For constructors and destructors, the repository contains
information about the clones -- not the original function --
because only the clones are emitted in the object file. */
- if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
- || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
+ if (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl))
{
int emit_p = 0;
tree clone;
if (!DECL_REPO_AVAILABLE_P (decl))
{
DECL_REPO_AVAILABLE_P (decl) = 1;
- pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
+ vec_safe_push (pending_repo, decl);
}
- return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
+ return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
}
/* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
export from this translation unit. */
bool
-repo_export_class_p (tree class_type)
+repo_export_class_p (const_tree class_type)
{
if (!flag_use_repository)
return false;