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-2022 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.common.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 this(const ref Loc loc,Identifier ident)37 extern (D) this(const ref Loc loc, Identifier ident) 38 { 39 super(loc, ident); 40 } 41 this(const ref Loc loc,uint level)42 extern (D) this(const ref Loc loc, uint level) 43 { 44 super(loc, null); 45 this.level = level; 46 } 47 syntaxCopy(Dsymbol s)48 override DebugSymbol 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 toChars()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 addMember(Scope * sc,ScopeDsymbol sds)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 kind()106 override const(char)* kind() const nothrow 107 { 108 return "debug"; 109 } 110 inout(DebugSymbol)111 override inout(DebugSymbol) isDebugSymbol() inout 112 { 113 return this; 114 } 115 accept(Visitor v)116 override void accept(Visitor v) 117 { 118 v.visit(this); 119 } 120 } 121 122 /*********************************************************** 123 * VersionSymbol's happen for statements like: 124 * version = identifier; 125 * version = integer; 126 */ 127 extern (C++) final class VersionSymbol : Dsymbol 128 { 129 uint level; 130 this(const ref Loc loc,Identifier ident)131 extern (D) this(const ref Loc loc, Identifier ident) 132 { 133 super(loc, ident); 134 } 135 this(const ref Loc loc,uint level)136 extern (D) this(const ref Loc loc, uint level) 137 { 138 super(loc, null); 139 this.level = level; 140 } 141 syntaxCopy(Dsymbol s)142 override VersionSymbol syntaxCopy(Dsymbol s) 143 { 144 assert(!s); 145 auto ds = ident ? new VersionSymbol(loc, ident) 146 : new VersionSymbol(loc, level); 147 ds.comment = comment; 148 return ds; 149 } 150 toChars()151 override const(char)* toChars() const nothrow 152 { 153 if (ident) 154 return ident.toChars(); 155 else 156 { 157 OutBuffer buf; 158 buf.print(level); 159 return buf.extractChars(); 160 } 161 } 162 addMember(Scope * sc,ScopeDsymbol sds)163 override void addMember(Scope* sc, ScopeDsymbol sds) 164 { 165 //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), toChars()); 166 Module m = sds.isModule(); 167 // Do not add the member to the symbol table, 168 // just make sure subsequent debug declarations work. 169 if (ident) 170 { 171 VersionCondition.checkReserved(loc, ident.toString()); 172 if (!m) 173 { 174 error("declaration must be at module level"); 175 errors = true; 176 } 177 else 178 { 179 if (findCondition(m.versionidsNot, ident)) 180 { 181 error("defined after use"); 182 errors = true; 183 } 184 if (!m.versionids) 185 m.versionids = new Identifiers(); 186 m.versionids.push(ident); 187 } 188 } 189 else 190 { 191 if (!m) 192 { 193 error("level declaration must be at module level"); 194 errors = true; 195 } 196 else 197 m.versionlevel = level; 198 } 199 } 200 kind()201 override const(char)* kind() const nothrow 202 { 203 return "version"; 204 } 205 inout(VersionSymbol)206 override inout(VersionSymbol) isVersionSymbol() inout 207 { 208 return this; 209 } 210 accept(Visitor v)211 override void accept(Visitor v) 212 { 213 v.visit(this); 214 } 215 } 216