mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-09 17:43:57 +00:00
[clang-query] Add option to print matcher expression
Summary: This is useful if using clang-query -f with a file containing multiple matchers. Reviewers: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D52859 llvm-svn: 344840
This commit is contained in:
parent
d0e5eca0fd
commit
4a5b01ddd7
@ -41,6 +41,8 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
|
|||||||
"as part of other expressions.\n"
|
"as part of other expressions.\n"
|
||||||
" set bind-root (true|false) "
|
" set bind-root (true|false) "
|
||||||
"Set whether to bind the root matcher to \"root\".\n"
|
"Set whether to bind the root matcher to \"root\".\n"
|
||||||
|
" set print-matcher (true|false) "
|
||||||
|
"Set whether to print the current matcher,\n"
|
||||||
" set output (diag|print|dump) "
|
" set output (diag|print|dump) "
|
||||||
"Set whether to print bindings as diagnostics,\n"
|
"Set whether to print bindings as diagnostics,\n"
|
||||||
" "
|
" "
|
||||||
@ -86,6 +88,12 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
|
|||||||
}
|
}
|
||||||
Finder.matchAST(AST->getASTContext());
|
Finder.matchAST(AST->getASTContext());
|
||||||
|
|
||||||
|
if (QS.PrintMatcher) {
|
||||||
|
std::string prefixText = "Matcher: ";
|
||||||
|
OS << "\n " << prefixText << Source << "\n";
|
||||||
|
OS << " " << std::string(prefixText.size() + Source.size(), '=') << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
for (auto MI = Matches.begin(), ME = Matches.end(); MI != ME; ++MI) {
|
for (auto MI = Matches.begin(), ME = Matches.end(); MI != ME; ++MI) {
|
||||||
OS << "\nMatch #" << ++MatchCount << ":\n\n";
|
OS << "\nMatch #" << ++MatchCount << ":\n\n";
|
||||||
|
|
||||||
|
@ -83,12 +83,15 @@ struct QuitQuery : Query {
|
|||||||
|
|
||||||
/// Query for "match MATCHER".
|
/// Query for "match MATCHER".
|
||||||
struct MatchQuery : Query {
|
struct MatchQuery : Query {
|
||||||
MatchQuery(const ast_matchers::dynamic::DynTypedMatcher &Matcher)
|
MatchQuery(StringRef Source,
|
||||||
: Query(QK_Match), Matcher(Matcher) {}
|
const ast_matchers::dynamic::DynTypedMatcher &Matcher)
|
||||||
|
: Query(QK_Match), Matcher(Matcher), Source(Source) {}
|
||||||
bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
|
bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
|
||||||
|
|
||||||
ast_matchers::dynamic::DynTypedMatcher Matcher;
|
ast_matchers::dynamic::DynTypedMatcher Matcher;
|
||||||
|
|
||||||
|
StringRef Source;
|
||||||
|
|
||||||
static bool classof(const Query *Q) { return Q->Kind == QK_Match; }
|
static bool classof(const Query *Q) { return Q->Kind == QK_Match; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -142,7 +142,12 @@ enum ParsedQueryKind {
|
|||||||
PQK_Quit
|
PQK_Quit
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ParsedQueryVariable { PQV_Invalid, PQV_Output, PQV_BindRoot };
|
enum ParsedQueryVariable {
|
||||||
|
PQV_Invalid,
|
||||||
|
PQV_Output,
|
||||||
|
PQV_BindRoot,
|
||||||
|
PQV_PrintMatcher
|
||||||
|
};
|
||||||
|
|
||||||
QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) {
|
QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) {
|
||||||
std::string ErrStr;
|
std::string ErrStr;
|
||||||
@ -214,21 +219,23 @@ QueryRef QueryParser::doParse() {
|
|||||||
return completeMatcherExpression();
|
return completeMatcherExpression();
|
||||||
|
|
||||||
Diagnostics Diag;
|
Diagnostics Diag;
|
||||||
|
auto MatcherSource = StringRef(Begin, End - Begin).trim();
|
||||||
Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
|
Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
|
||||||
StringRef(Begin, End - Begin), nullptr, &QS.NamedValues, &Diag);
|
MatcherSource, nullptr, &QS.NamedValues, &Diag);
|
||||||
if (!Matcher) {
|
if (!Matcher) {
|
||||||
return makeInvalidQueryFromDiagnostics(Diag);
|
return makeInvalidQueryFromDiagnostics(Diag);
|
||||||
}
|
}
|
||||||
return new MatchQuery(*Matcher);
|
return new MatchQuery(MatcherSource, *Matcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
case PQK_Set: {
|
case PQK_Set: {
|
||||||
StringRef VarStr;
|
StringRef VarStr;
|
||||||
ParsedQueryVariable Var = LexOrCompleteWord<ParsedQueryVariable>(this,
|
ParsedQueryVariable Var =
|
||||||
VarStr)
|
LexOrCompleteWord<ParsedQueryVariable>(this, VarStr)
|
||||||
.Case("output", PQV_Output)
|
.Case("output", PQV_Output)
|
||||||
.Case("bind-root", PQV_BindRoot)
|
.Case("bind-root", PQV_BindRoot)
|
||||||
.Default(PQV_Invalid);
|
.Case("print-matcher", PQV_PrintMatcher)
|
||||||
|
.Default(PQV_Invalid);
|
||||||
if (VarStr.empty())
|
if (VarStr.empty())
|
||||||
return new InvalidQuery("expected variable name");
|
return new InvalidQuery("expected variable name");
|
||||||
if (Var == PQV_Invalid)
|
if (Var == PQV_Invalid)
|
||||||
@ -242,6 +249,9 @@ QueryRef QueryParser::doParse() {
|
|||||||
case PQV_BindRoot:
|
case PQV_BindRoot:
|
||||||
Q = parseSetBool(&QuerySession::BindRoot);
|
Q = parseSetBool(&QuerySession::BindRoot);
|
||||||
break;
|
break;
|
||||||
|
case PQV_PrintMatcher:
|
||||||
|
Q = parseSetBool(&QuerySession::PrintMatcher);
|
||||||
|
break;
|
||||||
case PQV_Invalid:
|
case PQV_Invalid:
|
||||||
llvm_unreachable("Invalid query kind");
|
llvm_unreachable("Invalid query kind");
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,13 @@ namespace query {
|
|||||||
class QuerySession {
|
class QuerySession {
|
||||||
public:
|
public:
|
||||||
QuerySession(llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs)
|
QuerySession(llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs)
|
||||||
: ASTs(ASTs), OutKind(OK_Diag), BindRoot(true), Terminate(false) {}
|
: ASTs(ASTs), OutKind(OK_Diag), BindRoot(true), PrintMatcher(false),
|
||||||
|
Terminate(false) {}
|
||||||
|
|
||||||
llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs;
|
llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs;
|
||||||
OutputKind OutKind;
|
OutputKind OutKind;
|
||||||
bool BindRoot;
|
bool BindRoot;
|
||||||
|
bool PrintMatcher;
|
||||||
bool Terminate;
|
bool Terminate;
|
||||||
llvm::StringMap<ast_matchers::dynamic::VariantValue> NamedValues;
|
llvm::StringMap<ast_matchers::dynamic::VariantValue> NamedValues;
|
||||||
};
|
};
|
||||||
|
@ -52,6 +52,8 @@ TEST_F(QueryEngineTest, Basic) {
|
|||||||
DynTypedMatcher FnMatcher = functionDecl();
|
DynTypedMatcher FnMatcher = functionDecl();
|
||||||
DynTypedMatcher FooMatcher = functionDecl(hasName("foo1"));
|
DynTypedMatcher FooMatcher = functionDecl(hasName("foo1"));
|
||||||
|
|
||||||
|
std::string FooMatcherString = "functionDecl(hasName(\"foo1\"))";
|
||||||
|
|
||||||
EXPECT_TRUE(NoOpQuery().run(OS, S));
|
EXPECT_TRUE(NoOpQuery().run(OS, S));
|
||||||
|
|
||||||
EXPECT_EQ("", OS.str());
|
EXPECT_EQ("", OS.str());
|
||||||
@ -70,7 +72,7 @@ TEST_F(QueryEngineTest, Basic) {
|
|||||||
|
|
||||||
Str.clear();
|
Str.clear();
|
||||||
|
|
||||||
EXPECT_TRUE(MatchQuery(FnMatcher).run(OS, S));
|
EXPECT_TRUE(MatchQuery("functionDecl()", FnMatcher).run(OS, S));
|
||||||
|
|
||||||
EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=
|
EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=
|
||||||
std::string::npos);
|
std::string::npos);
|
||||||
@ -84,7 +86,7 @@ TEST_F(QueryEngineTest, Basic) {
|
|||||||
|
|
||||||
Str.clear();
|
Str.clear();
|
||||||
|
|
||||||
EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S));
|
EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));
|
||||||
|
|
||||||
EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=
|
EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=
|
||||||
std::string::npos);
|
std::string::npos);
|
||||||
@ -94,7 +96,7 @@ TEST_F(QueryEngineTest, Basic) {
|
|||||||
|
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
SetQuery<OutputKind>(&QuerySession::OutKind, OK_Print).run(OS, S));
|
SetQuery<OutputKind>(&QuerySession::OutKind, OK_Print).run(OS, S));
|
||||||
EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S));
|
EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));
|
||||||
|
|
||||||
EXPECT_TRUE(OS.str().find("Binding for \"root\":\nvoid foo1()") !=
|
EXPECT_TRUE(OS.str().find("Binding for \"root\":\nvoid foo1()") !=
|
||||||
std::string::npos);
|
std::string::npos);
|
||||||
@ -102,20 +104,20 @@ TEST_F(QueryEngineTest, Basic) {
|
|||||||
Str.clear();
|
Str.clear();
|
||||||
|
|
||||||
EXPECT_TRUE(SetQuery<OutputKind>(&QuerySession::OutKind, OK_Dump).run(OS, S));
|
EXPECT_TRUE(SetQuery<OutputKind>(&QuerySession::OutKind, OK_Dump).run(OS, S));
|
||||||
EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S));
|
EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));
|
||||||
|
|
||||||
EXPECT_TRUE(OS.str().find("FunctionDecl") != std::string::npos);
|
EXPECT_TRUE(OS.str().find("FunctionDecl") != std::string::npos);
|
||||||
|
|
||||||
Str.clear();
|
Str.clear();
|
||||||
|
|
||||||
EXPECT_TRUE(SetQuery<bool>(&QuerySession::BindRoot, false).run(OS, S));
|
EXPECT_TRUE(SetQuery<bool>(&QuerySession::BindRoot, false).run(OS, S));
|
||||||
EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S));
|
EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));
|
||||||
|
|
||||||
EXPECT_TRUE(OS.str().find("No bindings.") != std::string::npos);
|
EXPECT_TRUE(OS.str().find("No bindings.") != std::string::npos);
|
||||||
|
|
||||||
Str.clear();
|
Str.clear();
|
||||||
|
|
||||||
EXPECT_FALSE(MatchQuery(isMain()).run(OS, S));
|
EXPECT_FALSE(MatchQuery("isMain()", isMain()).run(OS, S));
|
||||||
|
|
||||||
EXPECT_EQ("Not a valid top-level matcher.\n", OS.str());
|
EXPECT_EQ("Not a valid top-level matcher.\n", OS.str());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user