1//===--- Query.h - clang-query ----------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_H
11
12#include "QuerySession.h"
13#include "clang/ASTMatchers/Dynamic/VariantValue.h"
14#include "llvm/ADT/IntrusiveRefCntPtr.h"
15#include <string>
16
17namespace clang {
18namespace query {
19
20enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST, OK_SrcLoc };
21
22enum QueryKind {
23 QK_Invalid,
24 QK_NoOp,
25 QK_Help,
26 QK_Let,
27 QK_Match,
28 QK_SetBool,
29 QK_SetOutputKind,
30 QK_SetTraversalKind,
31 QK_EnableOutputKind,
32 QK_DisableOutputKind,
33 QK_Quit
34};
35
36class QuerySession;
37
38struct Query : llvm::RefCountedBase<Query> {
39 Query(QueryKind Kind) : Kind(Kind) {}
40 virtual ~Query();
41
42 /// Perform the query on \p QS and print output to \p OS.
43 ///
44 /// \return false if an error occurs, otherwise return true.
45 virtual bool run(llvm::raw_ostream &OS, QuerySession &QS) const = 0;
46
47 StringRef RemainingContent;
48 const QueryKind Kind;
49};
50
51typedef llvm::IntrusiveRefCntPtr<Query> QueryRef;
52
53/// Any query which resulted in a parse error. The error message is in ErrStr.
54struct InvalidQuery : Query {
55 InvalidQuery(const Twine &ErrStr) : Query(QK_Invalid), ErrStr(ErrStr.str()) {}
56 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
57
58 std::string ErrStr;
59
60 static bool classof(const Query *Q) { return Q->Kind == QK_Invalid; }
61};
62
63/// No-op query (i.e. a blank line).
64struct NoOpQuery : Query {
65 NoOpQuery() : Query(QK_NoOp) {}
66 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
67
68 static bool classof(const Query *Q) { return Q->Kind == QK_NoOp; }
69};
70
71/// Query for "help".
72struct HelpQuery : Query {
73 HelpQuery() : Query(QK_Help) {}
74 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
75
76 static bool classof(const Query *Q) { return Q->Kind == QK_Help; }
77};
78
79/// Query for "quit".
80struct QuitQuery : Query {
81 QuitQuery() : Query(QK_Quit) {}
82 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
83
84 static bool classof(const Query *Q) { return Q->Kind == QK_Quit; }
85};
86
87/// Query for "match MATCHER".
88struct MatchQuery : Query {
89 MatchQuery(StringRef Source,
90 const ast_matchers::dynamic::DynTypedMatcher &Matcher)
91 : Query(QK_Match), Matcher(Matcher), Source(Source) {}
92 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
93
94 ast_matchers::dynamic::DynTypedMatcher Matcher;
95
96 StringRef Source;
97
98 static bool classof(const Query *Q) { return Q->Kind == QK_Match; }
99};
100
101struct LetQuery : Query {
102 LetQuery(StringRef Name, const ast_matchers::dynamic::VariantValue &Value)
103 : Query(QK_Let), Name(Name), Value(Value) {}
104 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
105
106 std::string Name;
107 ast_matchers::dynamic::VariantValue Value;
108
109 static bool classof(const Query *Q) { return Q->Kind == QK_Let; }
110};
111
112template <typename T> struct SetQueryKind {};
113
114template <> struct SetQueryKind<bool> {
115 static const QueryKind value = QK_SetBool;
116};
117
118template <> struct SetQueryKind<OutputKind> {
119 static const QueryKind value = QK_SetOutputKind;
120};
121
122template <> struct SetQueryKind<TraversalKind> {
123 static const QueryKind value = QK_SetTraversalKind;
124};
125
126/// Query for "set VAR VALUE".
127template <typename T> struct SetQuery : Query {
128 SetQuery(T QuerySession::*Var, T Value)
129 : Query(SetQueryKind<T>::value), Var(Var), Value(Value) {}
130 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override {
131 QS.*Var = Value;
132 return true;
133 }
134
135 static bool classof(const Query *Q) {
136 return Q->Kind == SetQueryKind<T>::value;
137 }
138
139 T QuerySession::*Var;
140 T Value;
141};
142
143// Implements the exclusive 'set output dump|diag|print' options.
144struct SetExclusiveOutputQuery : Query {
145 SetExclusiveOutputQuery(bool QuerySession::*Var)
146 : Query(QK_SetOutputKind), Var(Var) {}
147 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override {
148 QS.DiagOutput = false;
149 QS.DetailedASTOutput = false;
150 QS.PrintOutput = false;
151 QS.SrcLocOutput = false;
152 QS.*Var = true;
153 return true;
154 }
155
156 static bool classof(const Query *Q) { return Q->Kind == QK_SetOutputKind; }
157
158 bool QuerySession::*Var;
159};
160
161// Implements the non-exclusive 'set output dump|diag|print' options.
162struct SetNonExclusiveOutputQuery : Query {
163 SetNonExclusiveOutputQuery(QueryKind Kind, bool QuerySession::*Var,
164 bool Value)
165 : Query(Kind), Var(Var), Value(Value) {}
166 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override {
167 QS.*Var = Value;
168 return true;
169 }
170
171 bool QuerySession::*Var;
172 bool Value;
173};
174
175struct EnableOutputQuery : SetNonExclusiveOutputQuery {
176 EnableOutputQuery(bool QuerySession::*Var)
177 : SetNonExclusiveOutputQuery(QK_EnableOutputKind, Var, true) {}
178
179 static bool classof(const Query *Q) { return Q->Kind == QK_EnableOutputKind; }
180};
181
182struct DisableOutputQuery : SetNonExclusiveOutputQuery {
183 DisableOutputQuery(bool QuerySession::*Var)
184 : SetNonExclusiveOutputQuery(QK_DisableOutputKind, Var, false) {}
185
186 static bool classof(const Query *Q) {
187 return Q->Kind == QK_DisableOutputKind;
188 }
189};
190
191} // namespace query
192} // namespace clang
193
194#endif
195

source code of clang-tools-extra/clang-query/Query.h