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