Правильный ответ
На самом деле обход AST для построения паттернов последовательности (который является основой статического анализа) на самом деле не является правильным подходом, потому что вы НЕ знаете, произойдет ли на самом деле утверждение pattern1
до pattern2
Рассмотреть возможность
int foo() {
int a = 0;
int *b;
int c = -1;
if(c < 0) goto fixit;
nowhat:
b = &a;
fixit:
c = *b;
goto nowhat;
}
Как видите, AST здесь не поможет, но CFG — правильный выбор.
Некоторый ответ с использованием AST
Если вы посмотрите на Traversal Matchers в AST (v6.0.0), то увидите, что они в значительной степени иерархичны по своей природе. Вы хотите расширить соответствие, чтобы найти братьев и сестер.
Большая часть того, о чем я собираюсь рассказать, предполагает, что вы знаете, как реализовать пользовательский сопоставитель AST. Если нет, это довольно хорошо объясняет Ману Санчес в его Написание AST Matchers для записи в блоге libclang.
Не уверен, что он на самом деле напишет сопоставитель братьев и сестер, но он очень близок к этому, поэтому начните с этого, а затем вам придется реализовать что-то вроде этого:
Скажем, учитывая код:
class P {}; class Q {}; class R {};
Мы хотим иметь возможность делать что-то вроде:
(matcher = recordDecl(hasName("P"), \
hasNextSibling(recordDecl(hasName("R"))))`
Вы можете комбинировать matchesChild
и matchesParent
в классе AstMatchFinder
и проходить дочерние элементы родителя текущего курсора (это будут братья и сестры: P). Прочтите сноски, так как вам придется реализовать BoundCursors, чтобы избежать безудержной рекурсии.
person
Ahmed Masud
schedule
27.09.2017