简体   繁体   中英

Getting C++ function mangled name

I am trying to track code coverage for C++ and I would like to specify what functions a particular test covers. I would like to have a macro or template that gives me the mangled name of the function so in the test I can specify which methods are covered and I can match this up with the mangled names in the coverage information generated. I've been fiddling for some time but have been unable to get this to work. Prefer it worked with overloaded methods too

COVERS_BEGIN_FUNCTIONS
  COVERS_CLASS_FUNCTION( atestfile::aFunction( int ) );
COVERS_END_FUNCTIONS

I don't know if this will answer your question directly but these resources might be of assistance:

This is what I finally came up with that seems to work (at least for clang)

namespace testing {
    namespace coverage {
    inline std::string toString( const std::list<std::string> &list ) {
      std::ostringstream out;
      bool first = true;
      for ( const auto &item : list ) {
        if ( first ) {
          first = false;
        } else {
          out << std::endl;
        }
        out << item;
      }
      return out.str();
    }

    template<typename T> struct returnExtract { typedef void type; };
    template<typename R, typename...A> struct returnExtract<R( A... )> { typedef R type; };
    template<typename...> struct argsExtract { static std::string toString() { return std::string(); } };
    template<typename T, typename Y, typename... A> struct argsExtract<T, Y, A...> {
      static std::string toString() {
        return boost::core::demangled_name( typeid( T ) ) + ", " + argsExtract<Y, A...>::toString();
      }
    };
    template<typename T> struct argsExtract<T> { static std::string toString() { return boost::core::demangled_name( typeid( T ) ); } };
    template<typename T, typename... A> struct argsExtract<T( A... )> { static std::string toString() { return argsExtract<A...>::toString(); } };
    template<typename T> struct argsExtract<T()> { static std::string toString() { return std::string(); } };

    std::string functionComponentsToString( const std::type_info &returnType, const std::type_info &classType, const char *functionName,
                                            const std::string &argumentTypes, const std::string &templateArguments = std::string() ) {
      std::ostringstream rt;
      if ( not templateArguments.empty() ) {
        rt << boost::core::demangled_name( returnType ) << " ";
      }
      rt << boost::core::demangled_name( classType ) << "::" << functionName;
      if ( not templateArguments.empty() ) {
        rt << "<" << templateArguments << ">";
      }
      rt << "(" << argumentTypes << ")";
      return rt.str();
    }

    template<typename... X> struct functionCheck {};
    template<typename A, typename B, typename... C> struct functionCheck<A, B( C... )> { inline static void func( B (A::*)( C... ) ) {} };
  }
}

#define COVERS_BEGIN_FUNCTIONS { \
  std::list<std::string> functions;
#define COVERS_CLASS_FUNCTION( c, n, s ) \
  functions.emplace_back( testing::coverage::functionComponentsToString( typeid( testing::coverage::returnExtract<s>::type ), typeid( c ), #n, testing::coverage::argsExtract<s>::toString() ) ); \
  testing::coverage::functionCheck<c,s>::func( &c::n );
#define COVERS_CLASS_FUNCTION_T( c, n, s, t... ) \
  functions.emplace_back( testing::coverage::functionComponentsToString( typeid( testing::coverage::returnExtract<s>::type ), typeid( c ), #n, testing::coverage::argsExtract<s>::toString(), testing::coverage::argsExtract<t>::toString() ) ); \
  testing::coverage::functionCheck<c,s>::func( &c::n<t> );
#define COVERS_END_FUNCTIONS RecordProperty("COVERS_FUNCTIONS", testing::coverage::toString(functions) ); \
}

This allows me to put

  COVERS_BEGIN_FUNCTIONS
    COVERS_CLASS_FUNCTION( atestfile, aFunction, int( const char *) );
    COVERS_CLASS_FUNCTION_T( atestfile, aTestFunction, void( int ), int );
    COVERS_CLASS_FUNCTION_T( atestfile, aTestFunction, void( const char* ), const char* );
  COVERS_END_FUNCTIONS

In the test case which calls RecordProperty with a newline separated string of function signatures that I can compare to the mangled names in the coverage data (unmangling them first)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM