Skip to content

Commit 8c789af

Browse files
committed
Error if body could not be matched
1 parent 9698708 commit 8c789af

3 files changed

Lines changed: 59 additions & 9 deletions

File tree

cpp2rust/converter/rule_src_parser.cpp

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <clang/ASTMatchers/ASTMatchFinder.h>
1212
#include <clang/ASTMatchers/ASTMatchers.h>
1313
#include <clang/Frontend/FrontendActions.h>
14+
#include <clang/Lex/Lexer.h>
1415
#include <clang/Sema/Initialization.h>
1516
#include <clang/Sema/Lookup.h>
1617
#include <clang/Sema/Overload.h>
@@ -19,6 +20,9 @@
1920
#include <clang/Tooling/CompilationDatabase.h>
2021
#include <clang/Tooling/Tooling.h>
2122

23+
#include <string>
24+
#include <unordered_map>
25+
2226
#include "compat/platform_flags.h"
2327
#include "converter/mapper.h"
2428

@@ -69,7 +73,9 @@ struct LookupInfo {
6973

7074
class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
7175
public:
72-
explicit Callback(llvm::json::Object &out) : out_(out) {}
76+
Callback(llvm::json::Object &out,
77+
std::unordered_map<std::string, std::string> &expected_funcs)
78+
: out_(out), expected_funcs_(expected_funcs) {}
7379

7480
void init(clang::Sema &sema) {
7581
sema_ = &sema;
@@ -80,6 +86,22 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
8086
void run(const clang::ast_matchers::MatchFinder::MatchResult &R) override {
8187
assert(sema_);
8288
Mapper::PushASTContext scoped(*R.Context);
89+
90+
if (auto efunc = R.Nodes.getNodeAs<clang::FunctionDecl>("expected_func")) {
91+
std::string body_src;
92+
if (auto *body = efunc->getBody()) {
93+
auto &sm = R.Context->getSourceManager();
94+
auto &lo = R.Context->getLangOpts();
95+
body_src =
96+
clang::Lexer::getSourceText(
97+
clang::CharSourceRange::getTokenRange(body->getSourceRange()),
98+
sm, lo)
99+
.str();
100+
}
101+
expected_funcs_[efunc->getQualifiedNameAsString()] = std::move(body_src);
102+
return;
103+
}
104+
83105
if (auto var = R.Nodes.getNodeAs<clang::TypeAliasDecl>("tvar")) {
84106
clang::QualType type;
85107
if (auto *tdecl = var->getDescribedAliasTemplate()) {
@@ -171,6 +193,7 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
171193

172194
private:
173195
llvm::json::Object &out_;
196+
std::unordered_map<std::string, std::string> &expected_funcs_;
174197
clang::Sema *sema_ = nullptr;
175198
clang::SourceLocation loc_;
176199

@@ -646,7 +669,9 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
646669

647670
class ActionFactory : public clang::tooling::FrontendActionFactory {
648671
public:
649-
explicit ActionFactory(llvm::json::Object &out) : cb_(out) {
672+
ActionFactory(llvm::json::Object &out,
673+
std::unordered_map<std::string, std::string> &expected_funcs)
674+
: cb_(out, expected_funcs) {
650675
using namespace clang::ast_matchers;
651676
finder_.addMatcher(
652677
returnStmt(
@@ -675,6 +700,13 @@ class ActionFactory : public clang::tooling::FrontendActionFactory {
675700
typeAliasDecl(matchesName("(^|::)t[0-9]+$"), isExpansionInMainFile())
676701
.bind("tvar"),
677702
&cb_);
703+
704+
// Collect every f<n> for the post-run diff against bound bodies.
705+
finder_.addMatcher(functionDecl(isDefinition(),
706+
matchesName("(^|::)f[0-9]+$"),
707+
isExpansionInMainFile())
708+
.bind("expected_func"),
709+
&cb_);
678710
}
679711

680712
std::unique_ptr<clang::FrontendAction> create() override {
@@ -721,14 +753,28 @@ class ActionFactory : public clang::tooling::FrontendActionFactory {
721753

722754
} // namespace
723755

724-
void Extract(const std::filesystem::path &src_path, llvm::json::Object &out) {
756+
bool Extract(const std::filesystem::path &src_path, llvm::json::Object &out) {
725757
auto flags = getPlatformClangBeginFlags();
726758
auto end_flags = getPlatformClangEndFlags();
727759
flags.insert(flags.end(), end_flags.begin(), end_flags.end());
728760
clang::tooling::FixedCompilationDatabase compilations(".", flags);
729-
ActionFactory factory(out);
761+
std::unordered_map<std::string, std::string> expected_funcs;
762+
ActionFactory factory(out, expected_funcs);
730763
clang::tooling::ClangTool tool(compilations, {src_path.string()});
731-
tool.run(&factory);
764+
bool ok = (tool.run(&factory) == 0);
765+
766+
for (const auto &[name, body_src] : expected_funcs) {
767+
if (out.find(name) == out.end()) {
768+
llvm::errs() << src_path.string() << ": " << name
769+
<< ": matcher did not bind to the function body.\n"
770+
<< " body: " << body_src << '\n'
771+
<< " Likely cause: return expression shape not handled by "
772+
"rule_src_parser.cpp's ActionFactory matcher (e.g. a "
773+
"literal from a macro expansion).\n";
774+
ok = false;
775+
}
776+
}
777+
return ok;
732778
}
733779

734780
} // namespace cpp2rust::RuleSrcParser

cpp2rust/converter/rule_src_parser.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
namespace cpp2rust::RuleSrcParser {
1111

12-
// Visit every f<n> / t<n> declaration in `src_path`:
13-
// f<n> / t<n>: { "to_string": <Mapper::ToString> }
14-
void Extract(const std::filesystem::path &src_path, llvm::json::Object &out);
12+
// Emits one entry per f<n>/t<n>: { "to_string": <Mapper::ToString> }.
13+
// Returns false if clang errored or any f<n> body shape went unmatched.
14+
bool Extract(const std::filesystem::path &src_path, llvm::json::Object &out);
1515

1616
} // namespace cpp2rust::RuleSrcParser

cpp2rust/cpp_rule_preprocessor.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ int main(int argc, char *argv[]) {
3232
fs::path src = SrcFile.getValue();
3333
llvm::errs() << "Preprocessing " << src.string() << '\n';
3434
llvm::json::Object root;
35-
cpp2rust::RuleSrcParser::Extract(src, root);
35+
if (!cpp2rust::RuleSrcParser::Extract(src, root)) {
36+
llvm::errs() << "ERROR: clang reported errors parsing " << src.string()
37+
<< "; ir_src.json was not written\n";
38+
return EXIT_FAILURE;
39+
}
3640

3741
auto out_path = src.parent_path() / "ir_src.json";
3842
std::error_code ec;

0 commit comments

Comments
 (0)