Skip to content

Commit 858a958

Browse files
committed
[clang-query] Add check to prevent setting srcloc when no introspection is available.
Checks if introspection support is available set output kind parser. If it isn't present the auto complete will not suggest `srcloc` and an error query will be reported if a user tries to access it. Reviewed By: steveire Differential Revision: https://reviews.llvm.org/D101365
1 parent 3ea4bc7 commit 858a958

File tree

3 files changed

+43
-20
lines changed

3 files changed

+43
-20
lines changed

clang-tools-extra/clang-query/Query.h

+1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ struct SetExclusiveOutputQuery : Query {
149149
QS.DiagOutput = false;
150150
QS.DetailedASTOutput = false;
151151
QS.PrintOutput = false;
152+
QS.SrcLocOutput = false;
152153
QS.*Var = true;
153154
return true;
154155
}

clang-tools-extra/clang-query/QueryParser.cpp

+16-11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "QuerySession.h"
1212
#include "clang/ASTMatchers/Dynamic/Parser.h"
1313
#include "clang/Basic/CharInfo.h"
14+
#include "clang/Tooling/NodeIntrospection.h"
1415
#include "llvm/ADT/StringRef.h"
1516
#include "llvm/ADT/StringSwitch.h"
1617
#include <set>
@@ -104,17 +105,19 @@ QueryRef QueryParser::parseSetBool(bool QuerySession::*Var) {
104105

105106
template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() {
106107
StringRef ValStr;
107-
unsigned OutKind = LexOrCompleteWord<unsigned>(this, ValStr)
108-
.Case("diag", OK_Diag)
109-
.Case("print", OK_Print)
110-
.Case("detailed-ast", OK_DetailedAST)
111-
.Case("srcloc", OK_SrcLoc)
112-
.Case("dump", OK_DetailedAST)
113-
.Default(~0u);
108+
bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport();
109+
unsigned OutKind =
110+
LexOrCompleteWord<unsigned>(this, ValStr)
111+
.Case("diag", OK_Diag)
112+
.Case("print", OK_Print)
113+
.Case("detailed-ast", OK_DetailedAST)
114+
.Case("srcloc", OK_SrcLoc, /*IsCompletion=*/HasIntrospection)
115+
.Case("dump", OK_DetailedAST)
116+
.Default(~0u);
114117
if (OutKind == ~0u) {
115-
return new InvalidQuery(
116-
"expected 'diag', 'print', 'detailed-ast' or 'dump', got '" + ValStr +
117-
"'");
118+
return new InvalidQuery("expected 'diag', 'print', 'detailed-ast'" +
119+
StringRef(HasIntrospection ? ", 'srcloc'" : "") +
120+
" or 'dump', got '" + ValStr + "'");
118121
}
119122

120123
switch (OutKind) {
@@ -125,7 +128,9 @@ template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() {
125128
case OK_Print:
126129
return new QueryType(&QuerySession::PrintOutput);
127130
case OK_SrcLoc:
128-
return new QueryType(&QuerySession::SrcLocOutput);
131+
if (HasIntrospection)
132+
return new QueryType(&QuerySession::SrcLocOutput);
133+
return new InvalidQuery("'srcloc' output support is not available.");
129134
}
130135

131136
llvm_unreachable("Invalid output kind");

clang-tools-extra/unittests/clang-query/QueryParserTest.cpp

+26-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "QueryParser.h"
1010
#include "Query.h"
1111
#include "QuerySession.h"
12+
#include "clang/Tooling/NodeIntrospection.h"
1213
#include "llvm/LineEditor/LineEditor.h"
1314
#include "gtest/gtest.h"
1415

@@ -59,6 +60,8 @@ TEST_F(QueryParserTest, Quit) {
5960
}
6061

6162
TEST_F(QueryParserTest, Set) {
63+
64+
bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport();
6265
QueryRef Q = parse("set");
6366
ASSERT_TRUE(isa<InvalidQuery>(Q));
6467
EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);
@@ -69,17 +72,27 @@ TEST_F(QueryParserTest, Set) {
6972

7073
Q = parse("set output");
7174
ASSERT_TRUE(isa<InvalidQuery>(Q));
72-
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''",
73-
cast<InvalidQuery>(Q)->ErrStr);
75+
if (HasIntrospection)
76+
EXPECT_EQ(
77+
"expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', got ''",
78+
cast<InvalidQuery>(Q)->ErrStr);
79+
else
80+
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''",
81+
cast<InvalidQuery>(Q)->ErrStr);
7482

7583
Q = parse("set bind-root true foo");
7684
ASSERT_TRUE(isa<InvalidQuery>(Q));
7785
EXPECT_EQ("unexpected extra input: ' foo'", cast<InvalidQuery>(Q)->ErrStr);
7886

7987
Q = parse("set output foo");
8088
ASSERT_TRUE(isa<InvalidQuery>(Q));
81-
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'",
82-
cast<InvalidQuery>(Q)->ErrStr);
89+
if (HasIntrospection)
90+
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', "
91+
"got 'foo'",
92+
cast<InvalidQuery>(Q)->ErrStr);
93+
else
94+
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'",
95+
cast<InvalidQuery>(Q)->ErrStr);
8396

8497
Q = parse("set output dump");
8598
ASSERT_TRUE(isa<SetExclusiveOutputQuery >(Q));
@@ -217,19 +230,23 @@ TEST_F(QueryParserTest, Complete) {
217230
EXPECT_EQ("output ", Comps[0].TypedText);
218231
EXPECT_EQ("output", Comps[0].DisplayText);
219232

233+
bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport();
234+
220235
Comps = QueryParser::complete("enable output ", 14, QS);
221-
ASSERT_EQ(5u, Comps.size());
236+
ASSERT_EQ(HasIntrospection ? 5u : 4u, Comps.size());
222237

223238
EXPECT_EQ("diag ", Comps[0].TypedText);
224239
EXPECT_EQ("diag", Comps[0].DisplayText);
225240
EXPECT_EQ("print ", Comps[1].TypedText);
226241
EXPECT_EQ("print", Comps[1].DisplayText);
227242
EXPECT_EQ("detailed-ast ", Comps[2].TypedText);
228243
EXPECT_EQ("detailed-ast", Comps[2].DisplayText);
229-
EXPECT_EQ("srcloc ", Comps[3].TypedText);
230-
EXPECT_EQ("srcloc", Comps[3].DisplayText);
231-
EXPECT_EQ("dump ", Comps[4].TypedText);
232-
EXPECT_EQ("dump", Comps[4].DisplayText);
244+
if (HasIntrospection) {
245+
EXPECT_EQ("srcloc ", Comps[3].TypedText);
246+
EXPECT_EQ("srcloc", Comps[3].DisplayText);
247+
}
248+
EXPECT_EQ("dump ", Comps[HasIntrospection ? 4 : 3].TypedText);
249+
EXPECT_EQ("dump", Comps[HasIntrospection ? 4 : 3].DisplayText);
233250

234251
Comps = QueryParser::complete("set traversal ", 14, QS);
235252
ASSERT_EQ(2u, Comps.size());

0 commit comments

Comments
 (0)