Как получить полное выражение в правой части дерева абстрактного синтаксиса clang?

Давайте возьмем игрушечный пример, скажем, у меня есть следующий код в файле test.cpp:

int main()
{
int gt = 3;
int g = 10 / gt;
}

Я хочу найти имя переменной знаменателя в операции деления, затем с помощью clang я получаю абстрактное синтаксическое дерево (AST) приведенного выше кода с помощью команды clang -Xclang -ast-dump -fsyntax-only test.cpp , Я получаю следующий вывод

TranslationUnitDecl 0x34f8100 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x34f8638 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x34f8350 '__int128'
|-TypedefDecl 0x34f8698 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x34f8370 'unsigned __int128'
|-TypedefDecl 0x34f8728 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x34f86f0 'char *'
|   `-BuiltinType 0x34f8190 'char'
|-TypedefDecl 0x34f8a48 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x34f89f0 'struct __va_list_tag [1]' 1
|   `-RecordType 0x34f8810 'struct __va_list_tag'
|     `-CXXRecord 0x34f8778 '__va_list_tag'
`-FunctionDecl 0x34f8af0 <test.cpp:1:1, line:5:1> line:1:5 main 'int (void)'
`-CompoundStmt 0x34f8dc0 <line:2:1, line:5:1>
|-DeclStmt 0x34f8c98 <line:3:2, col:12>
| `-VarDecl 0x34f8c18 <col:2, col:11> col:6 used gt 'int' cinit
|   `-IntegerLiteral 0x34f8c78 <col:11> 'int' 3
`-DeclStmt 0x34f8da8 <line:4:2, col:17>
`-VarDecl 0x34f8cc0 <col:2, col:15> col:6 g 'int' cinit
`-BinaryOperator 0x34f8d80 <col:10, col:15> 'int' '/'
|-IntegerLiteral 0x34f8d20 <col:10> 'int' 10
`-ImplicitCastExpr 0x34f8d68 <col:15> 'int' <LValueToRValue>
`-DeclRefExpr 0x34f8d40 <col:15> 'int' lvalue Var 0x34f8c18 'gt' 'int'

Исходя из знания вышеупомянутого AST и используя clang-query, я получаю имя переменной знаменателя, используя следующую команду

clang-query> match declRefExpr(isExpansionInMainFile(), allOf(hasAncestor(binaryOperator(hasOperatorName("/"))), hasAncestor(declStmt())  ))

Я получаю свой вывод как

Match #1:

/home/clang-llvm/cpp/code/test.cpp:4:15: note: "root" binds here
int g = 10 / gt;
^~
1 match.

Теперь, когда мы находимся на одной странице, у меня есть два вопроса.

  1. Вот в приведенном выше примере игрушек, вместо 10, если у меня есть другой
    переменная, то мой запрос соответствует обеим переменным (числитель и
    знаменатель). Как я могу ограничить свой Clang-запрос, чтобы соответствовать только
    переменная, которая является знаменателем операции деления? В других
    слова, как найти переменную, которая присутствует в правой руке
    сторона бинарного оператора «/»? Примером является int g = gw / gt;

  2. Вместо переменной gt, если у меня есть выражение в знаменателе
    тогда как я могу получить все выражение, используя Clang? Другими словами,
    как получить выражение, которое находится на правой стороне двоичного файла
    оператор «/» в абстрактном синтаксическом дереве? Простой пример может быть
    int g = gw / (gt - gw); и сложный пример может быть int g = gw
    / gt - gw / gr * gg / sqrt( gt - gw ^ 2) + gq;

Я ценю любую помощь в этом отношении.

0

Решение

У Clang есть средство поиска «hasRHS ()», которое делает именно то, что вы хотите.

int main()
{
int gt = 3;
int g = 10 / gt;

int gw, gg, gr, gq;
int g1 = gw / gt;
int g2 = gw / (gt-gw);
int g3 = gw / gt - gw / gr * gg / ( gt - gw ^ 2) + gq;
return 0;
}

Выход:

clang-query> match varDecl(hasDescendant(binaryOperator(hasOperatorName("/"), hasRHS(expr().bind("myExpr")))))

Match #1:
/home/test.cpp:4:18: note: "myExpr" binds here
int g = 10 / gt;
^~
/home/test.cpp:4:5: note: "root" binds here
int g = 10 / gt;
^~~~~~~~~~~~~~~

Match #2:
/home/test.cpp:7:19: note: "myExpr" binds here
int g1 = gw / gt;
^~
/home/test.cpp:7:5: note: "root" binds here
int g1 = gw / gt;
^~~~~~~~~~~~~~~~

Match #3:
/home/test.cpp:8:19: note: "myExpr" binds here
int g2 = gw / (gt-gw);
^~~~~~~
/home/test.cpp:8:5: note: "root" binds here
int g2 = gw / (gt-gw);
^~~~~~~~~~~~~~~~~~~~~

Match #4:
/home/test.cpp:9:19: note: "myExpr" binds here
int g3 = gw / gt - gw / gr * gg / ( gt - gw ^ 2) + gq;
^~
/home/test.cpp:9:5: note: "root" binds here
int g3 = gw / gt - gw / gr * gg / ( gt - gw ^ 2) + gq;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 matches.

«myExpr» привязан к тому, что вы хотите.
Ref: http://clang.llvm.org/docs/LibASTMatchersReference.html

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]