1/* Code to maintain a C++ template repository. 2 Copyright (C) 1995-2015 Free Software Foundation, Inc. 3 Contributed by Jason Merrill (jason@cygnus.com) 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21/* My strategy here is as follows: 22 23 Everything should be emitted in a translation unit where it is used. 24 The results of the automatic process should be easily reproducible with 25 explicit code. */ 26 27#include "config.h" 28#include "system.h" 29#include "coretypes.h" 30#include "tm.h" 31#include "hash-set.h" 32#include "machmode.h" 33#include "vec.h" 34#include "double-int.h" 35#include "input.h" 36#include "alias.h" 37#include "symtab.h" 38#include "wide-int.h" 39#include "inchash.h" 40#include "tree.h" 41#include "stringpool.h" 42#include "cp-tree.h" 43#include "input.h" 44#include "obstack.h" 45#include "toplev.h" 46#include "diagnostic-core.h" 47#include "flags.h" 48 49static const char *extract_string (const char **); 50static const char *get_base_filename (const char *); 51static FILE *open_repo_file (const char *); 52static char *afgets (FILE *); 53static FILE *reopen_repo_file_for_write (void); 54 55static GTY(()) vec<tree, va_gc> *pending_repo; 56static char *repo_name; 57 58static const char *old_args, *old_dir, *old_main; 59 60static struct obstack temporary_obstack; 61static bool temporary_obstack_initialized_p; 62 63/* Parse a reasonable subset of shell quoting syntax. */ 64 65static const char * 66extract_string (const char **pp) 67{ 68 const char *p = *pp; 69 int backquote = 0; 70 int inside = 0; 71 72 for (;;) 73 { 74 char c = *p; 75 if (c == '\0') 76 break; 77 ++p; 78 if (backquote) 79 { 80 obstack_1grow (&temporary_obstack, c); 81 backquote = 0; 82 } 83 else if (! inside && c == ' ') 84 break; 85 else if (! inside && c == '\\') 86 backquote = 1; 87 else if (c == '\'') 88 inside = !inside; 89 else 90 obstack_1grow (&temporary_obstack, c); 91 } 92 93 obstack_1grow (&temporary_obstack, '\0'); 94 *pp = p; 95 return (char *) obstack_finish (&temporary_obstack); 96} 97 98static const char * 99get_base_filename (const char *filename) 100{ 101 const char *p = getenv ("COLLECT_GCC_OPTIONS"); 102 const char *output = NULL; 103 int compiling = 0; 104 105 while (p && *p) 106 { 107 const char *q = extract_string (&p); 108 109 if (strcmp (q, "-o") == 0) 110 { 111 if (flag_compare_debug) 112 /* Just in case aux_base_name was based on a name with two 113 or more '.'s, add an arbitrary extension that will be 114 stripped by the caller. */ 115 output = concat (aux_base_name, ".o", NULL); 116 else 117 output = extract_string (&p); 118 } 119 else if (strcmp (q, "-c") == 0) 120 compiling = 1; 121 } 122 123 if (compiling && output) 124 return output; 125 126 if (p && ! compiling) 127 { 128 warning (0, "-frepo must be used with -c"); 129 flag_use_repository = 0; 130 return NULL; 131 } 132 133 return lbasename (filename); 134} 135 136static FILE * 137open_repo_file (const char *filename) 138{ 139 const char *p; 140 const char *s = get_base_filename (filename); 141 142 if (s == NULL) 143 return NULL; 144 145 p = lbasename (s); 146 p = strrchr (p, '.'); 147 if (! p) 148 p = s + strlen (s); 149 150 repo_name = XNEWVEC (char, p - s + 5); 151 memcpy (repo_name, s, p - s); 152 memcpy (repo_name + (p - s), ".rpo", 5); 153 154 return fopen (repo_name, "r"); 155} 156 157static char * 158afgets (FILE *stream) 159{ 160 int c; 161 while ((c = getc (stream)) != EOF && c != '\n') 162 obstack_1grow (&temporary_obstack, c); 163 if (obstack_object_size (&temporary_obstack) == 0) 164 return NULL; 165 obstack_1grow (&temporary_obstack, '\0'); 166 return (char *) obstack_finish (&temporary_obstack); 167} 168 169void 170init_repo (void) 171{ 172 char *buf; 173 const char *p; 174 FILE *repo_file; 175 176 if (! flag_use_repository) 177 return; 178 179 /* When a PCH file is loaded, the entire identifier table is 180 replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared. 181 So, we have to reread the repository file. */ 182 lang_post_pch_load = init_repo; 183 184 if (!temporary_obstack_initialized_p) 185 gcc_obstack_init (&temporary_obstack); 186 187 repo_file = open_repo_file (main_input_filename); 188 189 if (repo_file == 0) 190 return; 191 192 while ((buf = afgets (repo_file))) 193 { 194 switch (buf[0]) 195 { 196 case 'A': 197 old_args = ggc_strdup (buf + 2); 198 break; 199 case 'D': 200 old_dir = ggc_strdup (buf + 2); 201 break; 202 case 'M': 203 old_main = ggc_strdup (buf + 2); 204 break; 205 case 'O': 206 /* A symbol that we were able to define the last time this 207 file was compiled. */ 208 break; 209 case 'C': 210 /* A symbol that the prelinker has requested that we 211 define. */ 212 { 213 tree id = get_identifier (buf + 2); 214 IDENTIFIER_REPO_CHOSEN (id) = 1; 215 } 216 break; 217 default: 218 error ("mysterious repository information in %s", repo_name); 219 } 220 obstack_free (&temporary_obstack, buf); 221 } 222 fclose (repo_file); 223 224 if (old_args && !get_random_seed (true) 225 && (p = strstr (old_args, "'-frandom-seed="))) 226 set_random_seed (extract_string (&p) + strlen ("-frandom-seed=")); 227} 228 229static FILE * 230reopen_repo_file_for_write (void) 231{ 232 FILE *repo_file = fopen (repo_name, "w"); 233 234 if (repo_file == 0) 235 { 236 error ("can%'t create repository information file %qs", repo_name); 237 flag_use_repository = 0; 238 } 239 240 return repo_file; 241} 242 243/* Emit any pending repos. */ 244 245void 246finish_repo (void) 247{ 248 tree val; 249 char *dir, *args; 250 FILE *repo_file; 251 unsigned ix; 252 253 if (!flag_use_repository || flag_compare_debug) 254 return; 255 256 if (seen_error ()) 257 return; 258 259 repo_file = reopen_repo_file_for_write (); 260 if (repo_file == 0) 261 goto out; 262 263 fprintf (repo_file, "M %s\n", main_input_filename); 264 dir = getpwd (); 265 fprintf (repo_file, "D %s\n", dir); 266 args = getenv ("COLLECT_GCC_OPTIONS"); 267 if (args) 268 { 269 fprintf (repo_file, "A %s", args); 270 /* If -frandom-seed is not among the ARGS, then add the value 271 that we chose. That will ensure that the names of types from 272 anonymous namespaces will get the same mangling when this 273 file is recompiled. */ 274 if (!strstr (args, "'-frandom-seed=")) 275 fprintf (repo_file, " '-frandom-seed=" HOST_WIDE_INT_PRINT_HEX_PURE "'", 276 get_random_seed (false)); 277 fprintf (repo_file, "\n"); 278 } 279 280 FOR_EACH_VEC_SAFE_ELT_REVERSE (pending_repo, ix, val) 281 { 282 tree name = DECL_ASSEMBLER_NAME (val); 283 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O'; 284 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name)); 285 } 286 287 out: 288 if (repo_file) 289 fclose (repo_file); 290} 291 292/* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose 293 definition is available in this translation unit. Returns 0 if 294 this definition should not be emitted in this translation unit 295 because it will be emitted elsewhere. Returns 1 if the repository 296 file indicates that that DECL should be emitted in this translation 297 unit, or 2 if the repository file is not in use. */ 298 299int 300repo_emit_p (tree decl) 301{ 302 int ret = 0; 303 gcc_assert (TREE_PUBLIC (decl)); 304 gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); 305 gcc_assert (!DECL_REALLY_EXTERN (decl) 306 /* A clone might not have its linkage flags updated yet 307 because we call import_export_decl before 308 maybe_clone_body. */ 309 || DECL_ABSTRACT_ORIGIN (decl)); 310 311 /* When not using the repository, emit everything. */ 312 if (!flag_use_repository) 313 return 2; 314 315 /* Only template instantiations are managed by the repository. This 316 is an artificial restriction; the code in the prelinker and here 317 will work fine if all entities with vague linkage are managed by 318 the repository. */ 319 if (VAR_P (decl)) 320 { 321 tree type = NULL_TREE; 322 if (DECL_VTABLE_OR_VTT_P (decl)) 323 type = DECL_CONTEXT (decl); 324 else if (DECL_TINFO_P (decl)) 325 type = TREE_TYPE (DECL_NAME (decl)); 326 if (!DECL_TEMPLATE_INSTANTIATION (decl) 327 && (!TYPE_LANG_SPECIFIC (type) 328 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type))) 329 return 2; 330 /* Const static data members initialized by constant expressions must 331 be processed where needed so that their definitions are 332 available. Still record them into *.rpo files, so if they 333 weren't actually emitted and collect2 requests them, they can 334 be provided. */ 335 if (decl_maybe_constant_var_p (decl) 336 && DECL_CLASS_SCOPE_P (decl)) 337 ret = 2; 338 } 339 else if (!DECL_TEMPLATE_INSTANTIATION (decl)) 340 return 2; 341 342 if (DECL_EXPLICIT_INSTANTIATION (decl)) 343 return 2; 344 345 /* For constructors and destructors, the repository contains 346 information about the clones -- not the original function -- 347 because only the clones are emitted in the object file. */ 348 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl) 349 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)) 350 { 351 int emit_p = 0; 352 tree clone; 353 /* There is no early exit from this loop because we want to 354 ensure that all of the clones are marked as available in this 355 object file. */ 356 FOR_EACH_CLONE (clone, decl) 357 /* The only possible results from the recursive call to 358 repo_emit_p are 0 or 1. */ 359 if (repo_emit_p (clone)) 360 emit_p = 1; 361 return emit_p; 362 } 363 364 /* Keep track of all available entities. */ 365 if (!DECL_REPO_AVAILABLE_P (decl)) 366 { 367 DECL_REPO_AVAILABLE_P (decl) = 1; 368 vec_safe_push (pending_repo, decl); 369 } 370 371 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret; 372} 373 374/* Returns true iff the prelinker has explicitly marked CLASS_TYPE for 375 export from this translation unit. */ 376 377bool 378repo_export_class_p (const_tree class_type) 379{ 380 if (!flag_use_repository) 381 return false; 382 if (!CLASSTYPE_VTABLES (class_type)) 383 return false; 384 /* If the virtual table has been assigned to this translation unit, 385 export the class. */ 386 return (IDENTIFIER_REPO_CHOSEN 387 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type)))); 388} 389 390#include "gt-cp-repo.h" 391