xref: /netbsd-src/external/gpl3/gdb.old/dist/gdbsupport/valid-expr.h (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
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