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-2023 by The D Language Foundation, All Rights Reserved 8 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 9 * License: $(LINK2 https://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.location; 26 import dmd.common.outbuffer; 27 import dmd.visitor; 28 29 /*********************************************************** 30 * DebugSymbol's happen for statements like: 31 * debug = identifier; 32 * debug = integer; 33 */ 34 extern (C++) final class DebugSymbol : Dsymbol 35 { 36 uint level; 37 38 extern (D) this(const ref Loc loc, Identifier ident) 39 { 40 super(loc, ident); 41 } 42 43 extern (D) this(const ref Loc loc, uint level) 44 { 45 super(loc, null); 46 this.level = level; 47 } 48 49 override DebugSymbol syntaxCopy(Dsymbol s) 50 { 51 assert(!s); 52 auto ds = new DebugSymbol(loc, ident); 53 ds.comment = comment; 54 ds.level = level; 55 return ds; 56 } 57 58 override const(char)* toChars() const nothrow 59 { 60 if (ident) 61 return ident.toChars(); 62 else 63 { 64 OutBuffer buf; 65 buf.print(level); 66 return buf.extractChars(); 67 } 68 } 69 70 override void addMember(Scope* sc, ScopeDsymbol sds) 71 { 72 //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), toChars()); 73 Module m = sds.isModule(); 74 // Do not add the member to the symbol table, 75 // just make sure subsequent debug declarations work. 76 if (ident) 77 { 78 if (!m) 79 { 80 error("declaration must be at module level"); 81 errors = true; 82 } 83 else 84 { 85 if (findCondition(m.debugidsNot, ident)) 86 { 87 error("defined after use"); 88 errors = true; 89 } 90 if (!m.debugids) 91 m.debugids = new Identifiers(); 92 m.debugids.push(ident); 93 } 94 } 95 else 96 { 97 if (!m) 98 { 99 error("level declaration must be at module level"); 100 errors = true; 101 } 102 else 103 m.debuglevel = level; 104 } 105 } 106 107 override const(char)* kind() const nothrow 108 { 109 return "debug"; 110 } 111 112 override inout(DebugSymbol) isDebugSymbol() inout 113 { 114 return this; 115 } 116 117 override void accept(Visitor v) 118 { 119 v.visit(this); 120 } 121 } 122 123 /*********************************************************** 124 * VersionSymbol's happen for statements like: 125 * version = identifier; 126 * version = integer; 127 */ 128 extern (C++) final class VersionSymbol : Dsymbol 129 { 130 uint level; 131 132 extern (D) this(const ref Loc loc, Identifier ident) 133 { 134 super(loc, ident); 135 } 136 137 extern (D) this(const ref Loc loc, uint level) 138 { 139 super(loc, null); 140 this.level = level; 141 } 142 143 override VersionSymbol syntaxCopy(Dsymbol s) 144 { 145 assert(!s); 146 auto ds = ident ? new VersionSymbol(loc, ident) 147 : new VersionSymbol(loc, level); 148 ds.comment = comment; 149 return ds; 150 } 151 152 override const(char)* toChars() const nothrow 153 { 154 if (ident) 155 return ident.toChars(); 156 else 157 { 158 OutBuffer buf; 159 buf.print(level); 160 return buf.extractChars(); 161 } 162 } 163 164 override void addMember(Scope* sc, ScopeDsymbol sds) 165 { 166 //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), toChars()); 167 Module m = sds.isModule(); 168 // Do not add the member to the symbol table, 169 // just make sure subsequent debug declarations work. 170 if (ident) 171 { 172 VersionCondition.checkReserved(loc, ident.toString()); 173 if (!m) 174 { 175 error("declaration must be at module level"); 176 errors = true; 177 } 178 else 179 { 180 if (findCondition(m.versionidsNot, ident)) 181 { 182 error("defined after use"); 183 errors = true; 184 } 185 if (!m.versionids) 186 m.versionids = new Identifiers(); 187 m.versionids.push(ident); 188 } 189 } 190 else 191 { 192 if (!m) 193 { 194 error("level declaration must be at module level"); 195 errors = true; 196 } 197 else 198 m.versionlevel = level; 199 } 200 } 201 202 override const(char)* kind() const nothrow 203 { 204 return "version"; 205 } 206 207 override inout(VersionSymbol) isVersionSymbol() inout 208 { 209 return this; 210 } 211 212 override void accept(Visitor v) 213 { 214 v.visit(this); 215 } 216 }