13 #include "llvm/Support/SaveAndRestore.h" 15 using namespace clang;
16 using namespace tooling;
23 if (!isa<ObjCImplDecl>(D))
29 R.getEnd(), tok::raw_identifier,
SM, LangOpts,
38 class ASTSelectionFinder
44 SelectionBegin(Selection.getBegin()),
45 SelectionEnd(Selection.getBegin() == Selection.getEnd()
47 : Selection.getEnd()),
48 TargetFile(TargetFile), Context(Context) {
50 SelectionStack.push_back(
56 assert(SelectionStack.size() == 1 &&
"stack was not popped");
58 SelectionStack.pop_back();
59 if (Result.Children.empty())
61 return std::move(Result);
73 if (!LookThroughOpaqueValueExprs)
79 bool TraverseDecl(
Decl *D) {
80 if (isa<TranslationUnitDecl>(D))
90 FileLoc = DeclRange.
getEnd();
97 selectionKindFor(getLexicalDeclRange(D, SM, Context.
getLangOpts()));
98 SelectionStack.push_back(
101 popAndAddToSelectionIfSelected(SelectionKind);
113 bool TraverseStmt(
Stmt *S) {
116 if (
auto *Opaque = dyn_cast<OpaqueValueExpr>(S))
117 return TraverseOpaqueValueExpr(Opaque);
119 if (
auto *TE = dyn_cast<CXXThisExpr>(S)) {
120 if (TE->isImplicit())
126 SelectionStack.push_back(
129 popAndAddToSelectionIfSelected(SelectionKind);
136 SelectionStack.pop_back();
138 SelectionStack.back().Children.push_back(std::move(Node));
148 if (!SelectionEnd.isValid()) {
156 if (HasStart && HasEnd)
163 if (HasStart && SelectionBegin != End)
165 if (HasEnd && SelectionEnd != Range.
getBegin())
174 std::vector<SelectedASTNode> SelectionStack;
178 bool LookThroughOpaqueValueExprs =
false;
186 assert(SelectionRange.
isValid() &&
188 SelectionRange.
getEnd()) &&
189 "Expected a file range");
194 "selection range must span one file");
196 ASTSelectionFinder Visitor(SelectionRange, TargetFile, Context);
198 return Visitor.getSelectedASTNode();
206 return "contains-selection";
208 return "contains-selection-start";
210 return "contains-selection-end";
214 llvm_unreachable(
"invalid selection kind");
218 unsigned Indent = 0) {
219 OS.indent(Indent * 2);
222 if (
const auto *ND = dyn_cast<NamedDecl>(D))
223 OS <<
" \"" << ND->getNameAsString() <<
'"';
228 for (
const auto &Child : Node.
Children)
229 dump(Child, OS, Indent + 1);
242 for (
const auto &Child : Node.
Children) {
243 if (Child.SelectionKind == Kind)
252 struct SelectedNodeWithParents {
266 getSelectionCanonizalizationAction(
const Stmt *S,
const Stmt *
Parent) {
271 if (isa<StringLiteral>(S) && isa<ObjCStringLiteral>(Parent))
280 else if (
const auto *CE = dyn_cast<CallExpr>(Parent)) {
281 if ((isa<MemberExpr>(S) || isa<DeclRefExpr>(S)) &&
282 CE->getCallee()->IgnoreImpCasts() == S)
286 return KeepSelection;
291 void SelectedNodeWithParents::canonicalize() {
293 assert(S &&
"non statement selection!");
294 const Stmt *
Parent = Parents[Parents.size() - 1].get().Node.get<
Stmt>();
299 unsigned ParentIndex = 1;
300 for (; (ParentIndex + 1) <= Parents.size() && isa<ImplicitCastExpr>(
Parent);
302 const Stmt *NewParent =
303 Parents[Parents.size() - ParentIndex - 1].get().Node.get<
Stmt>();
309 switch (getSelectionCanonizalizationAction(S, Parent)) {
311 Node = Parents[Parents.size() - ParentIndex];
312 for (; ParentIndex != 0; --ParentIndex)
350 for (
const auto &Child : ASTSelection.
Children) {
352 MatchingNodes.push_back(SelectedNodeWithParents{
353 std::cref(ASTSelection), {ParentStack.begin(), ParentStack.end()}});
360 MatchingNodes.push_back(SelectedNodeWithParents{
361 std::cref(ASTSelection), {ParentStack.begin(), ParentStack.end()}});
366 ParentStack.push_back(std::cref(ASTSelection));
367 for (
const auto &Child : ASTSelection.
Children)
369 ParentStack.pop_back();
391 if (ContainSelection.size() != 1)
393 SelectedNodeWithParents &Selected = ContainSelection[0];
394 if (!Selected.Node.get().Node.get<
Stmt>())
396 const Stmt *CodeRangeStmt = Selected.Node.get().Node.get<
Stmt>();
397 if (!isa<CompoundStmt>(CodeRangeStmt)) {
398 Selected.canonicalize();
410 Selected.Parents.push_back(Selected.Node);
417 return isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D);
421 bool IsPrevCompound =
false;
425 for (
const auto &
Parent : llvm::reverse(Parents)) {
427 if (
const auto *D = Node.
get<
Decl>()) {
429 return IsPrevCompound;
434 if (isa<TypeDecl>(D))
443 for (
const auto &
Parent : llvm::reverse(Parents)) {
445 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...
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)