【问题标题】:Getting C++ function mangled name获取 C++ 函数重命名的名称
【发布时间】:2018-03-12 07:44:07
【问题描述】:

我正在尝试跟踪 C++ 的代码覆盖率,并且我想指定特定测试涵盖的功能。我想要一个宏或模板,它给我函数的错位名称,所以在测试中我可以指定哪些方法被覆盖,我可以将它与生成的覆盖信息中的错位名称相匹配。我已经摆弄了一段时间,但一直无法让它发挥作用。更喜欢它也与重载方法一起使用

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

【问题讨论】:

  • 通常你不会弄乱名字,你demangle他们。
  • 听起来像是一个 XY 问题。为什么不能在代码中声明extern T0 my_func(T1, T2, T3, ...); 并调用my_func?您仍然需要编写代码来传递 T1、T2、T3 类型的变量,并接收 + 检查 T0 是否是正确的值,对吧?
  • 再读一遍这个问题,听起来更像是你需要c++filt,它将被破坏的名字翻译成被破坏的名字?
  • @nwp 我没有试图破坏它们我试图将信息附加到每个测试用例中,说明它的覆盖范围并使用它来过滤返回的覆盖率信息
  • 为什么不使用现有的代码覆盖工具?

标签: c++ clang code-coverage


【解决方案1】:

我不知道这是否会直接回答您的问题,但这些资源可能会有所帮助:

【讨论】:

    【解决方案2】:

    这就是我最终想出的似乎可行的方法(至少对于 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) ); \
    }
    

    这让我可以放

      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
    

    在使用换行符分隔的函数签名字符串调用 RecordProperty 的测试用例中,我可以将其与覆盖数据中损坏的名称进行比较(首先将它们解开)

    【讨论】:

      猜你喜欢
      • 2014-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-04
      • 2022-01-13
      • 2021-07-02
      • 1970-01-01
      相关资源
      最近更新 更多