1 /* 2 * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>. 3 * It is copyright by its individual contributors, as recorded in the 4 * project's Git history. See COPYING.txt at the top level for license 5 * terms and a link to the Git history. 6 */ 7 8 #pragma once 9 #include "dxxsconf.h" 10 11 /* This header serves several purposes: 12 * - Declare namespace dcx and add it to the list of searched 13 * namespaces. 14 * - If the compiler can disambiguate a namespace from a class inside a 15 * searched namespace[1], declare dummy classes scoped so that 16 * attempting to nest a namespace incorrectly causes a redefinition 17 * error. The build would usually fail even without this forced 18 * check, but the redefinition error forces a clear and immediate 19 * report. 20 * 21 * If building game-specific code: 22 * - #define dsx to a game-specific namespace: d1x or d2x, as 23 * appropriate. 24 * - Declare namespace dsx and add it to the list of searched 25 * namespaces. When the dsx migration is finished, this `using 26 * namespace` statement will be removed. 27 * Otherwise: 28 * - Declare dummy class dsx to force a redefinition error on attempts 29 * to declare `namespace dsx` in common-only code. 30 * 31 * [1] gcc handles this in all tested versions. There are no known 32 * clang versions which handle this. See the SConstruct test for 33 * DXX_HAVE_CXX_DISAMBIGUATE_USING_NAMESPACE for how this is detected. 34 */ 35 #if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II) 36 # if defined(DXX_BUILD_DESCENT_I) 37 # define dsx d1x 38 # else 39 # define dsx d2x 40 # endif 41 /* The "X declared inside Y" comments are on the same line as their 42 * declaration so that, if the compiler reports a redefinition error, 43 * the output shows the comment, which explains which type of mistake is 44 * being reported. 45 */ 46 namespace d1x { /* Force type mismatch on attempted nesting */ 47 # ifdef DXX_HAVE_CXX_DISAMBIGUATE_USING_NAMESPACE 48 class dcx; /* dcx declared inside d1x */ 49 class d1x; /* d1x declared inside d1x */ 50 class d2x; /* d2x declared inside d1x */ 51 # endif 52 } 53 namespace d2x { /* Force type mismatch on attempted nesting */ 54 # ifdef DXX_HAVE_CXX_DISAMBIGUATE_USING_NAMESPACE 55 class dcx; /* dcx declared inside d2x */ 56 class d1x; /* d1x declared inside d2x */ 57 class d2x; /* d2x declared inside d2x */ 58 # endif 59 } 60 #ifndef DXX_NO_USING_DSX 61 /* For compatibility during migration, add namespace dsx to the search 62 * list. This conflicts with the long term goal of the dsx project, but 63 * is currently required for a successful build. 64 * 65 * When working on the dsx project, define this preprocessor symbol on a 66 * file, then fix everything that breaks with that symbol defined. Move 67 * on to the next file. When all files build with this symbol set, the 68 * symbol and the using statement can be removed. 69 */ 70 using namespace dsx; // deprecated 71 #endif 72 #else 73 /* This dummy class does not need to be guarded by 74 * DXX_HAVE_CXX_DISAMBIGUATE_USING_NAMESPACE because it is declared only 75 * when no other uses of `dsx` are present, so there is no ambiguity for 76 * the compiler to resolve. 77 */ 78 class dsx; /* dsx declared in common-only code */ 79 class d1x; /* d1x declared in common-only code */ 80 class d2x; /* d2x declared in common-only code */ 81 #endif 82 83 #ifdef DXX_HAVE_CXX_DISAMBIGUATE_USING_NAMESPACE 84 namespace dcx { /* Force type mismatch on attempted nesting */ 85 class dcx; /* dcx declared inside dcx */ 86 class d1x; /* d1x declared inside dcx */ 87 class d2x; /* d2x declared inside dcx */ 88 } 89 90 namespace { 91 class dcx; /* dcx declared inside anonymous */ 92 class d1x; /* d1x declared inside anonymous */ 93 class d2x; /* d2x declared inside anonymous */ 94 } 95 #else 96 /* This empty namespace is required because, if 97 * !DXX_HAVE_CXX_DISAMBIGUATE_USING_NAMESPACE, then no other declaration 98 * of `namespace dcx` has been seen in this file. 99 */ 100 namespace dcx { 101 } 102 #endif 103 104 using namespace dcx; 105