1 /** 2 * Defines a `Dsymbol` for `version = identifier` and `debug = identifier` statements. 3 * 4 * Specification: $(LINK2 https://dlang.org/spec/version.html#version-specification, Version Specification), 5 * $(LINK2 https://dlang.org/spec/version.html#debug_specification, Debug Specification). 6 * 7 * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved 8 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 9 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 10 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dversion.d, _dversion.d) 11 * Documentation: https://dlang.org/phobos/dmd_dversion.html 12 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dversion.d 13 */ 14 15 module dmd.dversion; 16 17 import dmd.arraytypes; 18 import dmd.cond; 19 import dmd.dmodule; 20 import dmd.dscope; 21 import dmd.dsymbol; 22 import dmd.dsymbolsem; 23 import dmd.globals; 24 import dmd.identifier; 25 import dmd.root.outbuffer; 26 import dmd.visitor; 27 28 /*********************************************************** 29 * DebugSymbol's happen for statements like: 30 * debug = identifier; 31 * debug = integer; 32 */ 33 extern (C++) final class DebugSymbol : Dsymbol 34 { 35 uint level; 36 37 extern (D) this(const ref Loc loc, Identifier ident) 38 { 39 super(loc, ident); 40 } 41 42 extern (D) this(const ref Loc loc, uint level) 43 { 44 super(loc, null); 45 this.level = level; 46 } 47 48 override Dsymbol syntaxCopy(Dsymbol s) 49 { 50 assert(!s); 51 auto ds = new DebugSymbol(loc, ident); 52 ds.comment = comment; 53 ds.level = level; 54 return ds; 55 } 56 57 override const(char)* toChars() const nothrow 58 { 59 if (ident) 60 return ident.toChars(); 61 else 62 { 63 OutBuffer buf; 64 buf.print(level); 65 return buf.extractChars(); 66 } 67 } 68 69 override void addMember(Scope* sc, ScopeDsymbol sds) 70 { 71 //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), toChars()); 72 Module m = sds.isModule(); 73 // Do not add the member to the symbol table, 74 // just make sure subsequent debug declarations work. 75 if (ident) 76 { 77 if (!m) 78 { 79 error("declaration must be at module level"); 80 errors = true; 81 } 82 else 83 { 84 if (findCondition(m.debugidsNot, ident)) 85 { 86 error("defined after use"); 87 errors = true; 88 } 89 if (!m.debugids) 90 m.debugids = new Identifiers(); 91 m.debugids.push(ident); 92 } 93 } 94 else 95 { 96 if (!m) 97 { 98 error("level declaration must be at module level"); 99 errors = true; 100 } 101 else 102 m.debuglevel = level; 103 } 104 } 105 106 override const(char)* kind() const nothrow 107 { 108 return "debug"; 109 } 110 111 override void accept(Visitor v) 112 { 113 v.visit(this); 114 } 115 } 116 117 /*********************************************************** 118 * VersionSymbol's happen for statements like: 119 * version = identifier; 120 * version = integer; 121 */ 122 extern (C++) final class VersionSymbol : Dsymbol 123 { 124 uint level; 125 126 extern (D) this(const ref Loc loc, Identifier ident) 127 { 128 super(loc, ident); 129 } 130 131 extern (D) this(const ref Loc loc, uint level) 132 { 133 super(loc, null); 134 this.level = level; 135 } 136 137 override Dsymbol syntaxCopy(Dsymbol s) 138 { 139 assert(!s); 140 auto ds = ident ? new VersionSymbol(loc, ident) 141 : new VersionSymbol(loc, level); 142 ds.comment = comment; 143 return ds; 144 } 145 146 override const(char)* toChars() const nothrow 147 { 148 if (ident) 149 return ident.toChars(); 150 else 151 { 152 OutBuffer buf; 153 buf.print(level); 154 return buf.extractChars(); 155 } 156 } 157 158 override void addMember(Scope* sc, ScopeDsymbol sds) 159 { 160 //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), toChars()); 161 Module m = sds.isModule(); 162 // Do not add the member to the symbol table, 163 // just make sure subsequent debug declarations work. 164 if (ident) 165 { 166 VersionCondition.checkReserved(loc, ident.toString()); 167 if (!m) 168 { 169 error("declaration must be at module level"); 170 errors = true; 171 } 172 else 173 { 174 if (findCondition(m.versionidsNot, ident)) 175 { 176 error("defined after use"); 177 errors = true; 178 } 179 if (!m.versionids) 180 m.versionids = new Identifiers(); 181 m.versionids.push(ident); 182 } 183 } 184 else 185 { 186 if (!m) 187 { 188 error("level declaration must be at module level"); 189 errors = true; 190 } 191 else 192 m.versionlevel = level; 193 } 194 } 195 196 override const(char)* kind() const nothrow 197 { 198 return "version"; 199 } 200 201 override void accept(Visitor v) 202 { 203 v.visit(this); 204 } 205 }