12 #include "llvm/Support/SaveAndRestore.h" 14 using namespace clang;
15 using namespace tooling;
22 if (!isa<ObjCImplDecl>(D))
28 R.getEnd(), tok::raw_identifier,
SM, LangOpts,
37 class ASTSelectionFinder
43 SelectionBegin(Selection.getBegin()),
44 SelectionEnd(Selection.getBegin() == Selection.getEnd()
46 : Selection.getEnd()),
47 TargetFile(TargetFile), Context(Context) {
49 SelectionStack.push_back(
55 assert(SelectionStack.size() == 1 &&
"stack was not popped");
57 SelectionStack.pop_back();
58 if (Result.Children.empty())
60 return std::move(Result);
72 if (!LookThroughOpaqueValueExprs)
78 bool TraverseDecl(
Decl *D) {
79 if (isa<TranslationUnitDecl>(D))
89 FileLoc = DeclRange.
getEnd();
96 selectionKindFor(getLexicalDeclRange(D, SM, Context.
getLangOpts()));
97 SelectionStack.push_back(
100 popAndAddToSelectionIfSelected(SelectionKind);
112 bool TraverseStmt(
Stmt *S) {
115 if (
auto *Opaque = dyn_cast<OpaqueValueExpr>(S))
116 return TraverseOpaqueValueExpr(Opaque);
118 if (
auto *TE = dyn_cast<CXXThisExpr>(S)) {
119 if (TE->isImplicit())
125 SelectionStack.push_back(
128 popAndAddToSelectionIfSelected(SelectionKind);
135 SelectionStack.pop_back();
137 SelectionStack.back().Children.push_back(std::move(Node));
147 if (!SelectionEnd.isValid()) {
155 if (HasStart && HasEnd)
162 if (HasStart && SelectionBegin != End)
164 if (HasEnd && SelectionEnd != Range.
getBegin())
173 std::vector<SelectedASTNode> SelectionStack;
177 bool LookThroughOpaqueValueExprs =
false;
185 assert(SelectionRange.
isValid() &&
187 SelectionRange.
getEnd()) &&
188 "Expected a file range");
193 "selection range must span one file");
195 ASTSelectionFinder Visitor(SelectionRange, TargetFile, Context);
197 return Visitor.getSelectedASTNode();
205 return "contains-selection";
207 return "contains-selection-start";
209 return "contains-selection-end";
213 llvm_unreachable(
"invalid selection kind");
221 if (
const auto *ND = dyn_cast<NamedDecl>(D))
222 OS <<
" \"" << ND->getNameAsString() <<
'"';
227 for (
const auto &Child : Node.
Children)
241 for (
const auto &Child : Node.
Children) {
242 if (Child.SelectionKind == Kind)
251 struct SelectedNodeWithParents {
265 getSelectionCanonizalizationAction(
const Stmt *S,
const Stmt *
Parent) {
270 if (isa<StringLiteral>(S) && isa<ObjCStringLiteral>(Parent))
279 else if (
const auto *CE = dyn_cast<CallExpr>(Parent)) {
280 if ((isa<MemberExpr>(S) || isa<DeclRefExpr>(S)) &&
281 CE->getCallee()->IgnoreImpCasts() == S)
285 return KeepSelection;
290 void SelectedNodeWithParents::canonicalize() {
292 assert(S &&
"non statement selection!");
293 const Stmt *
Parent = Parents[Parents.size() - 1].get().Node.get<
Stmt>();
298 unsigned ParentIndex = 1;
299 for (; (ParentIndex + 1) <= Parents.size() && isa<ImplicitCastExpr>(
Parent);
301 const Stmt *NewParent =
302 Parents[Parents.size() - ParentIndex - 1].get().Node.get<
Stmt>();
308 switch (getSelectionCanonizalizationAction(S, Parent)) {
310 Node = Parents[Parents.size() - ParentIndex];
311 for (; ParentIndex != 0; --ParentIndex)
349 for (
const auto &Child : ASTSelection.
Children) {
351 MatchingNodes.push_back(SelectedNodeWithParents{
352 std::cref(ASTSelection), {ParentStack.begin(), ParentStack.end()}});
359 MatchingNodes.push_back(SelectedNodeWithParents{
360 std::cref(ASTSelection), {ParentStack.begin(), ParentStack.end()}});
365 ParentStack.push_back(std::cref(ASTSelection));
366 for (
const auto &Child : ASTSelection.
Children)
368 ParentStack.pop_back();
390 if (ContainSelection.size() != 1)
392 SelectedNodeWithParents &Selected = ContainSelection[0];
393 if (!Selected.Node.get().Node.get<
Stmt>())
395 const Stmt *CodeRangeStmt = Selected.Node.get().Node.get<
Stmt>();
396 if (!isa<CompoundStmt>(CodeRangeStmt)) {
397 Selected.canonicalize();
409 Selected.Parents.push_back(Selected.Node);
416 return isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D);
420 bool IsPrevCompound =
false;
424 for (
const auto &
Parent : llvm::reverse(Parents)) {
426 if (
const auto *D = Node.
get<
Decl>()) {
428 return IsPrevCompound;
433 if (isa<TypeDecl>(D))
442 for (
const auto &
Parent : llvm::reverse(Parents)) {
444 if (
const auto *D = Node.
get<
Decl>()) {
Expr * getSyntacticForm()
Return the syntactic form of this expression, i.e.
const char * getDeclKindName() const
static void findDeepestWithKind(const SelectedASTNode &ASTSelection, llvm::SmallVectorImpl< SelectedNodeWithParents > &MatchingNodes, SourceSelectionKind Kind, llvm::SmallVectorImpl< SelectedASTNode::ReferenceType > &ParentStack)
Finds the set of bottom-most selected AST nodes that are in the selection tree with the specified sel...
static void dump(const SelectedASTNode &Node, llvm::raw_ostream &OS, unsigned Indent=0)
Stmt - This represents one statement.
static CharSourceRange getTokenRange(SourceRange R)
const T * get() const
Retrieve the stored node as type T.
Decl - This represents one declaration (or definition), e.g.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
const char * getStmtClassName() const
SourceLocation getBegin() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
CompoundStmt - This represents a group of statements like { stmt stmt }.
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.
Represents a character-granular source range.
static SourceLocation findLocationAfterToken(SourceLocation loc, tok::TokenKind TKind, const SourceManager &SM, const LangOptions &LangOpts, bool SkipTrailingWhitespaceAndNewLine)
Checks that the given token is the first token that occurs after the given location (this excludes co...
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getEnd() const
static CharSourceRange getCharRange(SourceRange R)
static bool hasAnyDirectChildrenWithKind(const SelectedASTNode &Node, SourceSelectionKind Kind)
Returns true if the given node has any direct children with the following selection kind...
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Encodes a location in the source.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument's dy...
A RecursiveASTVisitor subclass that guarantees that AST traversal is performed in a lexical order (i...
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
ast_type_traits::DynTypedNode DynTypedNode
ast_type_traits::DynTypedNode Node
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Dataflow Directional Tag Classes.
static bool isPairOfFileLocations(SourceLocation Start, SourceLocation End)
bool isValid() const
Return true if this is a valid SourceLocation object.
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
static bool isFunctionLikeDeclaration(const Decl *D)
A dynamically typed AST node container.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
SourceLocation getEnd() const
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
bool isPointWithin(SourceLocation Location, SourceLocation Start, SourceLocation End) const
Return true if the Point is within Start and End.
SelectionCanonicalizationAction
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
This class handles loading and caching of source files into memory.
static const char * selectionKindToString(SourceSelectionKind Kind)