18dffb485Schristos /* Compile-time valid expression checker for GDB, the GNU debugger. 28dffb485Schristos 3*5ba1f45fSchristos Copyright (C) 2017-2024 Free Software Foundation, Inc. 48dffb485Schristos 58dffb485Schristos This file is part of GDB. 68dffb485Schristos 78dffb485Schristos This program is free software; you can redistribute it and/or modify 88dffb485Schristos it under the terms of the GNU General Public License as published by 98dffb485Schristos the Free Software Foundation; either version 3 of the License, or 108dffb485Schristos (at your option) any later version. 118dffb485Schristos 128dffb485Schristos This program is distributed in the hope that it will be useful, 138dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 148dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 158dffb485Schristos GNU General Public License for more details. 168dffb485Schristos 178dffb485Schristos You should have received a copy of the GNU General Public License 188dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 198dffb485Schristos 208dffb485Schristos /* Helper macros used to build compile-time unit tests that make sure 218dffb485Schristos that invalid expressions that should not compile would not compile, 228dffb485Schristos and that expressions that should compile do compile, and have the 238dffb485Schristos right type. This is mainly used to verify that some utility's API 248dffb485Schristos is really as safe as intended. */ 258dffb485Schristos 268dffb485Schristos #ifndef COMMON_VALID_EXPR_H 278dffb485Schristos #define COMMON_VALID_EXPR_H 288dffb485Schristos 298dffb485Schristos #include "gdbsupport/preprocessor.h" 308dffb485Schristos #include "gdbsupport/traits.h" 318dffb485Schristos 328dffb485Schristos /* Macro that uses SFINAE magic to detect whether the EXPR expression 338dffb485Schristos is either valid or ill-formed, at compile time, without actually 348dffb485Schristos producing compile-time errors. I.e., check that bad uses of the 358dffb485Schristos types (e.g., involving mismatching types) would be caught at 368dffb485Schristos compile time. If the expression is valid, also check whether the 378dffb485Schristos expression has the right type. 388dffb485Schristos 398dffb485Schristos EXPR must be defined in terms of some of the template parameters, 408dffb485Schristos so that template substitution failure discards the overload instead 418dffb485Schristos of causing a real compile error. TYPES is thus the list of types 428dffb485Schristos involved in the expression, and TYPENAMES is the same list, but 438dffb485Schristos with each element prefixed by "typename". These are passed as 448dffb485Schristos template parameter types to the templates within the macro. 458dffb485Schristos 468dffb485Schristos VALID is a boolean that indicates whether the expression is 478dffb485Schristos supposed to be valid or invalid. 488dffb485Schristos 498dffb485Schristos EXPR_TYPE is the expected type of EXPR. Only meaningful iff VALID 508dffb485Schristos is true. If VALID is false, then you must pass "void" as expected 518dffb485Schristos type. 528dffb485Schristos 538dffb485Schristos Each invocation of the macro is wrapped in its own namespace to 548dffb485Schristos avoid ODR violations. The generated namespace only includes the 558dffb485Schristos line number, so client code should wrap sets of calls in a 568dffb485Schristos test-specific namespace too, to fully guarantee uniqueness between 578dffb485Schristos the multiple clients in the codebase. */ 588dffb485Schristos #define CHECK_VALID_EXPR_INT(TYPENAMES, TYPES, VALID, EXPR_TYPE, EXPR) \ 598dffb485Schristos namespace CONCAT (check_valid_expr, __LINE__) { \ 608dffb485Schristos \ 614b169a6bSchristos template <TYPENAMES, typename = decltype (EXPR)> \ 624b169a6bSchristos struct archetype \ 634b169a6bSchristos { \ 644b169a6bSchristos }; \ 658dffb485Schristos \ 664b169a6bSchristos static_assert (gdb::is_detected_exact<archetype<TYPES, EXPR_TYPE>, \ 674b169a6bSchristos archetype, TYPES>::value == VALID, \ 688dffb485Schristos ""); \ 698dffb485Schristos } /* namespace */ 708dffb485Schristos 718dffb485Schristos /* A few convenience macros that support expressions involving a 728dffb485Schristos varying numbers of types. If you need more types, feel free to add 738dffb485Schristos another variant. */ 748dffb485Schristos 758dffb485Schristos #define CHECK_VALID_EXPR_1(T1, VALID, EXPR_TYPE, EXPR) \ 768dffb485Schristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1), \ 778dffb485Schristos ESC_PARENS (T1), \ 788dffb485Schristos VALID, EXPR_TYPE, EXPR) 798dffb485Schristos 808dffb485Schristos #define CHECK_VALID_EXPR_2(T1, T2, VALID, EXPR_TYPE, EXPR) \ 818dffb485Schristos CHECK_VALID_EXPR_INT (ESC_PARENS(typename T1, typename T2), \ 828dffb485Schristos ESC_PARENS (T1, T2), \ 838dffb485Schristos VALID, EXPR_TYPE, EXPR) 848dffb485Schristos 858dffb485Schristos #define CHECK_VALID_EXPR_3(T1, T2, T3, VALID, EXPR_TYPE, EXPR) \ 868dffb485Schristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1, typename T2, typename T3), \ 878dffb485Schristos ESC_PARENS (T1, T2, T3), \ 888dffb485Schristos VALID, EXPR_TYPE, EXPR) 898dffb485Schristos 908dffb485Schristos #define CHECK_VALID_EXPR_4(T1, T2, T3, T4, VALID, EXPR_TYPE, EXPR) \ 918dffb485Schristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1, typename T2, \ 928dffb485Schristos typename T3, typename T4), \ 938dffb485Schristos ESC_PARENS (T1, T2, T3, T4), \ 948dffb485Schristos VALID, EXPR_TYPE, EXPR) 958dffb485Schristos 964b169a6bSchristos #define CHECK_VALID_EXPR_5(T1, T2, T3, T4, T5, VALID, EXPR_TYPE, EXPR) \ 974b169a6bSchristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1, typename T2, \ 984b169a6bSchristos typename T3, typename T4, \ 994b169a6bSchristos typename T5), \ 1004b169a6bSchristos ESC_PARENS (T1, T2, T3, T4, T5), \ 1014b169a6bSchristos VALID, EXPR_TYPE, EXPR) 1024b169a6bSchristos 1034b169a6bSchristos #define CHECK_VALID_EXPR_6(T1, T2, T3, T4, T5, T6, \ 1044b169a6bSchristos VALID, EXPR_TYPE, EXPR) \ 1054b169a6bSchristos CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1, typename T2, \ 1064b169a6bSchristos typename T3, typename T4, \ 1074b169a6bSchristos typename T5, typename T6), \ 1084b169a6bSchristos ESC_PARENS (T1, T2, T3, T4, T5, T6), \ 1094b169a6bSchristos VALID, EXPR_TYPE, EXPR) 1104b169a6bSchristos 1118dffb485Schristos #endif /* COMMON_VALID_EXPR_H */ 112