clang: lib/Tooling/Transformer/RangeSelector.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
16#include "llvm/ADT/StringRef.h"
17#include "llvm/Support/Errc.h"
18#include "llvm/Support/Error.h"
19#include
20#include
21
22using namespace clang;
24
26using llvm::Error;
27using llvm::StringError;
28
30
32 return llvm::make_error(llvm::errc::invalid_argument, Message);
33}
34
37 " kind=" + Kind.asStringRef() + ")");
38}
39
44 " kind=" + Kind.asStringRef() + ")");
45}
46
48 StringRef Property) {
50 "' (node id=" + ID + ")");
51}
52
54 StringRef ID) {
55 auto &NodesMap = Nodes.getMap();
56 auto It = NodesMap.find(ID);
57 if (It == NodesMap.end())
59 return It->second;
60}
61
62
75
76
77
82 while (true) {
86
90
91 if (T.is(TK))
92 return T.getLocation();
93
94 Start = L;
95 }
96}
97
101 if (!SelectedRange)
102 return SelectedRange.takeError();
104 };
105}
106
110 if (!SelectedRange)
111 return SelectedRange.takeError();
113 if (SelectedRange->isTokenRange()) {
114
115
116
117
118
119
122 *Result.SourceManager, Result.Context->getLangOpts());
123 if (Range.isInvalid())
125 "after: can't resolve sub-range to valid source range");
126 End = Range.getEnd();
127 }
128
130 };
131}
132
136 if (!Node)
137 return Node.takeError();
138 return (Node->get<Decl>() != nullptr ||
139 (Node->get<Stmt>() != nullptr && Node->get<Expr>() == nullptr))
143 Node->getSourceRange(true));
144 };
145}
146
150 if (!Node)
151 return Node.takeError();
154 };
155}
156
160 if (!BeginRange)
161 return BeginRange.takeError();
163 if (!EndRange)
164 return EndRange.takeError();
167
168
169 if (Result.SourceManager->isBeforeInTranslationUnit(E, B)) {
171 }
173 };
174}
175
177 std::string EndID) {
179}
180
185 if (!FirstRange)
186 return FirstRange.takeError();
188 if (!SecondRange)
189 return SecondRange.takeError();
190
195
197 Result.SourceManager->isBeforeInTranslationUnit(FirstB, SecondB)
198 ? FirstB
199 : SecondB;
200 if (FirstRange->isTokenRange() && SecondRange->isTokenRange()) {
201
203 Result.SourceManager->isBeforeInTranslationUnit(FirstE, SecondE)
204 ? SecondE
205 : FirstE;
207 }
208
209 if (FirstRange->isTokenRange()) {
210
211
213 *Result.SourceManager,
214 Result.Context->getLangOpts());
217 "merge: can't resolve first token range to valid source range");
218 }
219 if (SecondRange->isTokenRange()) {
220
221
223 *Result.SourceManager,
224 Result.Context->getLangOpts());
227 "merge: can't resolve second token range to valid source range");
228 }
229
231 Result.SourceManager->isBeforeInTranslationUnit(FirstE, SecondE)
232 ? SecondE
233 : FirstE;
235 };
236}
237
241 if (!Node)
242 return Node.takeError();
245 M->getMemberNameInfo().getSourceRange());
246 return typeError(ID, Node->getNodeKind(), "MemberExpr");
247 };
248}
249
253 if (!N)
254 return N.takeError();
255 auto &Node = *N;
256 if (const auto *D = Node.get<NamedDecl>()) {
257 if (!D->getDeclName().isIdentifier())
261
262
263
264
265
267 if (Text != D->getName())
268 return llvm::make_error(
269 llvm::errc::not_supported,
270 "range selected by name(node id=" + ID + "): '" + Text +
271 "' is different from decl name '" + D->getName() + "'");
272 return R;
273 }
274 if (const auto *E = Node.get<DeclRefExpr>()) {
275 if (!E->getNameInfo().getName().isIdentifier())
279 }
281 if (!I->isMemberInitializer() && I->isWritten())
285 }
286 if (const auto *T = Node.get<TypeLoc>()) {
291 }
292 return typeError(ID, Node.getNodeKind(),
293 "DeclRefExpr, NamedDecl, CXXCtorInitializer, TypeLoc");
294 };
295}
296
297namespace {
298
299
300
301
302
303
304template <typename T, CharSourceRange (*Func)(const MatchResult &, const T &)>
305class RelativeSelector {
306 std::string ID;
307
308public:
309 RelativeSelector(std::string ID) : ID(std::move(ID)) {}
310
313 if (!N)
314 return N.takeError();
315 if (const auto *Arg = N->get<T>())
316 return Func(Result, *Arg);
317 return typeError(ID, N->getNodeKind());
318 }
319};
320}
321
322
323
324
325
326namespace {
327
332}
333}
334
336 return RelativeSelector<CompoundStmt, getStatementsRange>(std::move(ID));
337}
338
339namespace {
340
346}
347
348
349
353 for (int i = CE.getNumArgs() - 1; i >= 0; --i) {
356 continue;
358 }
359 return {};
360}
361
362
363CharSourceRange getCallArgumentsRange(const MatchResult &Result,
367 findArgStartDelimiter(CE, RLoc, *Result.SourceManager,
368 Result.Context->getLangOpts())
369 .getLocWithOffset(1),
370 RLoc);
371}
372
373
374
375CharSourceRange getConstructArgumentsRange(const MatchResult &Result,
380 Result.Context->getLangOpts()),
381 R.getEnd());
382 }
383
387 findLastArgEnd(CE, *Result.SourceManager,
388 Result.Context->getLangOpts()));
389 }
390
391 return {};
392}
393
394}
395
397 return RelativeSelector<CallExpr, getCallArgumentsRange>(std::move(ID));
398}
399
401 return RelativeSelector<CXXConstructExpr, getConstructArgumentsRange>(
402 std::move(ID));
403}
404
405namespace {
406
407
412}
413}
414
416 return RelativeSelector<InitListExpr, getElementsRange>(std::move(ID));
417}
418
419namespace {
420
424 tok::TokenKind::semi, *Result.Context);
425}
426}
427
429 return RelativeSelector<IfStmt, getElseRange>(std::move(ID));
430}
431
435 if (!SRange)
436 return SRange.takeError();
437 return Result.SourceManager->getExpansionRange(*SRange);
438 };
439}
static Error invalidArgumentError(Twine Message)
Definition RangeSelector.cpp:31
static SourceLocation findPreviousTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, tok::TokenKind TK)
Definition RangeSelector.cpp:78
static SourceLocation findPreviousTokenStart(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
Definition RangeSelector.cpp:63
static Error missingPropertyError(StringRef ID, Twine Description, StringRef Property)
Definition RangeSelector.cpp:47
static Error typeError(StringRef ID, const ASTNodeKind &Kind)
Definition RangeSelector.cpp:35
static Expected< DynTypedNode > getNode(const ast_matchers::BoundNodes &Nodes, StringRef ID)
Definition RangeSelector.cpp:53
Defines a combinator library supporting the definition of selectors, which select source ranges based...
Defines the clang::SourceLocation class and associated facilities.
Defines the clang::TypeLoc interface and its subclasses.
Represents a call to a C++ constructor.
SourceRange getParenOrBraceRange() const
Expr * getArg(unsigned Arg)
Return the specified argument.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents a C++ base or member initializer.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
SourceLocation getRParenLoc() const
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
static CharSourceRange getTokenRange(SourceRange R)
CompoundStmt - This represents a group of statements like { stmt stmt }.
SourceLocation getLBracLoc() const
SourceLocation getRBracLoc() const
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
IfStmt - This represents an if/then/else.
SourceLocation getElseLoc() const
SourceLocation getEndLoc() const LLVM_READONLY
Describes an C or C++ initializer list.
SourceLocation getLBraceLoc() const
SourceLocation getRBraceLoc() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static CharSourceRange makeFileCharRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Accepts a range and returns a character range with file locations.
static SourceLocation GetBeginningOfToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Given a location any where in a source buffer, find the location that corresponds to the beginning of...
static bool getRawToken(SourceLocation Loc, Token &Result, const SourceManager &SM, const LangOptions &LangOpts, bool IgnoreWhiteSpace=false)
Relex the token at the specified location.
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
This represents a decl that may have a name.
Smart pointer class that efficiently represents Objective-C method names.
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
Token - This structure provides full information about a lexed token.
Base wrapper for a particular "section" of type source info.
Maps string IDs to AST nodes matched by parts of a matcher.
const IDToNodeMap & getMap() const
Retrieve mapping from binding identifiers to bound nodes.
A class to allow finding matches over the Clang AST.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
RangeSelector initListElements(std::string ID)
Definition RangeSelector.cpp:415
RangeSelector enclose(RangeSelector Begin, RangeSelector End)
Selects from the start of Begin and to the end of End.
Definition RangeSelector.cpp:157
RangeSelector merge(RangeSelector First, RangeSelector Second)
Selects the merge of the two ranges, i.e.
Definition RangeSelector.cpp:181
RangeSelector member(std::string ID)
Given a MemberExpr, selects the member token. ID is the node's binding in the match result.
Definition RangeSelector.cpp:238
RangeSelector elseBranch(std::string ID)
Given an \IfStmt (bound to ID), selects the range of the else branch, starting from the else keyword.
Definition RangeSelector.cpp:428
RangeSelector node(std::string ID)
Selects a node, including trailing semicolon, if any (for declarations and non-expression statements)...
Definition RangeSelector.cpp:133
RangeSelector encloseNodes(std::string BeginID, std::string EndID)
Convenience version of range where end-points are bound nodes.
Definition RangeSelector.cpp:176
RangeSelector after(RangeSelector Selector)
Selects the point immediately following Selector.
Definition RangeSelector.cpp:107
RangeSelector constructExprArgs(std::string ID)
Definition RangeSelector.cpp:400
MatchConsumer< CharSourceRange > RangeSelector
RangeSelector callArgs(std::string ID)
Definition RangeSelector.cpp:396
RangeSelector before(RangeSelector Selector)
Selects the (empty) range [B,B) when Selector selects the range [B,E).
Definition RangeSelector.cpp:98
RangeSelector statement(std::string ID)
Selects a node, including trailing semicolon (always). Useful for selecting expression statements....
Definition RangeSelector.cpp:147
RangeSelector expansion(RangeSelector S)
Selects the range from which S was expanded (possibly along with other source), if S is an expansion,...
Definition RangeSelector.cpp:432
RangeSelector statements(std::string ID)
Definition RangeSelector.cpp:335
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
Definition RangeSelector.cpp:250
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
@ Result
The result type of a method or function.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
Contains all information for a given match.