Files
carbon-lang/toolchain/base/for_each_macro.h
T
Dana JansensandRichard Smith b24944bfba Allow using CARBON_KIND_SWITCH on a std::variant (#5433)
We use CARBON_KIND_SWITCH for handling the output of TypeIterator in the
TypeStructureBuilder

Here is how the errors look when it is misused:
- If you don't cover ever type in the variant with a case
  ```
Enumeration value 'VariantTypeT1NotHandledInSwitch' not handled in
switch
  ```
Is attached to the CARBON_KIND_SWITCH() usage, the `T1` being a 0-based
index into the std::variant's type list, indicating which type was
missed.
- If you have a case for a type that is not in the variant
  ```
In template: constraints not satisfied for class template
'ValidCaseType' [with T = char]
  ... bunch of instantiation stuff ...
kind_switch.h(124, 12): Because 'char' does not satisfy
'TypeFoundInVariant'
  ```
Where `char` was the type I put in the `CARBON_KIND` macro, which was
not in the variant.
- If you have too many types in your variant (currently > 12)
  ```
In template: static assertion failed due to requirement 'sizeof...(Ts)
<= 12': CARBON_KIND_SWITCH supports std::variant with up to 12 types.
Add more if needed.
  ```
  Is attached to the CARBON_KIND_SWITCH() usage.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-05-12 16:26:55 +00:00

45 lines
2.1 KiB
C

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef CARBON_TOOLCHAIN_BASE_FOR_EACH_MACRO_H_
#define CARBON_TOOLCHAIN_BASE_FOR_EACH_MACRO_H_
/// CARBON_FOR_EACH() will apply `macro` to each argument in the variadic
/// argument list, putting the output of `sep()` between each one.
///
/// The `sep` should be a function macro that returns a separator. Premade
/// separataors are provided as CARBON_FOR_EACH_XYZ() macros.
#define CARBON_FOR_EACH(macro, sep, ...) \
__VA_OPT__(CARBON_INTERNAL_FOR_EACH_EXPAND( \
CARBON_INTERNAL_FOR_EACH(macro, sep, __VA_ARGS__)))
#define CARBON_FOR_EACH_COMMA() ,
#define CARBON_FOR_EACH_SEMI() ;
#define CARBON_FOR_EACH_CONCAT()
// Internal helpers
#define CARBON_INTERNAL_FOR_EACH(macro, sep, a1, ...) \
macro(a1) __VA_OPT__(sep()) __VA_OPT__( \
CARBON_INTERNAL_FOR_EACH_AGAIN CARBON_INTERNAL_FOR_EACH_PARENS( \
macro, sep, __VA_ARGS__))
#define CARBON_INTERNAL_FOR_EACH_PARENS ()
#define CARBON_INTERNAL_FOR_EACH_AGAIN() CARBON_INTERNAL_FOR_EACH
#define CARBON_INTERNAL_FOR_EACH_EXPAND(...) \
CARBON_INTERNAL_FOR_EACH_EXPAND1( \
CARBON_INTERNAL_FOR_EACH_EXPAND1(CARBON_INTERNAL_FOR_EACH_EXPAND1( \
CARBON_INTERNAL_FOR_EACH_EXPAND1(__VA_ARGS__))))
#define CARBON_INTERNAL_FOR_EACH_EXPAND1(...) \
CARBON_INTERNAL_FOR_EACH_EXPAND2( \
CARBON_INTERNAL_FOR_EACH_EXPAND2(CARBON_INTERNAL_FOR_EACH_EXPAND2( \
CARBON_INTERNAL_FOR_EACH_EXPAND2(__VA_ARGS__))))
#define CARBON_INTERNAL_FOR_EACH_EXPAND2(...) \
CARBON_INTERNAL_FOR_EACH_EXPAND3( \
CARBON_INTERNAL_FOR_EACH_EXPAND3(CARBON_INTERNAL_FOR_EACH_EXPAND3( \
CARBON_INTERNAL_FOR_EACH_EXPAND3(__VA_ARGS__))))
#define CARBON_INTERNAL_FOR_EACH_EXPAND3(...) __VA_ARGS__
#endif // CARBON_TOOLCHAIN_BASE_FOR_EACH_MACRO_H_