2015-01-12 6 views
4

НС ï ве подход перекрывая каждого специального Memb FUNC и plonking в printf или cout в теле каждого (например, C++: Implicit Member Functions здесь на SO, Vandevoorde and Josuttis называют это «трассеры»), не прельщает:Как легко узнать, какие специальные функции функции выбраны компилятором?

  • инвазивными, с точки зрения кодовой базы дельты
  • O (п), где п = | классы |, с точки зрения усилий
  • возможный эффект наблюдателя

Gi ving -E (или -save-temps) в g ++ заставляет последний испускать файл .ii для каждого источника .cpp (или .cxx) файла; в таком .ii, источник будет аннотирован точными шагами, сделанными препроцессором cpp. Я хочу, в идеале, что-то подобное, но с источником будучи вместо аннотированный в

Foo baz; 
//// Line 55, choosing Foo::Foo(); implicit; empty body 

Foo qux(Bar::mkFoo(42)); 
//// Line 56, choosing Foo::Foo(int) 
//// Line 56, choosing Foo::Foo(const Foo&) 
//// Line 56, choosing Foo::~Foo(); implicit 

Foo qux2(std::move(Bar::mkFoo(4.2))); 
//// Line 57, choosing Foo::Foo(double) 
//// Line 57, choosing Foo::Foo(Foo&&) 
//// Line 57, choosing Foo::~Foo(); implicit 

Идеальный подход покажет выбор, как сделал для конкретных вариантов оптимизации данных для компилятора.

Кто-нибудь знает способ достижения этого desideratum с g ++? Я готов начать писать плагин g ++, но решил спросить, прежде чем изобретать это колесо.

Если есть способ сделать это с помощью clang, это было бы хорошо знать.

Большое спасибо заранее.

+4

* Почему вы хотите иметь это? – Deduplicator

+0

Как часто вам это нужно? Возможно, было бы быстрее просто загрузить программу в отладчик и установить контрольные точки во всех этих членах, чем разрабатывать плагин g ++ ... Если вы хотите сделать это по соображениям производительности, профилировщик - ваш друг. Если это вам не поможет, функции в любом случае не важны. –

+0

@Deduplicator: Чтобы лучше понять код, за который я несу ответственность, и лучше понять C++. Конечно, я _think_, что 'Foo (const Foo &)' будет вызываться в одном случае, а 'Foo (Foo &&)' в другом; но _thinking_ - это не то же самое, что _knowing_. (Различие, которое неизбежно ускользает от людей с либеральным искусством, довольно забавно.) – querentns

ответ

2

Я бы предположил, что вы можете построить что-то подобное сверху clang. clang предоставляет несколько библиотек, обеспечивающих доступ к используемым внутренним структурам данных, включая AST. Однако АСТ должен содержать много информации, и может быть неясно, что представляет интерес.

Например, используя этот вход

struct foo { 
    foo(); 
    explicit foo(int); 
    foo(foo&&); 
    foo(foo const&); 
    ~foo(); 
}; 

struct bar { 
    static auto mkfoo(int x) -> foo; 
}; 

template <typename T> 
auto move(T&& t) -> T&&; 

int main() { 
    foo f0; 
    foo f1{bar::mkfoo(17)}; 
    foo f2{move(bar::mkfoo(17))}; 
} 

с помощью встроенной команды, чтобы сбросить AST, то есть, с помощью командной строки

clang -cc1 -std=c++11 -ast-dump ast.cpp 

дает следующий выход ниже. Если вы посмотрите внимательно, вы увидите большую часть операций, которые вы выполняете. Возможно, вам придется игнорировать детали, которые вам не интересны.

TranslationUnitDecl 0x7fea3b82ccc0 <<invalid sloc>> <invalid sloc> 
|-TypedefDecl 0x7fea3b82d200 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128' 
|-TypedefDecl 0x7fea3b82d260 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128' 
|-TypedefDecl 0x7fea3b82d620 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]' 
|-CXXRecordDecl 0x7fea3b82d670 <ast.cpp:1:1, line:7:1> line:1:8 referenced struct foo definition 
| |-CXXRecordDecl 0x7fea3b82d780 <col:1, col:8> col:8 implicit referenced struct foo 
| |-CXXConstructorDecl 0x7fea3b82d8b0 <line:2:5, col:9> col:5 used foo 'void (void)' 
| |-CXXConstructorDecl 0x7fea3b873260 <line:3:5, col:21> col:14 foo 'void (int)' 
| | `-ParmVarDecl 0x7fea3b82d980 <col:18> col:21 'int' 
| |-CXXConstructorDecl 0x7fea3b873420 <line:4:5, col:14> col:5 used foo 'void (struct foo &&)' 
| | `-ParmVarDecl 0x7fea3b873360 <col:9, col:12> col:14 'struct foo &&' 
| |-CXXConstructorDecl 0x7fea3b8735e0 <line:5:5, col:19> col:5 foo 'void (const struct foo &)' 
| | `-ParmVarDecl 0x7fea3b873520 <col:9, col:18> col:19 'const struct foo &' 
| `-CXXDestructorDecl 0x7fea3b8736f0 <line:6:5, col:10> col:5 used ~foo 'void (void) noexcept' 
|-CXXRecordDecl 0x7fea3b8737e0 <line:9:1, line:11:1> line:9:8 struct bar definition 
| |-CXXRecordDecl 0x7fea3b8738f0 <col:1, col:8> col:8 implicit struct bar 
| `-CXXMethodDecl 0x7fea3b873af0 <line:10:5, col:33> col:17 used mkfoo 'auto (int) -> struct foo' static 
| `-ParmVarDecl 0x7fea3b873990 <col:23, col:27> col:27 x 'int' 
|-FunctionTemplateDecl 0x7fea3b873e70 <line:13:1, line:14:22> col:6 move 
| |-TemplateTypeParmDecl 0x7fea3b873ba0 <line:13:11, col:20> col:20 referenced typename T 
| |-FunctionDecl 0x7fea3b873dd0 <line:14:1, col:22> col:6 move 'auto (T &&) -> T &&' 
| | `-ParmVarDecl 0x7fea3b873cc0 <col:11, col:15> col:15 t 'T &&' 
| `-FunctionDecl 0x7fea3b8757b0 <col:1, col:22> col:6 used move 'auto (struct foo &&) -> struct foo &&' 
| |-TemplateArgument type 'struct foo' 
| `-ParmVarDecl 0x7fea3b8756b0 <col:11, col:15> col:15 t 'struct foo &&' 
`-FunctionDecl 0x7fea3b873f10 <line:16:1, line:20:1> line:16:5 main 'int (void)' 
    `-CompoundStmt 0x7fea3b875a48 <col:12, line:20:1> 
    |-DeclStmt 0x7fea3b8740e0 <line:17:5, col:11> 
    | `-VarDecl 0x7fea3b874020 <col:5, col:9> col:9 f0 'struct foo' callinit 
    | `-CXXConstructExpr 0x7fea3b874078 <col:9> 'struct foo' 'void (void)' 
    |-DeclStmt 0x7fea3b875398 <line:18:5, col:27> 
    | `-VarDecl 0x7fea3b874110 <col:5, col:26> col:9 f1 'struct foo' listinit 
    | `-ExprWithCleanups 0x7fea3b875380 <col:9, col:26> 'struct foo' 
    |  `-CXXConstructExpr 0x7fea3b875348 <col:9, col:26> 'struct foo' 'void (struct foo &&)' elidable 
    |  `-MaterializeTemporaryExpr 0x7fea3b875330 <col:12, col:25> 'struct foo' xvalue 
    |   `-CXXBindTemporaryExpr 0x7fea3b8752c8 <col:12, col:25> 'struct foo' (CXXTemporary 0x7fea3b8752c0) 
    |   `-CallExpr 0x7fea3b875290 <col:12, col:25> 'struct foo' 
    |    |-ImplicitCastExpr 0x7fea3b875278 <col:12, col:17> 'auto (*)(int) -> struct foo' <FunctionToPointerDecay> 
    |    | `-DeclRefExpr 0x7fea3b8741b8 <col:12, col:17> 'auto (int) -> struct foo' lvalue CXXMethod 0x7fea3b873af0 'mkfoo' 'auto (int) -> struct foo' 
    |    `-IntegerLiteral 0x7fea3b875200 <col:23> 'int' 17 
    `-DeclStmt 0x7fea3b875a30 <line:19:5, col:33> 
     `-VarDecl 0x7fea3b8753c0 <col:5, col:32> col:9 f2 'struct foo' listinit 
     `-ExprWithCleanups 0x7fea3b875a18 <col:9, col:32> 'struct foo' 
      `-CXXConstructExpr 0x7fea3b8759e0 <col:9, col:32> 'struct foo' 'void (struct foo &&)' 
      `-CallExpr 0x7fea3b875950 <col:12, col:31> 'struct foo':'struct foo' xvalue 
       |-ImplicitCastExpr 0x7fea3b875938 <col:12> 'auto (*)(struct foo &&) -> struct foo &&' <FunctionToPointerDecay> 
       | `-DeclRefExpr 0x7fea3b8758b0 <col:12> 'auto (struct foo &&) -> struct foo &&' lvalue Function 0x7fea3b8757b0 'move' 'auto (struct foo &&) -> struct foo &&' (FunctionTemplate 0x7fea3b873e70 'move') 
       `-MaterializeTemporaryExpr 0x7fea3b875980 <col:17, col:30> 'struct foo':'struct foo' xvalue 
       `-CXXBindTemporaryExpr 0x7fea3b875558 <col:17, col:30> 'struct foo' (CXXTemporary 0x7fea3b875550) 
        `-CallExpr 0x7fea3b875518 <col:17, col:30> 'struct foo' 
        |-ImplicitCastExpr 0x7fea3b875500 <col:17, col:22> 'auto (*)(int) -> struct foo' <FunctionToPointerDecay> 
        | `-DeclRefExpr 0x7fea3b8754a8 <col:17, col:22> 'auto (int) -> struct foo' lvalue CXXMethod 0x7fea3b873af0 'mkfoo' 'auto (int) -> struct foo' 
        `-IntegerLiteral 0x7fea3b8754e0 <col:28> 'int' 17 
+0

Спасибо, Дитмар. Это действительно очень близко к тому, что я хотел; и даже не требует написания плагинов. – querentns

Смежные вопросы