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

120 views Asked by At

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?

1

There are 1 answers

7
Ted Lyngmo On BEST ANSWER

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.