#include #include #include #include #include #include #include #include "fold/detect/function_enumeration.hpp" namespace { std::unique_ptr parse(const std::string& code) { return clang::tooling::buildASTFromCodeWithArgs(code, {"-std=c++20"}, "input.cpp"); } // Collects qualified names of every function definition the helper visits. std::multiset visitedNames(const std::string& code) { auto unit = parse(code); REQUIRE(unit); std::multiset names; fold::detect::forEachFunctionWithBody(unit->getASTContext(), [&](clang::FunctionDecl* fd) { names.insert(fd->getQualifiedNameAsString()); }); return names; } } // namespace TEST_CASE("forEachFunctionWithBody: visits free, namespaced, and class-method defs", "[enumeration]") { const std::string code = R"cpp( void freeFn() {} namespace ns { void nsFree() {} struct B { void inlineMethod() {} // in-class inline, inside namespace void outOfLine(); }; void B::outOfLine() {} // out-of-line def, inside namespace } )cpp"; auto names = visitedNames(code); REQUIRE(names.count("freeFn") == 1); REQUIRE(names.count("ns::nsFree") == 1); REQUIRE(names.count("ns::B::inlineMethod") == 1); REQUIRE(names.count("ns::B::outOfLine") == 1); } TEST_CASE("forEachFunctionWithBody: visits instantiated function templates", "[enumeration]") { // A template is only a definition once instantiated; the call site forces // instantiation. The helper should see at least the primary pattern. const std::string code = R"cpp( namespace ns { template T addOne(T x) { return x + 1; } int use() { return addOne(41); } } )cpp"; auto names = visitedNames(code); REQUIRE(names.count("ns::addOne") >= 1); REQUIRE(names.count("ns::use") == 1); } TEST_CASE("forEachFunctionWithBody: does not double-count a decl+def pair", "[enumeration]") { const std::string code = R"cpp( int declared(); // forward declaration int declared() { return 0; } // definition )cpp"; auto names = visitedNames(code); REQUIRE(names.count("declared") == 1); } TEST_CASE("forEachFunctionWithBody: skips pure declarations with no body", "[enumeration]") { const std::string code = R"cpp( namespace ns { void onlyDeclared(); } )cpp"; auto names = visitedNames(code); REQUIRE(names.count("ns::onlyDeclared") == 0); }