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