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 "llvm/ADT/Optional.h"
16 #include <string>
17 
18 namespace clang {
19 namespace query {
20 
21 enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST };
22 
23 enum QueryKind {
24   QK_Invalid,
25   QK_NoOp,
26   QK_Help,
27   QK_Let,
28   QK_Match,
29   QK_SetBool,
30   QK_SetOutputKind,
31   QK_SetTraversalKind,
32   QK_EnableOutputKind,
33   QK_DisableOutputKind,
34   QK_Quit
35 };
36 
37 class QuerySession;
38 
39 struct Query : llvm::RefCountedBase<Query> {
QueryQuery40   Query(QueryKind Kind) : Kind(Kind) {}
41   virtual ~Query();
42 
43   /// Perform the query on \p QS and print output to \p OS.
44   ///
45   /// \return false if an error occurs, otherwise return true.
46   virtual bool run(llvm::raw_ostream &OS, QuerySession &QS) const = 0;
47 
48   StringRef RemainingContent;
49   const QueryKind Kind;
50 };
51 
52 typedef llvm::IntrusiveRefCntPtr<Query> QueryRef;
53 
54 /// Any query which resulted in a parse error.  The error message is in ErrStr.
55 struct InvalidQuery : Query {
InvalidQueryInvalidQuery56   InvalidQuery(const Twine &ErrStr) : Query(QK_Invalid), ErrStr(ErrStr.str()) {}
57   bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
58 
59   std::string ErrStr;
60 
classofInvalidQuery61   static bool classof(const Query *Q) { return Q->Kind == QK_Invalid; }
62 };
63 
64 /// No-op query (i.e. a blank line).
65 struct NoOpQuery : Query {
NoOpQueryNoOpQuery66   NoOpQuery() : Query(QK_NoOp) {}
67   bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
68 
classofNoOpQuery69   static bool classof(const Query *Q) { return Q->Kind == QK_NoOp; }
70 };
71 
72 /// Query for "help".
73 struct HelpQuery : Query {
HelpQueryHelpQuery74   HelpQuery() : Query(QK_Help) {}
75   bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
76 
classofHelpQuery77   static bool classof(const Query *Q) { return Q->Kind == QK_Help; }
78 };
79 
80 /// Query for "quit".
81 struct QuitQuery : Query {
QuitQueryQuitQuery82   QuitQuery() : Query(QK_Quit) {}
83   bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
84 
classofQuitQuery85   static bool classof(const Query *Q) { return Q->Kind == QK_Quit; }
86 };
87 
88 /// Query for "match MATCHER".
89 struct MatchQuery : Query {
MatchQueryMatchQuery90   MatchQuery(StringRef Source,
91              const ast_matchers::dynamic::DynTypedMatcher &Matcher)
92       : Query(QK_Match), Matcher(Matcher), Source(Source) {}
93   bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
94 
95   ast_matchers::dynamic::DynTypedMatcher Matcher;
96 
97   StringRef Source;
98 
classofMatchQuery99   static bool classof(const Query *Q) { return Q->Kind == QK_Match; }
100 };
101 
102 struct LetQuery : Query {
LetQueryLetQuery103   LetQuery(StringRef Name, const ast_matchers::dynamic::VariantValue &Value)
104       : Query(QK_Let), Name(Name), Value(Value) {}
105   bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
106 
107   std::string Name;
108   ast_matchers::dynamic::VariantValue Value;
109 
classofLetQuery110   static bool classof(const Query *Q) { return Q->Kind == QK_Let; }
111 };
112 
113 template <typename T> struct SetQueryKind {};
114 
115 template <> struct SetQueryKind<bool> {
116   static const QueryKind value = QK_SetBool;
117 };
118 
119 template <> struct SetQueryKind<OutputKind> {
120   static const QueryKind value = QK_SetOutputKind;
121 };
122 
123 template <> struct SetQueryKind<ast_type_traits::TraversalKind> {
124   static const QueryKind value = QK_SetTraversalKind;
125 };
126 
127 /// Query for "set VAR VALUE".
128 template <typename T> struct SetQuery : Query {
129   SetQuery(T QuerySession::*Var, T Value)
130       : Query(SetQueryKind<T>::value), Var(Var), Value(Value) {}
131   bool run(llvm::raw_ostream &OS, QuerySession &QS) const override {
132     QS.*Var = Value;
133     return true;
134   }
135 
136   static bool classof(const Query *Q) {
137     return Q->Kind == SetQueryKind<T>::value;
138   }
139 
140   T QuerySession::*Var;
141   T Value;
142 };
143 
144 // Implements the exclusive 'set output dump|diag|print' options.
145 struct SetExclusiveOutputQuery : Query {
146   SetExclusiveOutputQuery(bool QuerySession::*Var)
147       : Query(QK_SetOutputKind), Var(Var) {}
148   bool run(llvm::raw_ostream &OS, QuerySession &QS) const override {
149     QS.DiagOutput = false;
150     QS.DetailedASTOutput = false;
151     QS.PrintOutput = 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.
162 struct 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 
175 struct 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 
182 struct 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