0

How can I ensure whether some specific code is not emitted?

Say, I tried to write something like a static switch (or static if) and I wish to detect whether second lambda operator ()'s body is emitted:

#include <type_traits>

namespace details
{

template< typename visitor, typename ...visitors >
struct composite_visitor
        : std::decay_t< visitor >
        , composite_visitor< visitors... >
{

    using std::decay_t< visitor >::operator ();
    using composite_visitor< visitors... >::operator ();

    composite_visitor(visitor & _visitor, visitors &... _visitors)
        : std::decay_t< visitor >(std::forward< visitor >(_visitor))
        , composite_visitor< visitors... >{_visitors...}
    { ; }

};

template< typename visitor >
struct composite_visitor< visitor >
        : std::decay_t< visitor >
{

    using std::decay_t< visitor >::operator ();

    composite_visitor(visitor & _visitor)
        : std::decay_t< visitor >(std::forward< visitor >(_visitor))
    { ; }

};

}

template< typename visitor, typename ...visitors >
details::composite_visitor< visitor, visitors... >
compose_visitors(visitor && _visitor, visitors &&... _visitors)
{
    return {_visitor, _visitors...};
}

#include <iostream>

#include <cstdlib>

template< int condition >
void
test()
{
    compose_visitors(
        [] (std::integral_constant< int, 0 >) { std::cout << 0 << std::endl; },
        [&] (std::integral_constant< int, 1 >) { std::cout << 1 << std::endl; },
        [] (std::integral_constant< int, 2 >) { std::cout << 2 << std::endl; }
    )(std::integral_constant< int, condition >{});
}

int
main()
{ 
    test< 0 >();
    //test< 1 >();
    test< 2 >();
    return EXIT_SUCCESS;
}

What is the tricks that allows me to detect a presence of specific code block into the resulting binary/.o/.a?

Previously one could do the following (for GCC):

  • add -Wa,-adhlns="$@.lst" to CXXFLAGS;
  • add asm volatile ("nop"); statement to code block you want to test;
  • build, then run awk "/\#APP/, /\#NO_APP/" build/*.lst (instead of hash symbol there may be a slash) command to see inline assembly into *.lst files in build directory;
  • if awk prints something, then particular code block is emitted.

LIVE DEMO

But I use clang and therefore can't use -Wa compiler parameter. What is a way for clang? I know I can emit assembly files (.S) using -S compiler option, but in big project it is hard to do in such a way if there is a dependency chain during building. How to emit assembly in addition to .o files?

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • 1
    Hm, why not just call defined, but not implemented function from `interesting for you code block` and you recieve link error if code emitted? – fghj Nov 06 '15 at 11:47
  • @user1034749 all possible ways is allowed. I want to know all of them ;). I think my version have at least one advantage: it allows one to detect all instantiations of specific function template or of specific member function (template) of template class. – Tomilov Anatoliy Nov 06 '15 at 12:03
  • You can use template defined not implemented function, with template parameters specific for you, for example class from which function called, and linker when report about error tell from which class this not implemented function was called. – fghj Nov 06 '15 at 12:07
  • I think you mean omitted? – o_weisman Nov 06 '15 at 13:02
  • Omit is to leave something out, emit is to discharge something most often a gas or a signal. Which one do you mean? – o_weisman Nov 06 '15 at 13:36
  • @o_wiesman I often hear "compiler emit some part of code". Try to google quoted substring (do use "+" before "emit" word). They are pretty good compatible words. – Tomilov Anatoliy Nov 06 '15 at 14:26
  • @o_weisman Also Borland C++ Builder has `__emit__()` function to insert code written in opcodes directly. Say, if you want to pass floating-point value directly to some (assembly-written) function, then you can use it as it [mentioned here](https://rsdn.ru/forum/cpp/3455799?tree=tree). – Tomilov Anatoliy Nov 06 '15 at 15:01

0 Answers0