mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-16 21:21:06 +00:00
[clang] Refactor AST printing tests to share more infrastructure
Differential Revision: https://reviews.llvm.org/D105457
This commit is contained in:
parent
c41e67f3f1
commit
20176bc7dd
@ -19,72 +19,88 @@
|
||||
|
||||
namespace clang {
|
||||
|
||||
using PolicyAdjusterType =
|
||||
Optional<llvm::function_ref<void(PrintingPolicy &Policy)>>;
|
||||
using PrintingPolicyAdjuster = llvm::function_ref<void(PrintingPolicy &Policy)>;
|
||||
|
||||
static void PrintStmt(raw_ostream &Out, const ASTContext *Context,
|
||||
const Stmt *S, PolicyAdjusterType PolicyAdjuster) {
|
||||
assert(S != nullptr && "Expected non-null Stmt");
|
||||
PrintingPolicy Policy = Context->getPrintingPolicy();
|
||||
if (PolicyAdjuster)
|
||||
(*PolicyAdjuster)(Policy);
|
||||
S->printPretty(Out, /*Helper*/ nullptr, Policy);
|
||||
}
|
||||
template <typename NodeType>
|
||||
using NodePrinter =
|
||||
std::function<void(llvm::raw_ostream &Out, const ASTContext *Context,
|
||||
const NodeType *Node,
|
||||
PrintingPolicyAdjuster PolicyAdjuster)>;
|
||||
|
||||
template <typename NodeType>
|
||||
using NodeFilter = std::function<bool(const NodeType *Node)>;
|
||||
|
||||
template <typename NodeType>
|
||||
class PrintMatch : public ast_matchers::MatchFinder::MatchCallback {
|
||||
using PrinterT = NodePrinter<NodeType>;
|
||||
using FilterT = NodeFilter<NodeType>;
|
||||
|
||||
SmallString<1024> Printed;
|
||||
unsigned NumFoundStmts;
|
||||
PolicyAdjusterType PolicyAdjuster;
|
||||
unsigned NumFoundNodes;
|
||||
PrinterT Printer;
|
||||
FilterT Filter;
|
||||
PrintingPolicyAdjuster PolicyAdjuster;
|
||||
|
||||
public:
|
||||
PrintMatch(PolicyAdjusterType PolicyAdjuster)
|
||||
: NumFoundStmts(0), PolicyAdjuster(PolicyAdjuster) {}
|
||||
PrintMatch(PrinterT Printer, PrintingPolicyAdjuster PolicyAdjuster,
|
||||
FilterT Filter)
|
||||
: NumFoundNodes(0), Printer(std::move(Printer)),
|
||||
Filter(std::move(Filter)), PolicyAdjuster(PolicyAdjuster) {}
|
||||
|
||||
void run(const ast_matchers::MatchFinder::MatchResult &Result) override {
|
||||
const Stmt *S = Result.Nodes.getNodeAs<Stmt>("id");
|
||||
if (!S)
|
||||
const NodeType *N = Result.Nodes.getNodeAs<NodeType>("id");
|
||||
if (!N || !Filter(N))
|
||||
return;
|
||||
NumFoundStmts++;
|
||||
if (NumFoundStmts > 1)
|
||||
NumFoundNodes++;
|
||||
if (NumFoundNodes > 1)
|
||||
return;
|
||||
|
||||
llvm::raw_svector_ostream Out(Printed);
|
||||
PrintStmt(Out, Result.Context, S, PolicyAdjuster);
|
||||
Printer(Out, Result.Context, N, PolicyAdjuster);
|
||||
}
|
||||
|
||||
StringRef getPrinted() const { return Printed; }
|
||||
|
||||
unsigned getNumFoundStmts() const { return NumFoundStmts; }
|
||||
unsigned getNumFoundNodes() const { return NumFoundNodes; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
::testing::AssertionResult
|
||||
PrintedStmtMatches(StringRef Code, const std::vector<std::string> &Args,
|
||||
const T &NodeMatch, StringRef ExpectedPrinted,
|
||||
PolicyAdjusterType PolicyAdjuster = None) {
|
||||
template <typename NodeType, typename Matcher>
|
||||
::testing::AssertionResult PrintedNodeMatches(
|
||||
StringRef Code, const std::vector<std::string> &Args,
|
||||
const Matcher &NodeMatch, StringRef ExpectedPrinted, StringRef FileName,
|
||||
NodePrinter<NodeType> Printer,
|
||||
PrintingPolicyAdjuster PolicyAdjuster = nullptr, bool AllowError = false,
|
||||
NodeFilter<NodeType> Filter = [](const NodeType *) { return true; }) {
|
||||
|
||||
PrintMatch Printer(PolicyAdjuster);
|
||||
PrintMatch<NodeType> Callback(Printer, PolicyAdjuster, Filter);
|
||||
ast_matchers::MatchFinder Finder;
|
||||
Finder.addMatcher(NodeMatch, &Printer);
|
||||
Finder.addMatcher(NodeMatch, &Callback);
|
||||
std::unique_ptr<tooling::FrontendActionFactory> Factory(
|
||||
tooling::newFrontendActionFactory(&Finder));
|
||||
|
||||
if (!tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args))
|
||||
bool ToolResult;
|
||||
if (FileName.empty()) {
|
||||
ToolResult = tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args);
|
||||
} else {
|
||||
ToolResult =
|
||||
tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName);
|
||||
}
|
||||
if (!ToolResult && !AllowError)
|
||||
return testing::AssertionFailure()
|
||||
<< "Parsing error in \"" << Code.str() << "\"";
|
||||
|
||||
if (Printer.getNumFoundStmts() == 0)
|
||||
return testing::AssertionFailure() << "Matcher didn't find any statements";
|
||||
if (Callback.getNumFoundNodes() == 0)
|
||||
return testing::AssertionFailure() << "Matcher didn't find any nodes";
|
||||
|
||||
if (Printer.getNumFoundStmts() > 1)
|
||||
if (Callback.getNumFoundNodes() > 1)
|
||||
return testing::AssertionFailure()
|
||||
<< "Matcher should match only one statement (found "
|
||||
<< Printer.getNumFoundStmts() << ")";
|
||||
<< "Matcher should match only one node (found "
|
||||
<< Callback.getNumFoundNodes() << ")";
|
||||
|
||||
if (Printer.getPrinted() != ExpectedPrinted)
|
||||
if (Callback.getPrinted() != ExpectedPrinted)
|
||||
return ::testing::AssertionFailure()
|
||||
<< "Expected \"" << ExpectedPrinted.str() << "\", got \""
|
||||
<< Printer.getPrinted().str() << "\"";
|
||||
<< Callback.getPrinted().str() << "\"";
|
||||
|
||||
return ::testing::AssertionSuccess();
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ASTPrint.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/ASTMatchers/ASTMatchers.h"
|
||||
@ -32,10 +33,8 @@ using namespace tooling;
|
||||
|
||||
namespace {
|
||||
|
||||
using PrintingPolicyModifier = void (*)(PrintingPolicy &policy);
|
||||
|
||||
void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D,
|
||||
PrintingPolicyModifier PolicyModifier) {
|
||||
PrintingPolicyAdjuster PolicyModifier) {
|
||||
PrintingPolicy Policy = Context->getPrintingPolicy();
|
||||
Policy.TerseOutput = true;
|
||||
Policy.Indentation = 0;
|
||||
@ -44,74 +43,23 @@ void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D,
|
||||
D->print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ false);
|
||||
}
|
||||
|
||||
class PrintMatch : public MatchFinder::MatchCallback {
|
||||
SmallString<1024> Printed;
|
||||
unsigned NumFoundDecls;
|
||||
PrintingPolicyModifier PolicyModifier;
|
||||
|
||||
public:
|
||||
PrintMatch(PrintingPolicyModifier PolicyModifier)
|
||||
: NumFoundDecls(0), PolicyModifier(PolicyModifier) {}
|
||||
|
||||
void run(const MatchFinder::MatchResult &Result) override {
|
||||
const Decl *D = Result.Nodes.getNodeAs<Decl>("id");
|
||||
if (!D || D->isImplicit())
|
||||
return;
|
||||
NumFoundDecls++;
|
||||
if (NumFoundDecls > 1)
|
||||
return;
|
||||
|
||||
llvm::raw_svector_ostream Out(Printed);
|
||||
PrintDecl(Out, Result.Context, D, PolicyModifier);
|
||||
}
|
||||
|
||||
StringRef getPrinted() const {
|
||||
return Printed;
|
||||
}
|
||||
|
||||
unsigned getNumFoundDecls() const {
|
||||
return NumFoundDecls;
|
||||
}
|
||||
};
|
||||
|
||||
::testing::AssertionResult
|
||||
PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
|
||||
const DeclarationMatcher &NodeMatch,
|
||||
StringRef ExpectedPrinted, StringRef FileName,
|
||||
PrintingPolicyModifier PolicyModifier = nullptr,
|
||||
PrintingPolicyAdjuster PolicyModifier = nullptr,
|
||||
bool AllowError = false) {
|
||||
PrintMatch Printer(PolicyModifier);
|
||||
MatchFinder Finder;
|
||||
Finder.addMatcher(NodeMatch, &Printer);
|
||||
std::unique_ptr<FrontendActionFactory> Factory(
|
||||
newFrontendActionFactory(&Finder));
|
||||
|
||||
if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName) &&
|
||||
!AllowError)
|
||||
return testing::AssertionFailure()
|
||||
<< "Parsing error in \"" << Code.str() << "\"";
|
||||
|
||||
if (Printer.getNumFoundDecls() == 0)
|
||||
return testing::AssertionFailure()
|
||||
<< "Matcher didn't find any declarations";
|
||||
|
||||
if (Printer.getNumFoundDecls() > 1)
|
||||
return testing::AssertionFailure()
|
||||
<< "Matcher should match only one declaration "
|
||||
"(found " << Printer.getNumFoundDecls() << ")";
|
||||
|
||||
if (Printer.getPrinted() != ExpectedPrinted)
|
||||
return ::testing::AssertionFailure()
|
||||
<< "Expected \"" << ExpectedPrinted.str() << "\", "
|
||||
"got \"" << Printer.getPrinted().str() << "\"";
|
||||
|
||||
return ::testing::AssertionSuccess();
|
||||
return PrintedNodeMatches<Decl>(
|
||||
Code, Args, NodeMatch, ExpectedPrinted, FileName, PrintDecl,
|
||||
PolicyModifier, AllowError,
|
||||
// Filter out implicit decls
|
||||
[](const Decl *D) { return !D->isImplicit(); });
|
||||
}
|
||||
|
||||
::testing::AssertionResult
|
||||
PrintedDeclCXX98Matches(StringRef Code, StringRef DeclName,
|
||||
StringRef ExpectedPrinted,
|
||||
PrintingPolicyModifier PolicyModifier = nullptr) {
|
||||
PrintingPolicyAdjuster PolicyModifier = nullptr) {
|
||||
std::vector<std::string> Args(1, "-std=c++98");
|
||||
return PrintedDeclMatches(Code, Args, namedDecl(hasName(DeclName)).bind("id"),
|
||||
ExpectedPrinted, "input.cc", PolicyModifier);
|
||||
@ -120,7 +68,7 @@ PrintedDeclCXX98Matches(StringRef Code, StringRef DeclName,
|
||||
::testing::AssertionResult
|
||||
PrintedDeclCXX98Matches(StringRef Code, const DeclarationMatcher &NodeMatch,
|
||||
StringRef ExpectedPrinted,
|
||||
PrintingPolicyModifier PolicyModifier = nullptr) {
|
||||
PrintingPolicyAdjuster PolicyModifier = nullptr) {
|
||||
std::vector<std::string> Args(1, "-std=c++98");
|
||||
return PrintedDeclMatches(Code,
|
||||
Args,
|
||||
@ -165,7 +113,7 @@ PrintedDeclCXX98Matches(StringRef Code, const DeclarationMatcher &NodeMatch,
|
||||
::testing::AssertionResult
|
||||
PrintedDeclCXX17Matches(StringRef Code, const DeclarationMatcher &NodeMatch,
|
||||
StringRef ExpectedPrinted,
|
||||
PrintingPolicyModifier PolicyModifier = nullptr) {
|
||||
PrintingPolicyAdjuster PolicyModifier = nullptr) {
|
||||
std::vector<std::string> Args{"-std=c++17", "-fno-delayed-template-parsing"};
|
||||
return PrintedDeclMatches(Code, Args, NodeMatch, ExpectedPrinted, "input.cc",
|
||||
PolicyModifier);
|
||||
@ -174,7 +122,7 @@ PrintedDeclCXX17Matches(StringRef Code, const DeclarationMatcher &NodeMatch,
|
||||
::testing::AssertionResult
|
||||
PrintedDeclC11Matches(StringRef Code, const DeclarationMatcher &NodeMatch,
|
||||
StringRef ExpectedPrinted,
|
||||
PrintingPolicyModifier PolicyModifier = nullptr) {
|
||||
PrintingPolicyAdjuster PolicyModifier = nullptr) {
|
||||
std::vector<std::string> Args(1, "-std=c11");
|
||||
return PrintedDeclMatches(Code, Args, NodeMatch, ExpectedPrinted, "input.c",
|
||||
PolicyModifier);
|
||||
|
@ -15,6 +15,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ASTPrint.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
@ -66,31 +67,11 @@ public:
|
||||
const DeclarationMatcher &NodeMatch, StringRef ExpectedPrinted,
|
||||
StringRef FileName,
|
||||
std::function<void(llvm::raw_ostream &, const NamedDecl *)> Print) {
|
||||
PrintMatch Printer(std::move(Print));
|
||||
MatchFinder Finder;
|
||||
Finder.addMatcher(NodeMatch, &Printer);
|
||||
std::unique_ptr<FrontendActionFactory> Factory =
|
||||
newFrontendActionFactory(&Finder);
|
||||
|
||||
if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName))
|
||||
return testing::AssertionFailure()
|
||||
<< "Parsing error in \"" << Code.str() << "\"";
|
||||
|
||||
if (Printer.getNumFoundDecls() == 0)
|
||||
return testing::AssertionFailure()
|
||||
<< "Matcher didn't find any named declarations";
|
||||
|
||||
if (Printer.getNumFoundDecls() > 1)
|
||||
return testing::AssertionFailure()
|
||||
<< "Matcher should match only one named declaration "
|
||||
"(found " << Printer.getNumFoundDecls() << ")";
|
||||
|
||||
if (Printer.getPrinted() != ExpectedPrinted)
|
||||
return ::testing::AssertionFailure()
|
||||
<< "Expected \"" << ExpectedPrinted.str() << "\", "
|
||||
"got \"" << Printer.getPrinted().str() << "\"";
|
||||
|
||||
return ::testing::AssertionSuccess();
|
||||
return PrintedNodeMatches<NamedDecl>(
|
||||
Code, Args, NodeMatch, ExpectedPrinted, FileName,
|
||||
[Print](llvm::raw_ostream &Out, const ASTContext *Context,
|
||||
const NamedDecl *ND,
|
||||
PrintingPolicyAdjuster PolicyAdjuster) { Print(Out, ND); });
|
||||
}
|
||||
|
||||
::testing::AssertionResult
|
||||
|
@ -38,11 +38,29 @@ DeclarationMatcher FunctionBodyMatcher(StringRef ContainingFunction) {
|
||||
has(compoundStmt(has(stmt().bind("id")))));
|
||||
}
|
||||
|
||||
static void PrintStmt(raw_ostream &Out, const ASTContext *Context,
|
||||
const Stmt *S, PrintingPolicyAdjuster PolicyAdjuster) {
|
||||
assert(S != nullptr && "Expected non-null Stmt");
|
||||
PrintingPolicy Policy = Context->getPrintingPolicy();
|
||||
if (PolicyAdjuster)
|
||||
PolicyAdjuster(Policy);
|
||||
S->printPretty(Out, /*Helper*/ nullptr, Policy);
|
||||
}
|
||||
|
||||
template <typename Matcher>
|
||||
::testing::AssertionResult
|
||||
PrintedStmtMatches(StringRef Code, const std::vector<std::string> &Args,
|
||||
const Matcher &NodeMatch, StringRef ExpectedPrinted,
|
||||
PrintingPolicyAdjuster PolicyAdjuster = nullptr) {
|
||||
return PrintedNodeMatches<Stmt>(Code, Args, NodeMatch, ExpectedPrinted, "",
|
||||
PrintStmt, PolicyAdjuster);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
::testing::AssertionResult
|
||||
PrintedStmtCXXMatches(StdVer Standard, StringRef Code, const T &NodeMatch,
|
||||
StringRef ExpectedPrinted,
|
||||
PolicyAdjusterType PolicyAdjuster = None) {
|
||||
PrintingPolicyAdjuster PolicyAdjuster = nullptr) {
|
||||
const char *StdOpt;
|
||||
switch (Standard) {
|
||||
case StdVer::CXX98: StdOpt = "-std=c++98"; break;
|
||||
@ -64,7 +82,7 @@ template <typename T>
|
||||
::testing::AssertionResult
|
||||
PrintedStmtMSMatches(StringRef Code, const T &NodeMatch,
|
||||
StringRef ExpectedPrinted,
|
||||
PolicyAdjusterType PolicyAdjuster = None) {
|
||||
PrintingPolicyAdjuster PolicyAdjuster = nullptr) {
|
||||
std::vector<std::string> Args = {
|
||||
"-std=c++98",
|
||||
"-target", "i686-pc-win32",
|
||||
@ -79,7 +97,7 @@ template <typename T>
|
||||
::testing::AssertionResult
|
||||
PrintedStmtObjCMatches(StringRef Code, const T &NodeMatch,
|
||||
StringRef ExpectedPrinted,
|
||||
PolicyAdjusterType PolicyAdjuster = None) {
|
||||
PrintingPolicyAdjuster PolicyAdjuster = nullptr) {
|
||||
std::vector<std::string> Args = {
|
||||
"-ObjC",
|
||||
"-fobjc-runtime=macosx-10.12.0",
|
||||
@ -202,10 +220,10 @@ class A {
|
||||
};
|
||||
)";
|
||||
// No implicit 'this'.
|
||||
ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11,
|
||||
CPPSource, memberExpr(anything()).bind("id"), "field",
|
||||
PolicyAdjusterType(
|
||||
[](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; })));
|
||||
ASSERT_TRUE(PrintedStmtCXXMatches(
|
||||
StdVer::CXX11, CPPSource, memberExpr(anything()).bind("id"), "field",
|
||||
|
||||
[](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; }));
|
||||
// Print implicit 'this'.
|
||||
ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11,
|
||||
CPPSource, memberExpr(anything()).bind("id"), "this->field"));
|
||||
@ -222,11 +240,10 @@ class A {
|
||||
@end
|
||||
)";
|
||||
// No implicit 'self'.
|
||||
ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"),
|
||||
"return ivar;\n",
|
||||
PolicyAdjusterType([](PrintingPolicy &PP) {
|
||||
PP.SuppressImplicitBase = true;
|
||||
})));
|
||||
ASSERT_TRUE(PrintedStmtObjCMatches(
|
||||
ObjCSource, returnStmt().bind("id"), "return ivar;\n",
|
||||
|
||||
[](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; }));
|
||||
// Print implicit 'self'.
|
||||
ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"),
|
||||
"return self->ivar;\n"));
|
||||
@ -243,5 +260,6 @@ TEST(StmtPrinter, TerseOutputWithLambdas) {
|
||||
// body not printed when TerseOutput is on.
|
||||
ASSERT_TRUE(PrintedStmtCXXMatches(
|
||||
StdVer::CXX11, CPPSource, lambdaExpr(anything()).bind("id"), "[] {}",
|
||||
PolicyAdjusterType([](PrintingPolicy &PP) { PP.TerseOutput = true; })));
|
||||
|
||||
[](PrintingPolicy &PP) { PP.TerseOutput = true; }));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user