1/* imports.cc -- Build imported modules/declarations. 2 Copyright (C) 2014-2020 Free Software Foundation, Inc. 3 4GCC is free software; you can redistribute it and/or modify 5it under the terms of the GNU General Public License as published by 6the Free Software Foundation; either version 3, or (at your option) 7any later version. 8 9GCC is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12GNU General Public License for more details. 13 14You should have received a copy of the GNU General Public License 15along with GCC; see the file COPYING3. If not see 16<http://www.gnu.org/licenses/>. */ 17 18#include "config.h" 19#include "system.h" 20#include "coretypes.h" 21 22#include "dmd/aggregate.h" 23#include "dmd/declaration.h" 24#include "dmd/enum.h" 25#include "dmd/identifier.h" 26#include "dmd/import.h" 27#include "dmd/module.h" 28 29#include "tree.h" 30#include "stringpool.h" 31 32#include "d-tree.h" 33 34 35/* Implements the visitor interface to build debug trees for all 36 module and import declarations, where ISYM holds the cached 37 back-end representation to be returned. */ 38class ImportVisitor : public Visitor 39{ 40 using Visitor::visit; 41 42 /* Build the declaration DECL as an imported symbol. */ 43 tree make_import (tree decl) 44 { 45 gcc_assert (decl != NULL_TREE); 46 47 tree import = build_decl (input_location, IMPORTED_DECL, 48 DECL_NAME (decl), void_type_node); 49 IMPORTED_DECL_ASSOCIATED_DECL (import) = decl; 50 d_keep (import); 51 52 return import; 53 } 54 55public: 56 ImportVisitor (void) 57 { 58 } 59 60 /* This should be overridden by each symbol class. */ 61 void visit (Dsymbol *) 62 { 63 gcc_unreachable (); 64 } 65 66 /* Build the module decl for M, this is considered toplevel, regardless 67 of whether there are any parent packages in the module system. */ 68 void visit (Module *m) 69 { 70 Loc loc = (m->md != NULL) ? m->md->loc 71 : Loc (m->srcfile->toChars (), 1, 0); 72 73 m->isym = build_decl (make_location_t (loc), NAMESPACE_DECL, 74 get_identifier (m->toPrettyChars ()), 75 void_type_node); 76 d_keep (m->isym); 77 78 if (!m->isRoot ()) 79 DECL_EXTERNAL (m->isym) = 1; 80 81 TREE_PUBLIC (m->isym) = 1; 82 DECL_CONTEXT (m->isym) = NULL_TREE; 83 } 84 85 /* Build an import of another module symbol. */ 86 87 void visit (Import *m) 88 { 89 tree module = build_import_decl (m->mod); 90 m->isym = this->make_import (module); 91 } 92 93 /* Build an import for any kind of user defined type. 94 Use the TYPE_DECL associated with the type symbol. */ 95 void visit (EnumDeclaration *d) 96 { 97 tree type = build_ctype (d->type); 98 /* Not all kinds of D enums create a TYPE_DECL. */ 99 if (TREE_CODE (type) == ENUMERAL_TYPE) 100 { 101 type = TYPE_MAIN_VARIANT (type); 102 d->isym = this->make_import (TYPE_STUB_DECL (type)); 103 } 104 105 } 106 107 void visit (AggregateDeclaration *d) 108 { 109 tree type = build_ctype (d->type); 110 type = TYPE_MAIN_VARIANT (type); 111 d->isym = this->make_import (TYPE_STUB_DECL (type)); 112 } 113 114 void visit (ClassDeclaration *d) 115 { 116 /* Want the RECORD_TYPE, not POINTER_TYPE. */ 117 tree type = TREE_TYPE (build_ctype (d->type)); 118 type = TYPE_MAIN_VARIANT (type); 119 d->isym = this->make_import (TYPE_STUB_DECL (type)); 120 } 121 122 /* For now, ignore importing other kinds of dsymbols. */ 123 void visit (ScopeDsymbol *) 124 { 125 } 126 127 /* Alias symbols aren't imported, but their targets are. */ 128 void visit (AliasDeclaration *d) 129 { 130 Dsymbol *dsym = d->toAlias (); 131 132 if (dsym == d) 133 { 134 Type *type = d->getType (); 135 136 /* Type imports should really be part of their own visit method. */ 137 if (type != NULL) 138 { 139 if (type->ty == Tenum) 140 dsym = ((TypeEnum *) type)->sym; 141 else if (type->ty == Tstruct) 142 dsym = ((TypeStruct *) type)->sym; 143 else if (type->ty == Tclass) 144 dsym = ((TypeClass *) type)->sym; 145 } 146 } 147 148 /* This symbol is really an alias for another, visit the other. */ 149 if (dsym != d) 150 { 151 dsym->accept (this); 152 d->isym = dsym->isym; 153 } 154 } 155 156 /* Visit the underlying alias symbol of overloadable aliases. */ 157 void visit (OverDeclaration *d) 158 { 159 if (d->aliassym != NULL) 160 { 161 d->aliassym->accept (this); 162 d->isym = d->aliassym->isym; 163 } 164 } 165 166 /* Build IMPORTED_DECLs for all overloads in a set. */ 167 void visit (OverloadSet *d) 168 { 169 vec<tree, va_gc> *tset = NULL; 170 171 vec_alloc (tset, d->a.dim); 172 173 for (size_t i = 0; i < d->a.dim; i++) 174 vec_safe_push (tset, build_import_decl (d->a[i])); 175 176 d->isym = build_tree_list_vec (tset); 177 tset->truncate (0); 178 } 179 180 /* Function aliases are the same as alias symbols. */ 181 void visit (FuncAliasDeclaration *d) 182 { 183 FuncDeclaration *fd = d->toAliasFunc (); 184 185 if (fd != NULL) 186 { 187 fd->accept (this); 188 d->isym = fd->isym; 189 } 190 } 191 192 /* Skip over importing templates and tuples. */ 193 void visit (TemplateDeclaration *) 194 { 195 } 196 197 void visit (TupleDeclaration *) 198 { 199 } 200 201 /* Import any other kind of declaration. If the class does not implement 202 symbol generation routines, the compiler will throw an error. */ 203 void visit (Declaration *d) 204 { 205 d->isym = this->make_import (get_symbol_decl (d)); 206 } 207}; 208 209 210/* Build a declaration for the symbol D that can be used for the 211 debug_hook imported_module_or_decl. */ 212tree 213build_import_decl (Dsymbol *d) 214{ 215 if (!d->isym) 216 { 217 location_t saved_location = input_location; 218 ImportVisitor v; 219 220 input_location = make_location_t (d->loc); 221 d->accept (&v); 222 input_location = saved_location; 223 } 224 225 /* Not all visitors set 'isym'. */ 226 return d->isym ? d->isym : NULL_TREE; 227} 228 229