c++templatesbuilt-in

How does __is_const(_Tp) in LLVM's header work?


While going through some of the type traits, I was searching how does std::is_const<type_name> work. According to the definition in it is

#if __has_builtin(__is_const)

template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS is_const : _BoolConstant<__is_const(_Tp)> { };

// ...

#else
// "normal" type trait
#endif

I know it's a compiler builtin, but was wondering on a high level as to how it's implemented?


Solution

  • It's implemented via an X macro that populates a map of type llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>.

    From clang/lib/Parse/ParseExpr.cpp:

    #define RTT_JOIN(X,Y) X##Y
    #define REVERTIBLE_TYPE_TRAIT(Name)                         \
              RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] \
                = RTT_JOIN(tok::kw_,Name)
    
    // ...
              REVERTIBLE_TYPE_TRAIT(__is_const);
    // ...
    
    #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait)                                     \
      REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait));
    #include "clang/Basic/TransformTypeTraits.def"
    #undef REVERTIBLE_TYPE_TRAIT
    #undef RTT_JOIN
    

    ... and then when parsing your code, the RevertibleTypeTraits map is consulted:

            // If we find that this is in fact the name of a type trait,
            // update the token kind in place and parse again to treat it as
            // the appropriate kind of type trait.
            llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known
              = RevertibleTypeTraits.find(II);
            if (Known != RevertibleTypeTraits.end()) {
              Tok.setKind(Known->second);
              return ParseCastExpression(ParseKind, isAddressOfOperand,
                                         NotCastExpr, isTypeCast,
                                         isVectorLiteral, NotPrimaryExpression);
            }
          }
          // ... and a lot more
    

    This is internal compiler details. It'll likely look very different when looking inside another compiler's code.