Прежде всего, вам нужно сопоставлять не объявления функций, а выражения вызовов.Деконструируя эту проблему, мы получаем следующее: нам нужно сопоставить все выражения вызова, которые вызывают функции, возвращающие что-то и не используемые где-либо в качестве операнда.
Первое условие довольно простое.Тем не менее, второй вариант может иметь много разных вариантов, так как используемое возвращаемое значение может появляться в AST многими разными способами:
- операнд некоторого другого выражения
- возвращаемое значение
- инициализатор для объявления переменных
- условие в
if
/ while
/ do while
/ for
/ switch
операторов
Возможноесть некоторые другие случаи, о которых я не думал.
Собираем все вместе без последнего случая:
callExpr(callee(functionDecl(unless(returns(voidType())))),
unless(hasParent(anyOf(expr(), returnStmt()))),
unless(hasParent(varDecl())))
Для условий в различных утверждениях не существует общепринятого способапроверьте, чтобы был реализован новый механизм сопоставления.
#include <clang/ASTMatchers/ASTMatchers.h>
template <class... Other>
bool isCondition(const clang::Expr *Node, const clang::Stmt *Parent);
template <class ConditionalNode, class... Other>
inline bool isConditionImpl(const clang::Expr *Node,
const clang::Stmt *Parent) {
if (const auto *AsConditional = llvm::dyn_cast<ConditionalNode>(Parent)) {
return AsConditional->getCond() == Node;
}
return isCondition<Other...>(Node, Parent);
}
template <class... Other>
inline bool isCondition(const clang::Expr *Node, const clang::Stmt *Parent) {
return isConditionImpl<Other...>(Node, Parent);
}
template <>
inline bool isCondition(const clang::Expr *,
const clang::Stmt *) {
return false;
}
AST_MATCHER(clang::Expr, isInCondition) {
auto &Context = Finder->getASTContext();
auto *Parent = Context.getParents(Node)[0].get<clang::Stmt>();
if (Parent == nullptr) {
return false;
}
return isCondition<clang::DoStmt, clang::IfStmt, clang::ForStmt,
clang::SwitchStmt, clang::WhileStmt>(&Node, Parent);
}
Включая этот новый механизм сопоставления, мы можем использовать следующий механизм сопоставления:
callExpr(callee(functionDecl(unless(returns(voidType())))),
unless(hasParent(anyOf(expr(), returnStmt()))),
unless(hasParent(varDecl())),
unless(isInCondition()))
Скорее всего, это решение может быть грубымпо краям в некоторых случаях, включая неявное приведение, но это может дать вам представление.
Счастливого взлома с помощью clang!