17d62b00eSchristos /* Compile-time valid expression checker for GDB, the GNU debugger. 27d62b00eSchristos 3*6881a400Schristos Copyright (C) 2017-2023 Free Software Foundation, Inc. 47d62b00eSchristos 57d62b00eSchristos This file is part of GDB. 67d62b00eSchristos 77d62b00eSchristos This program is free software; you can redistribute it and/or modify 87d62b00eSchristos it under the terms of the GNU General Public License as published by 97d62b00eSchristos the Free Software Foundation; either version 3 of the License, or 107d62b00eSchristos (at your option) any later version. 117d62b00eSchristos 127d62b00eSchristos This program is distributed in the hope that it will be useful, 137d62b00eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 147d62b00eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 157d62b00eSchristos GNU General Public License for more details. 167d62b00eSchristos 177d62b00eSchristos You should have received a copy of the GNU General Public License 187d62b00eSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 197d62b00eSchristos 207d62b00eSchristos /* Helper macros used to build compile-time unit tests that make sure 217d62b00eSchristos that invalid expressions that should not compile would not compile, 227d62b00eSchristos and that expressions that should compile do compile, and have the 237d62b00eSchristos right type. This is mainly used to verify that some utility's API 247d62b00eSchristos is really as safe as intended. */ 257d62b00eSchristos 267d62b00eSchristos #ifndef COMMON_VALID_EXPR_H 277d62b00eSchristos #define COMMON_VALID_EXPR_H 287d62b00eSchristos 297d62b00eSchristos #include "gdbsupport/preprocessor.h" 307d62b00eSchristos #include "gdbsupport/traits.h" 317d62b00eSchristos 327d62b00eSchristos /* Macro that uses SFINAE magic to detect whether the EXPR expression 337d62b00eSchristos is either valid or ill-formed, at compile time, without actually 347d62b00eSchristos producing compile-time errors. I.e., check that bad uses of the 357d62b00eSchristos types (e.g., involving mismatching types) would be caught at 367d62b00eSchristos compile time. If the expression is valid, also check whether the 377d62b00eSchristos expression has the right type. 387d62b00eSchristos 397d62b00eSchristos EXPR must be defined in terms of some of the template parameters, 407d62b00eSchristos so that template substitution failure discards the overload instead 417d62b00eSchristos of causing a real compile error. TYPES is thus the list of types 427d62b00eSchristos involved in the expression, and TYPENAMES is the same list, but 437d62b00eSchristos with each element prefixed by "typename". These are passed as 447d62b00eSchristos template parameter types to the templates within the macro. 457d62b00eSchristos 467d62b00eSchristos VALID is a boolean that indicates whether the expression is 477d62b00eSchristos supposed to be valid or invalid. 487d62b00eSchristos 497d62b00eSchristos EXPR_TYPE is the expected type of EXPR. Only meaningful iff VALID 507d62b00eSchristos is true. If VALID is false, then you must pass "void" as expected 517d62b00eSchristos type. 527d62b00eSchristos 537d62b00eSchristos Each invocation of the macro is wrapped in its own namespace to 547d62b00eSchristos avoid ODR violations. The generated namespace only includes the 557d62b00eSchristos line number, so client code should wrap sets of calls in a 567d62b00eSchristos test-specific namespace too, to fully guarantee uniqueness between 577d62b00eSchristos the multiple clients in the codebase. */ 587d62b00eSchristos #define CHECK_VALID_EXPR_INT(TYPENAMES, TYPES, VALID, EXPR_TYPE, EXPR) \ 597d62b00eSchristos namespace CONCAT (check_valid_expr, __LINE__) { \ 607d62b00eSchristos \ 61*6881a400Schristos template <TYPENAMES, typename = decltype (EXPR)> \ 62*6881a400Schristos struct archetype \ 63*6881a400Schristos { \ 64*6881a400Schristos }; \ 657d62b00eSchristos \ 66*6881a400Schristos static_assert (gdb::is_detected_exact<archetype<TYPES, EXPR_TYPE>, \ 67*6881a400Schristos archetype, TYPES>::value == VALID, \ 687d62b00eSchristos ""); \ 697d62b00eSchristos } /* namespace */ 707d62b00eSchristos 717d62b00eSchristos /* A few convenience macros that support expressions involving a 727d62b00eSchristos varying numbers of types. If you need more types, feel free to add 737d62b00eSchristos another variant. */ 747d62b00eSchristos 757d62b00eSchristos #define CHECK_VALID_EXPR_1(T1, VALID, EXPR_TYPE, EXPR) \ 767d62b00eSchristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1), \ 777d62b00eSchristos ESC_PARENS (T1), \ 787d62b00eSchristos VALID, EXPR_TYPE, EXPR) 797d62b00eSchristos 807d62b00eSchristos #define CHECK_VALID_EXPR_2(T1, T2, VALID, EXPR_TYPE, EXPR) \ 817d62b00eSchristos CHECK_VALID_EXPR_INT (ESC_PARENS(typename T1, typename T2), \ 827d62b00eSchristos ESC_PARENS (T1, T2), \ 837d62b00eSchristos VALID, EXPR_TYPE, EXPR) 847d62b00eSchristos 857d62b00eSchristos #define CHECK_VALID_EXPR_3(T1, T2, T3, VALID, EXPR_TYPE, EXPR) \ 867d62b00eSchristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1, typename T2, typename T3), \ 877d62b00eSchristos ESC_PARENS (T1, T2, T3), \ 887d62b00eSchristos VALID, EXPR_TYPE, EXPR) 897d62b00eSchristos 907d62b00eSchristos #define CHECK_VALID_EXPR_4(T1, T2, T3, T4, VALID, EXPR_TYPE, EXPR) \ 917d62b00eSchristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1, typename T2, \ 927d62b00eSchristos typename T3, typename T4), \ 937d62b00eSchristos ESC_PARENS (T1, T2, T3, T4), \ 947d62b00eSchristos VALID, EXPR_TYPE, EXPR) 957d62b00eSchristos 96*6881a400Schristos #define CHECK_VALID_EXPR_5(T1, T2, T3, T4, T5, VALID, EXPR_TYPE, EXPR) \ 97*6881a400Schristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1, typename T2, \ 98*6881a400Schristos typename T3, typename T4, \ 99*6881a400Schristos typename T5), \ 100*6881a400Schristos ESC_PARENS (T1, T2, T3, T4, T5), \ 101*6881a400Schristos VALID, EXPR_TYPE, EXPR) 102*6881a400Schristos 103*6881a400Schristos #define CHECK_VALID_EXPR_6(T1, T2, T3, T4, T5, T6, \ 104*6881a400Schristos VALID, EXPR_TYPE, EXPR) \ 105*6881a400Schristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1, typename T2, \ 106*6881a400Schristos typename T3, typename T4, \ 107*6881a400Schristos typename T5, typename T6), \ 108*6881a400Schristos ESC_PARENS (T1, T2, T3, T4, T5, T6), \ 109*6881a400Schristos VALID, EXPR_TYPE, EXPR) 110*6881a400Schristos 1117d62b00eSchristos #endif /* COMMON_VALID_EXPR_H */ 112