1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _nspace.d) 9 */ 10 11 module ddmd.nspace; 12 13 import ddmd.aggregate; 14 import ddmd.arraytypes; 15 import ddmd.dscope; 16 import ddmd.dsymbol; 17 import ddmd.globals; 18 import ddmd.identifier; 19 import ddmd.visitor; 20 import core.stdc.stdio; 21 22 private enum LOG = false; 23 24 /*********************************************************** 25 * A namespace corresponding to a C++ namespace. 26 * Implies extern(C++). 27 */ 28 extern (C++) final class Nspace : ScopeDsymbol 29 { 30 extern (D) this(Loc loc, Identifier ident, Dsymbols* members) 31 { 32 super(ident); 33 //printf("Nspace::Nspace(ident = %s)\n", ident->toChars()); 34 this.loc = loc; 35 this.members = members; 36 } 37 38 override Dsymbol syntaxCopy(Dsymbol s) 39 { 40 auto ns = new Nspace(loc, ident, null); 41 return ScopeDsymbol.syntaxCopy(ns); 42 } 43 44 override void addMember(Scope* sc, ScopeDsymbol sds) 45 { 46 ScopeDsymbol.addMember(sc, sds); 47 if (members) 48 { 49 if (!symtab) 50 symtab = new DsymbolTable(); 51 // The namespace becomes 'imported' into the enclosing scope 52 for (Scope* sce = sc; 1; sce = sce.enclosing) 53 { 54 ScopeDsymbol sds2 = sce.scopesym; 55 if (sds2) 56 { 57 sds2.importScope(this, Prot(PROTpublic)); 58 break; 59 } 60 } 61 assert(sc); 62 sc = sc.push(this); 63 sc.linkage = LINKcpp; // namespaces default to C++ linkage 64 sc.parent = this; 65 foreach (s; *members) 66 { 67 //printf("add %s to scope %s\n", s->toChars(), toChars()); 68 s.addMember(sc, this); 69 } 70 sc.pop(); 71 } 72 } 73 74 override void setScope(Scope* sc) 75 { 76 ScopeDsymbol.setScope(sc); 77 if (members) 78 { 79 assert(sc); 80 sc = sc.push(this); 81 sc.linkage = LINKcpp; // namespaces default to C++ linkage 82 sc.parent = this; 83 foreach (s; *members) 84 { 85 s.setScope(sc); 86 } 87 sc.pop(); 88 } 89 } 90 91 override void semantic(Scope* sc) 92 { 93 if (semanticRun >= PASSsemantic) 94 return; 95 semanticRun = PASSsemantic; 96 static if (LOG) 97 { 98 printf("+Nspace::semantic('%s')\n", toChars()); 99 } 100 if (_scope) 101 { 102 sc = _scope; 103 _scope = null; 104 } 105 parent = sc.parent; 106 if (members) 107 { 108 assert(sc); 109 sc = sc.push(this); 110 sc.linkage = LINKcpp; // note that namespaces imply C++ linkage 111 sc.parent = this; 112 foreach (s; *members) 113 { 114 s.importAll(sc); 115 } 116 foreach (s; *members) 117 { 118 static if (LOG) 119 { 120 printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind()); 121 } 122 s.semantic(sc); 123 } 124 sc.pop(); 125 } 126 static if (LOG) 127 { 128 printf("-Nspace::semantic('%s')\n", toChars()); 129 } 130 } 131 132 override void semantic2(Scope* sc) 133 { 134 if (semanticRun >= PASSsemantic2) 135 return; 136 semanticRun = PASSsemantic2; 137 static if (LOG) 138 { 139 printf("+Nspace::semantic2('%s')\n", toChars()); 140 } 141 if (members) 142 { 143 assert(sc); 144 sc = sc.push(this); 145 sc.linkage = LINKcpp; 146 foreach (s; *members) 147 { 148 static if (LOG) 149 { 150 printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind()); 151 } 152 s.semantic2(sc); 153 } 154 sc.pop(); 155 } 156 static if (LOG) 157 { 158 printf("-Nspace::semantic2('%s')\n", toChars()); 159 } 160 } 161 162 override void semantic3(Scope* sc) 163 { 164 if (semanticRun >= PASSsemantic3) 165 return; 166 semanticRun = PASSsemantic3; 167 static if (LOG) 168 { 169 printf("Nspace::semantic3('%s')\n", toChars()); 170 } 171 if (members) 172 { 173 sc = sc.push(this); 174 sc.linkage = LINKcpp; 175 foreach (s; *members) 176 { 177 s.semantic3(sc); 178 } 179 sc.pop(); 180 } 181 } 182 183 override bool oneMember(Dsymbol* ps, Identifier ident) 184 { 185 return Dsymbol.oneMember(ps, ident); 186 } 187 188 override final Dsymbol search(Loc loc, Identifier ident, int flags = SearchLocalsOnly) 189 { 190 //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars()); 191 if (_scope && !symtab) 192 semantic(_scope); 193 194 if (!members || !symtab) // opaque or semantic() is not yet called 195 { 196 error("is forward referenced when looking for '%s'", ident.toChars()); 197 return null; 198 } 199 200 return ScopeDsymbol.search(loc, ident, flags); 201 } 202 203 override int apply(Dsymbol_apply_ft_t fp, void* param) 204 { 205 if (members) 206 { 207 foreach (s; *members) 208 { 209 if (s) 210 { 211 if (s.apply(fp, param)) 212 return 1; 213 } 214 } 215 } 216 return 0; 217 } 218 219 override bool hasPointers() 220 { 221 //printf("Nspace::hasPointers() %s\n", toChars()); 222 if (members) 223 { 224 foreach (s; *members) 225 { 226 //printf(" s = %s %s\n", s->kind(), s->toChars()); 227 if (s.hasPointers()) 228 { 229 return true; 230 } 231 } 232 } 233 return false; 234 } 235 236 override void setFieldOffset(AggregateDeclaration ad, uint* poffset, bool isunion) 237 { 238 //printf("Nspace::setFieldOffset() %s\n", toChars()); 239 if (_scope) // if fwd reference 240 semantic(null); // try to resolve it 241 if (members) 242 { 243 foreach (s; *members) 244 { 245 //printf("\t%s\n", s->toChars()); 246 s.setFieldOffset(ad, poffset, isunion); 247 } 248 } 249 } 250 251 override const(char)* kind() const 252 { 253 return "namespace"; 254 } 255 256 override inout(Nspace) isNspace() inout 257 { 258 return this; 259 } 260 261 override void accept(Visitor v) 262 { 263 v.visit(this); 264 } 265 }