1 /**
2  * Stores command line options and contains other miscellaneous declarations.
3  *
4  * Copyright:   Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
5  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
6  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/globals.d, _globals.d)
8  * Documentation:  https://dlang.org/phobos/dmd_globals.html
9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/globals.d
10  */
11 
12 module dmd.globals;
13 
14 import core.stdc.stdint;
15 import dmd.root.array;
16 import dmd.root.filename;
17 import dmd.root.outbuffer;
18 import dmd.identifier;
19 
20 /// Bit decoding of the TargetOS
21 enum TargetOS : ubyte
22 {
23     /* These are mutually exclusive; one and only one is set.
24      * Match spelling and casing of corresponding version identifiers
25      */
26     linux        = 1,
27     Windows      = 2,
28     OSX          = 4,
29     OpenBSD      = 8,
30     FreeBSD      = 0x10,
31     Solaris      = 0x20,
32     DragonFlyBSD = 0x40,
33 
34     // Combination masks
35     all = linux | Windows | OSX | FreeBSD | Solaris | DragonFlyBSD,
36     Posix = linux | OSX | FreeBSD | Solaris | DragonFlyBSD,
37 }
38 
39 template xversion(string s)
40 {
41     enum xversion = mixin(`{ version (` ~ s ~ `) return true; else return false; }`)();
42 }
43 
44 enum TARGET : bool
45 {
46     Linux        = xversion!`linux`,
47     OSX          = xversion!`OSX`,
48     FreeBSD      = xversion!`FreeBSD`,
49     OpenBSD      = xversion!`OpenBSD`,
50     Solaris      = xversion!`Solaris`,
51     Windows      = xversion!`Windows`,
52     DragonFlyBSD = xversion!`DragonFlyBSD`,
53 }
54 
55 enum DiagnosticReporting : ubyte
56 {
57     error,        // generate an error
58     inform,       // generate a warning
59     off,          // disable diagnostic
60 }
61 
62 enum MessageStyle : ubyte
63 {
64     digitalmars,  // filename.d(line): message
65     gnu,          // filename.d:line: message, see https://www.gnu.org/prep/standards/html_node/Errors.html
66 }
67 
68 enum CHECKENABLE : ubyte
69 {
70     _default,     // initial value
71     off,          // never do checking
72     on,           // always do checking
73     safeonly,     // do checking only in @safe functions
74 }
75 
76 enum CHECKACTION : ubyte
77 {
78     D,            // call D assert on failure
79     C,            // call C assert on failure
80     halt,         // cause program halt on failure
81     context,      // call D assert with the error context on failure
82 }
83 
84 enum CPU
85 {
86     x87,
87     mmx,
88     sse,
89     sse2,
90     sse3,
91     ssse3,
92     sse4_1,
93     sse4_2,
94     avx,                // AVX1 instruction set
95     avx2,               // AVX2 instruction set
96     avx512,             // AVX-512 instruction set
97 
98     // Special values that don't survive past the command line processing
99     baseline,           // (default) the minimum capability CPU
100     native              // the machine the compiler is being run on
101 }
102 
103 enum PIC : ubyte
104 {
105     fixed,              /// located at a specific address
106     pic,                /// Position Independent Code
107     pie,                /// Position Independent Executable
108 }
109 
110 /**
111 Each flag represents a field that can be included in the JSON output.
112 
113 NOTE: set type to uint so its size matches C++ unsigned type
114 */
115 enum JsonFieldFlags : uint
116 {
117     none         = 0,
118     compilerInfo = (1 << 0),
119     buildInfo    = (1 << 1),
120     modules      = (1 << 2),
121     semantics    = (1 << 3),
122 }
123 
124 enum CppStdRevision : uint
125 {
126     cpp98 = 1997_11,
127     cpp11 = 2011_03,
128     cpp14 = 2014_02,
129     cpp17 = 2017_03,
130     cpp20 = 2020_02,
131 }
132 
133 /// Configuration for the C++ header generator
134 enum CxxHeaderMode : uint
135 {
136     none,   /// Don't generate headers
137     silent, /// Generate headers
138     verbose /// Generate headers and add comments for hidden declarations
139 }
140 
141 /// Trivalent boolean to represent the state of a `revert`able change
142 enum FeatureState : byte
143 {
144     default_ = -1, /// Not specified by the user
145     disabled = 0,  /// Specified as `-revert=`
146     enabled = 1    /// Specified as `-preview=`
147 }
148 
149 // Put command line switches in here
150 extern (C++) struct Param
151 {
152     bool obj = true;        // write object file
153     bool link = true;       // perform link
154     bool dll;               // generate shared dynamic library
155     bool lib;               // write library file instead of object file(s)
156     bool multiobj;          // break one object file into multiple ones
157     bool oneobj;            // write one object file instead of multiple ones
158     bool trace;             // insert profiling hooks
159     bool tracegc;           // instrument calls to 'new'
160     bool verbose;           // verbose compile
161     bool vcg_ast;           // write-out codegen-ast
162     bool showColumns;       // print character (column) numbers in diagnostics
163     bool vtls;              // identify thread local variables
164     bool vtemplates;        // collect and list statistics on template instantiations
165     bool vtemplatesListInstances; // collect and list statistics on template instantiations origins. TODO: make this an enum when we want to list other kinds of instances
166     bool vgc;               // identify gc usage
167     bool vfield;            // identify non-mutable field variables
168     bool vcomplex;          // identify complex/imaginary type usage
169     ubyte symdebug;         // insert debug symbolic information
170     bool symdebugref;       // insert debug information for all referenced types, too
171     bool optimize;          // run optimizer
172     bool is64bit = (size_t.sizeof == 8);  // generate 64 bit code; true by default for 64 bit dmd
173     bool isLP64;            // generate code for LP64
174     TargetOS targetOS;      // operating system to generate code for
175     bool hasObjectiveC;     // target supports Objective-C
176     bool mscoff = false;    // for Win32: write MsCoff object files instead of OMF
177     DiagnosticReporting useDeprecated = DiagnosticReporting.inform;  // how use of deprecated features are handled
178     bool stackstomp;            // add stack stomping code
179     bool useUnitTests;          // generate unittest code
180     bool useInline = false;     // inline expand functions
181     FeatureState useDIP25;  // implement http://wiki.dlang.org/DIP25
182     bool useDIP1021;        // implement https://github.com/dlang/DIPs/blob/master/DIPs/DIP1021.md
183     bool release;           // build release version
184     bool preservePaths;     // true means don't strip path from source file
185     DiagnosticReporting warnings = DiagnosticReporting.off;  // how compiler warnings are handled
186     PIC pic = PIC.fixed;    // generate fixed, pic or pie code
187     bool color;             // use ANSI colors in console output
188     bool cov;               // generate code coverage data
189     ubyte covPercent;       // 0..100 code coverage percentage required
190     bool ctfe_cov = false;  // generate coverage data for ctfe
191     bool nofloat;           // code should not pull in floating point support
192     bool ignoreUnsupportedPragmas;  // rather than error on them
193     bool useModuleInfo = true;   // generate runtime module information
194     bool useTypeInfo = true;     // generate runtime type information
195     bool useExceptions = true;   // support exception handling
196     bool noSharedAccess;         // read/write access to shared memory objects
197     bool previewIn;         // `in` means `[ref] scope const`, accepts rvalues
198     bool shortenedMethods; // allow => in normal function declarations
199     bool betterC;           // be a "better C" compiler; no dependency on D runtime
200     bool addMain;           // add a default main() function
201     bool allInst;           // generate code for all template instantiations
202     bool fix16997;          // fix integral promotions for unary + - ~ operators
203                             // https://issues.dlang.org/show_bug.cgi?id=16997
204     bool fixAliasThis;      // if the current scope has an alias this, check it before searching upper scopes
205     bool inclusiveInContracts;   // 'in' contracts of overridden methods must be a superset of parent contract
206     /** The --transition=safe switch should only be used to show code with
207      * silent semantics changes related to @safe improvements.  It should not be
208      * used to hide a feature that will have to go through deprecate-then-error
209      * before becoming default.
210      */
211     bool vsafe;             // use enhanced @safe checking
212     bool ehnogc;            // use @nogc exception handling
213     FeatureState dtorFields; // destruct fields of partially constructed objects
214                             // https://issues.dlang.org/show_bug.cgi?id=14246
215     bool fieldwise;         // do struct equality testing field-wise rather than by memcmp()
216     bool rvalueRefParam;    // allow rvalues to be arguments to ref parameters
217                             // http://dconf.org/2019/talks/alexandrescu.html
218                             // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
219                             // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html
220                             // Implementation: https://github.com/dlang/dmd/pull/9817
221 
222     CppStdRevision cplusplus = CppStdRevision.cpp11;    // version of C++ standard to support
223 
224     bool markdown = true;   // enable Markdown replacements in Ddoc
225     bool vmarkdown;         // list instances of Markdown replacements in Ddoc
226 
227     bool showGaggedErrors;  // print gagged errors anyway
228     bool printErrorContext;  // print errors with the error context (the error line in the source file)
229     bool manual;            // open browser on compiler manual
230     bool usage;             // print usage and exit
231     bool mcpuUsage;         // print help on -mcpu switch
232     bool transitionUsage;   // print help on -transition switch
233     bool checkUsage;        // print help on -check switch
234     bool checkActionUsage;  // print help on -checkaction switch
235     bool revertUsage;       // print help on -revert switch
236     bool previewUsage;      // print help on -preview switch
237     bool externStdUsage;    // print help on -extern-std switch
238     bool hcUsage;           // print help on -HC switch
239     bool logo;              // print compiler logo
240 
241     CPU cpu = CPU.baseline; // CPU instruction set to target
242 
243     CHECKENABLE useInvariants  = CHECKENABLE._default;  // generate class invariant checks
244     CHECKENABLE useIn          = CHECKENABLE._default;  // generate precondition checks
245     CHECKENABLE useOut         = CHECKENABLE._default;  // generate postcondition checks
246     CHECKENABLE useArrayBounds = CHECKENABLE._default;  // when to generate code for array bounds checks
247     CHECKENABLE useAssert      = CHECKENABLE._default;  // when to generate code for assert()'s
248     CHECKENABLE useSwitchError = CHECKENABLE._default;  // check for switches without a default
249     CHECKENABLE boundscheck    = CHECKENABLE._default;  // state of -boundscheck switch
250 
251     CHECKACTION checkAction = CHECKACTION.D; // action to take when bounds, asserts or switch defaults are violated
252 
253     uint errorLimit = 20;
254 
255     const(char)[] argv0;                // program name
256     Array!(const(char)*) modFileAliasStrings; // array of char*'s of -I module filename alias strings
257     Array!(const(char)*)* imppath;      // array of char*'s of where to look for import modules
258     Array!(const(char)*)* fileImppath;  // array of char*'s of where to look for file import modules
259     const(char)[] objdir;                // .obj/.lib file output directory
260     const(char)[] objname;               // .obj file output name
261     const(char)[] libname;               // .lib file output name
262 
263     bool doDocComments;                 // process embedded documentation comments
264     const(char)[] docdir;               // write documentation file to docdir directory
265     const(char)[] docname;              // write documentation file to docname
266     Array!(const(char)*) ddocfiles;     // macro include files for Ddoc
267 
268     bool doHdrGeneration;               // process embedded documentation comments
269     const(char)[] hdrdir;                // write 'header' file to docdir directory
270     const(char)[] hdrname;               // write 'header' file to docname
271     bool hdrStripPlainFunctions = true; // strip the bodies of plain (non-template) functions
272 
273     CxxHeaderMode doCxxHdrGeneration;      /// Generate 'Cxx header' file
274     const(char)[] cxxhdrdir;            // write 'header' file to docdir directory
275     const(char)[] cxxhdrname;           // write 'header' file to docname
276 
277     bool doJsonGeneration;              // write JSON file
278     const(char)[] jsonfilename;          // write JSON file to jsonfilename
279     JsonFieldFlags jsonFieldFlags;      // JSON field flags to include
280 
281     OutBuffer* mixinOut;                // write expanded mixins for debugging
282     const(char)* mixinFile;             // .mixin file output name
283     int mixinLines;                     // Number of lines in writeMixins
284 
285     uint debuglevel;                    // debug level
286     Array!(const(char)*)* debugids;     // debug identifiers
287 
288     uint versionlevel;                  // version level
289     Array!(const(char)*)* versionids;   // version identifiers
290 
291     const(char)[] defaultlibname;        // default library for non-debug builds
292     const(char)[] debuglibname;          // default library for debug builds
293     const(char)[] mscrtlib;              // MS C runtime library
294 
295     const(char)[] moduleDepsFile;        // filename for deps output
296     OutBuffer* moduleDeps;              // contents to be written to deps file
297 
298     bool emitMakeDeps;                   // whether to emit makedeps
299     const(char)[] makeDepsFile;          // filename for makedeps output
300     Array!(const(char)*) makeDeps;      // dependencies for makedeps
301 
302     MessageStyle messageStyle = MessageStyle.digitalmars; // style of file/line annotations on messages
303 
304     bool run; // run resulting executable
305     Strings runargs; // arguments for executable
306 
307     // Linker stuff
308     Array!(const(char)*) objfiles;
309     Array!(const(char)*) linkswitches;
310     Array!bool linkswitchIsForCC;
311     Array!(const(char)*) libfiles;
312     Array!(const(char)*) dllfiles;
313     const(char)[] deffile;
314     const(char)[] resfile;
315     const(char)[] exefile;
316     const(char)[] mapfile;
317 }
318 
319 alias structalign_t = uint;
320 
321 // magic value means "match whatever the underlying C compiler does"
322 // other values are all powers of 2
323 enum STRUCTALIGN_DEFAULT = (cast(structalign_t)~0);
324 
325 extern (C++) struct Global
326 {
327     const(char)[] inifilename;
328     string mars_ext = "d";
329     const(char)[] obj_ext;
330     const(char)[] lib_ext;
331     const(char)[] dll_ext;
332     string doc_ext = "html";      // for Ddoc generated files
333     string ddoc_ext = "ddoc";     // for Ddoc macro include files
334     string hdr_ext = "di";        // for D 'header' import files
335     string cxxhdr_ext = "h";      // for C/C++ 'header' files
336     string json_ext = "json";     // for JSON files
337     string map_ext = "map";       // for .map files
338     bool run_noext;                     // allow -run sources without extensions.
339 
340     string copyright = "Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved";
341     string written = "written by Walter Bright";
342 
343     Array!(const(char)*)* path;         // Array of char*'s which form the import lookup path
344     Array!(const(char)*)* filePath;     // Array of char*'s which form the file import lookup path
345 
346     private enum string _version = import("VERSION");
347     private enum uint _versionNumber = parseVersionNumber(_version);
348 
349     const(char)[] vendor;    // Compiler backend name
350 
351     Param params;
352     uint errors;            // number of errors reported so far
353     uint warnings;          // number of warnings reported so far
354     uint gag;               // !=0 means gag reporting of errors & warnings
355     uint gaggedErrors;      // number of errors reported while gagged
356     uint gaggedWarnings;    // number of warnings reported while gagged
357 
358     void* console;         // opaque pointer to console for controlling text attributes
359 
360     Array!Identifier* versionids;    // command line versions and predefined versions
361     Array!Identifier* debugids;      // command line debug versions and predefined versions
362 
363     enum recursionLimit = 500; // number of recursive template expansions before abort
364 
365   nothrow:
366 
367     /* Start gagging. Return the current number of gagged errors
368      */
369     extern (C++) uint startGagging()
370     {
371         ++gag;
372         gaggedWarnings = 0;
373         return gaggedErrors;
374     }
375 
376     /* End gagging, restoring the old gagged state.
377      * Return true if errors occurred while gagged.
378      */
379     extern (C++) bool endGagging(uint oldGagged)
380     {
381         bool anyErrs = (gaggedErrors != oldGagged);
382         --gag;
383         // Restore the original state of gagged errors; set total errors
384         // to be original errors + new ungagged errors.
385         errors -= (gaggedErrors - oldGagged);
386         gaggedErrors = oldGagged;
387         return anyErrs;
388     }
389 
390     /*  Increment the error count to record that an error
391      *  has occurred in the current context. An error message
392      *  may or may not have been printed.
393      */
394     extern (C++) void increaseErrorCount()
395     {
396         if (gag)
397             ++gaggedErrors;
398         ++errors;
399     }
400 
401     extern (C++) void _init()
402     {
403         version (MARS)
404         {
405             vendor = "Digital Mars D";
406             static if (TARGET.Windows)
407             {
408                 obj_ext = "obj";
409             }
410             else static if (TARGET.Linux || TARGET.OSX || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.Solaris || TARGET.DragonFlyBSD)
411             {
412                 obj_ext = "o";
413             }
414             else
415             {
416                 static assert(0, "fix this");
417             }
418             static if (TARGET.Windows)
419             {
420                 lib_ext = "lib";
421             }
422             else static if (TARGET.Linux || TARGET.OSX || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.Solaris || TARGET.DragonFlyBSD)
423             {
424                 lib_ext = "a";
425             }
426             else
427             {
428                 static assert(0, "fix this");
429             }
430             static if (TARGET.Windows)
431             {
432                 dll_ext = "dll";
433             }
434             else static if (TARGET.Linux || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.Solaris || TARGET.DragonFlyBSD)
435             {
436                 dll_ext = "so";
437             }
438             else static if (TARGET.OSX)
439             {
440                 dll_ext = "dylib";
441             }
442             else
443             {
444                 static assert(0, "fix this");
445             }
446             static if (TARGET.Windows)
447             {
448                 run_noext = false;
449             }
450             else static if (TARGET.Linux || TARGET.OSX || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.Solaris || TARGET.DragonFlyBSD)
451             {
452                 // Allow 'script' D source files to have no extension.
453                 run_noext = true;
454             }
455             else
456             {
457                 static assert(0, "fix this");
458             }
459             static if (TARGET.Windows)
460             {
461                 params.mscoff = params.is64bit;
462             }
463 
464             // -color=auto is the default value
465             import dmd.console : Console;
466             params.color = Console.detectTerminal();
467         }
468         else version (IN_GCC)
469         {
470             vendor = "GNU D";
471             obj_ext = "o";
472             lib_ext = "a";
473             dll_ext = "so";
474             run_noext = true;
475         }
476     }
477 
478     /**
479      * Deinitializes the global state of the compiler.
480      *
481      * This can be used to restore the state set by `_init` to its original
482      * state.
483      */
484     extern (D) void deinitialize()
485     {
486         this = this.init;
487     }
488 
489     /**
490      * Computes the version number __VERSION__ from the compiler version string.
491      */
492     extern (D) private static uint parseVersionNumber(string version_)
493     {
494         //
495         // parse _version
496         //
497         uint major = 0;
498         uint minor = 0;
499         bool point = false;
500         // skip initial 'v'
501         foreach (const c; version_[1..$])
502         {
503             if ('0' <= c && c <= '9') // isdigit
504             {
505                 minor = minor * 10 + c - '0';
506             }
507             else if (c == '.')
508             {
509                 if (point)
510                     break; // ignore everything after second '.'
511                 point = true;
512                 major = minor;
513                 minor = 0;
514             }
515             else
516                 break;
517         }
518         return major * 1000 + minor;
519     }
520 
521     /**
522     Returns: the version as the number that would be returned for __VERSION__
523     */
524     extern(C++) uint versionNumber()
525     {
526         return _versionNumber;
527     }
528 
529     /**
530     Returns: compiler version string.
531     */
532     extern(D) string versionString()
533     {
534         return _version;
535     }
536 
537     /**
538     Returns: compiler version as char string.
539     */
540     extern(C++) const(char*) versionChars()
541     {
542         return _version.ptr;
543     }
544 
545     /**
546     Returns: the final defaultlibname based on the command-line parameters
547     */
548     extern (D) const(char)[] finalDefaultlibname() const
549     {
550         return params.betterC ? null :
551             params.symdebug ? params.debuglibname : params.defaultlibname;
552     }
553 }
554 
555 // Because int64_t and friends may be any integral type of the
556 // correct size, we have to explicitly ask for the correct
557 // integer type to get the correct mangling with dmd
558 
559 // Be careful not to care about sign when using dinteger_t
560 // use this instead of integer_t to
561 // avoid conflicts with system #include's
562 alias dinteger_t = ulong;
563 // Signed and unsigned variants
564 alias sinteger_t = long;
565 alias uinteger_t = ulong;
566 
567 alias d_int8 = int8_t;
568 alias d_uns8 = uint8_t;
569 alias d_int16 = int16_t;
570 alias d_uns16 = uint16_t;
571 alias d_int32 = int32_t;
572 alias d_uns32 = uint32_t;
573 alias d_int64 = int64_t;
574 alias d_uns64 = uint64_t;
575 
576 version (DMDLIB)
577 {
578     version = LocOffset;
579 }
580 
581 // file location
582 struct Loc
583 {
584     const(char)* filename; // either absolute or relative to cwd
585     uint linnum;
586     uint charnum;
587     version (LocOffset)
588         uint fileOffset;
589 
590     static immutable Loc initial;       /// use for default initialization of const ref Loc's
591 
592 nothrow:
593     extern (D) this(const(char)* filename, uint linnum, uint charnum) pure
594     {
595         this.linnum = linnum;
596         this.charnum = charnum;
597         this.filename = filename;
598     }
599 
600     extern (C++) const(char)* toChars(
601         bool showColumns = global.params.showColumns,
602         ubyte messageStyle = global.params.messageStyle) const pure nothrow
603     {
604         OutBuffer buf;
605         if (filename)
606         {
607             buf.writestring(filename);
608         }
609         if (linnum)
610         {
611             final switch (messageStyle)
612             {
613                 case MessageStyle.digitalmars:
614                     buf.writeByte('(');
615                     buf.print(linnum);
616                     if (showColumns && charnum)
617                     {
618                         buf.writeByte(',');
619                         buf.print(charnum);
620                     }
621                     buf.writeByte(')');
622                     break;
623                 case MessageStyle.gnu: // https://www.gnu.org/prep/standards/html_node/Errors.html
624                     buf.writeByte(':');
625                     buf.print(linnum);
626                     if (showColumns && charnum)
627                     {
628                         buf.writeByte(':');
629                         buf.print(charnum);
630                     }
631                     break;
632             }
633         }
634         return buf.extractChars();
635     }
636 
637     /* Checks for equivalence,
638      * a) comparing the filename contents (not the pointer), case-
639      *    insensitively on Windows, and
640      * b) ignoring charnum if `global.params.showColumns` is false.
641      */
642     extern (C++) bool equals(ref const(Loc) loc) const
643     {
644         return (!global.params.showColumns || charnum == loc.charnum) &&
645                linnum == loc.linnum &&
646                FileName.equals(filename, loc.filename);
647     }
648 
649     /* opEquals() / toHash() for AA key usage:
650      *
651      * Compare filename contents (case-sensitively on Windows too), not
652      * the pointer - a static foreach loop repeatedly mixing in a mixin
653      * may lead to multiple equivalent filenames (`foo.d-mixin-<line>`),
654      * e.g., for test/runnable/test18880.d.
655      */
656     extern (D) bool opEquals(ref const(Loc) loc) const @trusted pure nothrow @nogc
657     {
658         import core.stdc.string : strcmp;
659 
660         return charnum == loc.charnum &&
661                linnum == loc.linnum &&
662                (filename == loc.filename ||
663                 (filename && loc.filename && strcmp(filename, loc.filename) == 0));
664     }
665 
666     extern (D) size_t toHash() const @trusted pure nothrow
667     {
668         import dmd.root.string : toDString;
669 
670         auto hash = hashOf(linnum);
671         hash = hashOf(charnum, hash);
672         hash = hashOf(filename.toDString, hash);
673         return hash;
674     }
675 
676     /******************
677      * Returns:
678      *   true if Loc has been set to other than the default initialization
679      */
680     bool isValid() const pure
681     {
682         return filename !is null;
683     }
684 }
685 
686 enum LINK : ubyte
687 {
688     default_,
689     d,
690     c,
691     cpp,
692     windows,
693     objc,
694     system,
695 }
696 
697 enum CPPMANGLE : ubyte
698 {
699     def,
700     asStruct,
701     asClass,
702 }
703 
704 enum MATCH : int
705 {
706     nomatch,   // no match
707     convert,   // match with conversions
708     constant,  // match with conversion to const
709     exact,     // exact match
710 }
711 
712 enum PINLINE : ubyte
713 {
714     default_,     // as specified on the command line
715     never,   // never inline
716     always,  // always inline
717 }
718 
719 alias StorageClass = uinteger_t;
720 
721 extern (C++) __gshared Global global;