Closed ta0kira closed 4 years ago
In order to prevent a non-$TestsOnly$
category from being defined in a $TestsOnly$
C++ extension, we can probably use some macro trickery:
// In non-$TestsOnly$ Streamlined_Foo.hpp.
#ifdef ZEOLITE_TESTS_ONLY
#error Category Foo cannot be defined as $TestsOnly$
#endif
#ifndef ZEOLITE_NO_TESTS_ONLY
#define ZEOLITE_NO_TESTS_ONLY
#endif
// In $TestsOnly$ Category_Bar.hpp.
#if !defined(ZEOLITE_TESTS_ONLY) || defined(ZEOLITE_NO_TESTS_ONLY)
#error Category Bar can only be used in $TestsOnly$ sources
#endif
The key here is that both the streamlined header (#include
d to define the category) and category header (#include
d to use the category) are generated.
// Attempt to circumvent.
#include "Streamlined_Foo.hpp"
#define ZEOLITE_TESTS_ONLY
#include "Category_Bar.hpp" // <- #error here due to ZEOLITE_NO_TESTS_ONLY
// Attempt to circumvent.
#define ZEOLITE_TESTS_ONLY
#include "Category_Bar.hpp"
#include "Streamlined_Foo.hpp" // <- #error here due to ZEOLITE_TESTS_ONLY
// Attempt to circumvent.
#include "Streamlined_Foo.hpp"
#define ZEOLITE_TESTS_ONLY
#undef ZEOLITE_NO_TESTS_ONLY
#include "Category_Bar.hpp" // Fine, this would actually work.
These two macros should be avoidable in all hand-written code (once streamlined extensions are implemented); therefore, they could be given ugly names that would look bad in hand-written code, e.g., ZEOLITE_TESTS_ONLY_GUARD_FOR_USE_IN_CODEGEN
. Or, the macro names could include the compiler hash at the end of the name, e.g., ZEOLITE_TESTS_ONLY_7bc4535736d2796f
.
A more concise plan:
In any $TestsOnly$
streamlined header (e.g., Streamlined_Foo.hpp
):
#ifndef ZEOLITE_TESTS_ONLY_7bc4535736d2796f
#define ZEOLITE_TESTS_ONLY_7bc4535736d2796f
#endif
#ifdef ZEOLITE_NO_TESTS_ONLY_7bc4535736d2796f
#error Cannot define both $TestsOnly$ and non-$TestsOnly$ in the same source file
#endif
In any non-$TestsOnly$
streamlined header (e.g., Streamlined_Foo.hpp
):
#ifndef ZEOLITE_NO_TESTS_ONLY_7bc4535736d2796f
#define ZEOLITE_NO_TESTS_ONLY_7bc4535736d2796f
#endif
#ifdef ZEOLITE_TESTS_ONLY_7bc4535736d2796f
#error Cannot define both $TestsOnly$ and non-$TestsOnly$ in the same source file
#endif
In any $TestsOnly$
category header (e.g., Category_Bar.hpp
):
#ifndef ZEOLITE_TESTS_ONLY_7bc4535736d2796f
#error Category Bar can only be used by $TestsOnly$ categories
#endif
The key points are that:
#include
d by source files that will define the respective categories, so disallowing non-$TestsOnly$
in $TestsOnly$
sources is fine.#include
d where the category will be used, notwithstanding other generated files, so non-$TestsOnly$
can be used in $TestsOnly$
sources.
For example, guard the headers with a macro (e.g.,
ZEOLITE_TESTS_ONLY
) so that the category is only available if that macro is defined.It would also be helpful if there was a consequence of defining that macro so that it can't just be used arbitrarily.