diff options
| author | 2020-08-03 15:06:44 +0000 | |
|---|---|---|
| committer | 2020-08-03 15:06:44 +0000 | |
| commit | b64793999546ed8adebaeebd9d8345d18db8927d (patch) | |
| tree | 4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp | |
| parent | Add support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff) | |
| download | wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip | |
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp | 451 |
1 files changed, 0 insertions, 451 deletions
diff --git a/gnu/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp b/gnu/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp deleted file mode 100644 index b8f996d8218..00000000000 --- a/gnu/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp +++ /dev/null @@ -1,451 +0,0 @@ -//===--- ASTSelection.cpp - Clang refactoring library ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/Tooling/Refactoring/ASTSelection.h" -#include "clang/AST/LexicallyOrderedRecursiveASTVisitor.h" -#include "clang/Lex/Lexer.h" -#include "llvm/Support/SaveAndRestore.h" - -using namespace clang; -using namespace tooling; -using ast_type_traits::DynTypedNode; - -namespace { - -CharSourceRange getLexicalDeclRange(Decl *D, const SourceManager &SM, - const LangOptions &LangOpts) { - if (!isa<ObjCImplDecl>(D)) - return CharSourceRange::getTokenRange(D->getSourceRange()); - // Objective-C implementation declarations end at the '@' instead of the 'end' - // keyword. Use the lexer to find the location right after 'end'. - SourceRange R = D->getSourceRange(); - SourceLocation LocAfterEnd = Lexer::findLocationAfterToken( - R.getEnd(), tok::raw_identifier, SM, LangOpts, - /*SkipTrailingWhitespaceAndNewLine=*/false); - return LocAfterEnd.isValid() - ? CharSourceRange::getCharRange(R.getBegin(), LocAfterEnd) - : CharSourceRange::getTokenRange(R); -} - -/// Constructs the tree of selected AST nodes that either contain the location -/// of the cursor or overlap with the selection range. -class ASTSelectionFinder - : public LexicallyOrderedRecursiveASTVisitor<ASTSelectionFinder> { -public: - ASTSelectionFinder(SourceRange Selection, FileID TargetFile, - const ASTContext &Context) - : LexicallyOrderedRecursiveASTVisitor(Context.getSourceManager()), - SelectionBegin(Selection.getBegin()), - SelectionEnd(Selection.getBegin() == Selection.getEnd() - ? SourceLocation() - : Selection.getEnd()), - TargetFile(TargetFile), Context(Context) { - // The TU decl is the root of the selected node tree. - SelectionStack.push_back( - SelectedASTNode(DynTypedNode::create(*Context.getTranslationUnitDecl()), - SourceSelectionKind::None)); - } - - Optional<SelectedASTNode> getSelectedASTNode() { - assert(SelectionStack.size() == 1 && "stack was not popped"); - SelectedASTNode Result = std::move(SelectionStack.back()); - SelectionStack.pop_back(); - if (Result.Children.empty()) - return None; - return std::move(Result); - } - - bool TraversePseudoObjectExpr(PseudoObjectExpr *E) { - // Avoid traversing the semantic expressions. They should be handled by - // looking through the appropriate opaque expressions in order to build - // a meaningful selection tree. - llvm::SaveAndRestore<bool> LookThrough(LookThroughOpaqueValueExprs, true); - return TraverseStmt(E->getSyntacticForm()); - } - - bool TraverseOpaqueValueExpr(OpaqueValueExpr *E) { - if (!LookThroughOpaqueValueExprs) - return true; - llvm::SaveAndRestore<bool> LookThrough(LookThroughOpaqueValueExprs, false); - return TraverseStmt(E->getSourceExpr()); - } - - bool TraverseDecl(Decl *D) { - if (isa<TranslationUnitDecl>(D)) - return LexicallyOrderedRecursiveASTVisitor::TraverseDecl(D); - if (D->isImplicit()) - return true; - - // Check if this declaration is written in the file of interest. - const SourceRange DeclRange = D->getSourceRange(); - const SourceManager &SM = Context.getSourceManager(); - SourceLocation FileLoc; - if (DeclRange.getBegin().isMacroID() && !DeclRange.getEnd().isMacroID()) - FileLoc = DeclRange.getEnd(); - else - FileLoc = SM.getSpellingLoc(DeclRange.getBegin()); - if (SM.getFileID(FileLoc) != TargetFile) - return true; - - SourceSelectionKind SelectionKind = - selectionKindFor(getLexicalDeclRange(D, SM, Context.getLangOpts())); - SelectionStack.push_back( - SelectedASTNode(DynTypedNode::create(*D), SelectionKind)); - LexicallyOrderedRecursiveASTVisitor::TraverseDecl(D); - popAndAddToSelectionIfSelected(SelectionKind); - - if (DeclRange.getEnd().isValid() && - SM.isBeforeInTranslationUnit(SelectionEnd.isValid() ? SelectionEnd - : SelectionBegin, - DeclRange.getEnd())) { - // Stop early when we've reached a declaration after the selection. - return false; - } - return true; - } - - bool TraverseStmt(Stmt *S) { - if (!S) - return true; - if (auto *Opaque = dyn_cast<OpaqueValueExpr>(S)) - return TraverseOpaqueValueExpr(Opaque); - // Avoid selecting implicit 'this' expressions. - if (auto *TE = dyn_cast<CXXThisExpr>(S)) { - if (TE->isImplicit()) - return true; - } - // FIXME (Alex Lorenz): Improve handling for macro locations. - SourceSelectionKind SelectionKind = - selectionKindFor(CharSourceRange::getTokenRange(S->getSourceRange())); - SelectionStack.push_back( - SelectedASTNode(DynTypedNode::create(*S), SelectionKind)); - LexicallyOrderedRecursiveASTVisitor::TraverseStmt(S); - popAndAddToSelectionIfSelected(SelectionKind); - return true; - } - -private: - void popAndAddToSelectionIfSelected(SourceSelectionKind SelectionKind) { - SelectedASTNode Node = std::move(SelectionStack.back()); - SelectionStack.pop_back(); - if (SelectionKind != SourceSelectionKind::None || !Node.Children.empty()) - SelectionStack.back().Children.push_back(std::move(Node)); - } - - SourceSelectionKind selectionKindFor(CharSourceRange Range) { - SourceLocation End = Range.getEnd(); - const SourceManager &SM = Context.getSourceManager(); - if (Range.isTokenRange()) - End = Lexer::getLocForEndOfToken(End, 0, SM, Context.getLangOpts()); - if (!SourceLocation::isPairOfFileLocations(Range.getBegin(), End)) - return SourceSelectionKind::None; - if (!SelectionEnd.isValid()) { - // Do a quick check when the selection is of length 0. - if (SM.isPointWithin(SelectionBegin, Range.getBegin(), End)) - return SourceSelectionKind::ContainsSelection; - return SourceSelectionKind::None; - } - bool HasStart = SM.isPointWithin(SelectionBegin, Range.getBegin(), End); - bool HasEnd = SM.isPointWithin(SelectionEnd, Range.getBegin(), End); - if (HasStart && HasEnd) - return SourceSelectionKind::ContainsSelection; - if (SM.isPointWithin(Range.getBegin(), SelectionBegin, SelectionEnd) && - SM.isPointWithin(End, SelectionBegin, SelectionEnd)) - return SourceSelectionKind::InsideSelection; - // Ensure there's at least some overlap with the 'start'/'end' selection - // types. - if (HasStart && SelectionBegin != End) - return SourceSelectionKind::ContainsSelectionStart; - if (HasEnd && SelectionEnd != Range.getBegin()) - return SourceSelectionKind::ContainsSelectionEnd; - - return SourceSelectionKind::None; - } - - const SourceLocation SelectionBegin, SelectionEnd; - FileID TargetFile; - const ASTContext &Context; - std::vector<SelectedASTNode> SelectionStack; - /// Controls whether we can traverse through the OpaqueValueExpr. This is - /// typically enabled during the traversal of syntactic form for - /// PseudoObjectExprs. - bool LookThroughOpaqueValueExprs = false; -}; - -} // end anonymous namespace - -Optional<SelectedASTNode> -clang::tooling::findSelectedASTNodes(const ASTContext &Context, - SourceRange SelectionRange) { - assert(SelectionRange.isValid() && - SourceLocation::isPairOfFileLocations(SelectionRange.getBegin(), - SelectionRange.getEnd()) && - "Expected a file range"); - FileID TargetFile = - Context.getSourceManager().getFileID(SelectionRange.getBegin()); - assert(Context.getSourceManager().getFileID(SelectionRange.getEnd()) == - TargetFile && - "selection range must span one file"); - - ASTSelectionFinder Visitor(SelectionRange, TargetFile, Context); - Visitor.TraverseDecl(Context.getTranslationUnitDecl()); - return Visitor.getSelectedASTNode(); -} - -static const char *selectionKindToString(SourceSelectionKind Kind) { - switch (Kind) { - case SourceSelectionKind::None: - return "none"; - case SourceSelectionKind::ContainsSelection: - return "contains-selection"; - case SourceSelectionKind::ContainsSelectionStart: - return "contains-selection-start"; - case SourceSelectionKind::ContainsSelectionEnd: - return "contains-selection-end"; - case SourceSelectionKind::InsideSelection: - return "inside"; - } - llvm_unreachable("invalid selection kind"); -} - -static void dump(const SelectedASTNode &Node, llvm::raw_ostream &OS, - unsigned Indent = 0) { - OS.indent(Indent * 2); - if (const Decl *D = Node.Node.get<Decl>()) { - OS << D->getDeclKindName() << "Decl"; - if (const auto *ND = dyn_cast<NamedDecl>(D)) - OS << " \"" << ND->getNameAsString() << '"'; - } else if (const Stmt *S = Node.Node.get<Stmt>()) { - OS << S->getStmtClassName(); - } - OS << ' ' << selectionKindToString(Node.SelectionKind) << "\n"; - for (const auto &Child : Node.Children) - dump(Child, OS, Indent + 1); -} - -void SelectedASTNode::dump(llvm::raw_ostream &OS) const { ::dump(*this, OS); } - -/// Returns true if the given node has any direct children with the following -/// selection kind. -/// -/// Note: The direct children also include children of direct children with the -/// "None" selection kind. -static bool hasAnyDirectChildrenWithKind(const SelectedASTNode &Node, - SourceSelectionKind Kind) { - assert(Kind != SourceSelectionKind::None && "invalid predicate!"); - for (const auto &Child : Node.Children) { - if (Child.SelectionKind == Kind) - return true; - if (Child.SelectionKind == SourceSelectionKind::None) - return hasAnyDirectChildrenWithKind(Child, Kind); - } - return false; -} - -namespace { -struct SelectedNodeWithParents { - SelectedASTNode::ReferenceType Node; - llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents; - - /// Canonicalizes the given selection by selecting different related AST nodes - /// when it makes sense to do so. - void canonicalize(); -}; - -enum SelectionCanonicalizationAction { KeepSelection, SelectParent }; - -/// Returns the canonicalization action which should be applied to the -/// selected statement. -SelectionCanonicalizationAction -getSelectionCanonizalizationAction(const Stmt *S, const Stmt *Parent) { - // Select the parent expression when: - // - The string literal in ObjC string literal is selected, e.g.: - // @"test" becomes @"test" - // ~~~~~~ ~~~~~~~ - if (isa<StringLiteral>(S) && isa<ObjCStringLiteral>(Parent)) - return SelectParent; - // The entire call should be selected when just the member expression - // that refers to the method or the decl ref that refers to the function - // is selected. - // f.call(args) becomes f.call(args) - // ~~~~ ~~~~~~~~~~~~ - // func(args) becomes func(args) - // ~~~~ ~~~~~~~~~~ - else if (const auto *CE = dyn_cast<CallExpr>(Parent)) { - if ((isa<MemberExpr>(S) || isa<DeclRefExpr>(S)) && - CE->getCallee()->IgnoreImpCasts() == S) - return SelectParent; - } - // FIXME: Syntactic form -> Entire pseudo-object expr. - return KeepSelection; -} - -} // end anonymous namespace - -void SelectedNodeWithParents::canonicalize() { - const Stmt *S = Node.get().Node.get<Stmt>(); - assert(S && "non statement selection!"); - const Stmt *Parent = Parents[Parents.size() - 1].get().Node.get<Stmt>(); - if (!Parent) - return; - - // Look through the implicit casts in the parents. - unsigned ParentIndex = 1; - for (; (ParentIndex + 1) <= Parents.size() && isa<ImplicitCastExpr>(Parent); - ++ParentIndex) { - const Stmt *NewParent = - Parents[Parents.size() - ParentIndex - 1].get().Node.get<Stmt>(); - if (!NewParent) - break; - Parent = NewParent; - } - - switch (getSelectionCanonizalizationAction(S, Parent)) { - case SelectParent: - Node = Parents[Parents.size() - ParentIndex]; - for (; ParentIndex != 0; --ParentIndex) - Parents.pop_back(); - break; - case KeepSelection: - break; - } -} - -/// Finds the set of bottom-most selected AST nodes that are in the selection -/// tree with the specified selection kind. -/// -/// For example, given the following selection tree: -/// -/// FunctionDecl "f" contains-selection -/// CompoundStmt contains-selection [#1] -/// CallExpr inside -/// ImplicitCastExpr inside -/// DeclRefExpr inside -/// IntegerLiteral inside -/// IntegerLiteral inside -/// FunctionDecl "f2" contains-selection -/// CompoundStmt contains-selection [#2] -/// CallExpr inside -/// ImplicitCastExpr inside -/// DeclRefExpr inside -/// IntegerLiteral inside -/// IntegerLiteral inside -/// -/// This function will find references to nodes #1 and #2 when searching for the -/// \c ContainsSelection kind. -static void findDeepestWithKind( - const SelectedASTNode &ASTSelection, - llvm::SmallVectorImpl<SelectedNodeWithParents> &MatchingNodes, - SourceSelectionKind Kind, - llvm::SmallVectorImpl<SelectedASTNode::ReferenceType> &ParentStack) { - if (ASTSelection.Node.get<DeclStmt>()) { - // Select the entire decl stmt when any of its child declarations is the - // bottom-most. - for (const auto &Child : ASTSelection.Children) { - if (!hasAnyDirectChildrenWithKind(Child, Kind)) { - MatchingNodes.push_back(SelectedNodeWithParents{ - std::cref(ASTSelection), {ParentStack.begin(), ParentStack.end()}}); - return; - } - } - } else { - if (!hasAnyDirectChildrenWithKind(ASTSelection, Kind)) { - // This node is the bottom-most. - MatchingNodes.push_back(SelectedNodeWithParents{ - std::cref(ASTSelection), {ParentStack.begin(), ParentStack.end()}}); - return; - } - } - // Search in the children. - ParentStack.push_back(std::cref(ASTSelection)); - for (const auto &Child : ASTSelection.Children) - findDeepestWithKind(Child, MatchingNodes, Kind, ParentStack); - ParentStack.pop_back(); -} - -static void findDeepestWithKind( - const SelectedASTNode &ASTSelection, - llvm::SmallVectorImpl<SelectedNodeWithParents> &MatchingNodes, - SourceSelectionKind Kind) { - llvm::SmallVector<SelectedASTNode::ReferenceType, 16> ParentStack; - findDeepestWithKind(ASTSelection, MatchingNodes, Kind, ParentStack); -} - -Optional<CodeRangeASTSelection> -CodeRangeASTSelection::create(SourceRange SelectionRange, - const SelectedASTNode &ASTSelection) { - // Code range is selected when the selection range is not empty. - if (SelectionRange.getBegin() == SelectionRange.getEnd()) - return None; - llvm::SmallVector<SelectedNodeWithParents, 4> ContainSelection; - findDeepestWithKind(ASTSelection, ContainSelection, - SourceSelectionKind::ContainsSelection); - // We are looking for a selection in one body of code, so let's focus on - // one matching result. - if (ContainSelection.size() != 1) - return None; - SelectedNodeWithParents &Selected = ContainSelection[0]; - if (!Selected.Node.get().Node.get<Stmt>()) - return None; - const Stmt *CodeRangeStmt = Selected.Node.get().Node.get<Stmt>(); - if (!isa<CompoundStmt>(CodeRangeStmt)) { - Selected.canonicalize(); - return CodeRangeASTSelection(Selected.Node, Selected.Parents, - /*AreChildrenSelected=*/false); - } - // FIXME (Alex L): First selected SwitchCase means that first case statement. - // is selected actually - // (See https://github.com/apple/swift-clang & CompoundStmtRange). - - // FIXME (Alex L): Tweak selection rules for compound statements, see: - // https://github.com/apple/swift-clang/blob/swift-4.1-branch/lib/Tooling/ - // Refactor/ASTSlice.cpp#L513 - // The user selected multiple statements in a compound statement. - Selected.Parents.push_back(Selected.Node); - return CodeRangeASTSelection(Selected.Node, Selected.Parents, - /*AreChildrenSelected=*/true); -} - -static bool isFunctionLikeDeclaration(const Decl *D) { - // FIXME (Alex L): Test for BlockDecl. - return isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D); -} - -bool CodeRangeASTSelection::isInFunctionLikeBodyOfCode() const { - bool IsPrevCompound = false; - // Scan through the parents (bottom-to-top) and check if the selection is - // contained in a compound statement that's a body of a function/method - // declaration. - for (const auto &Parent : llvm::reverse(Parents)) { - const DynTypedNode &Node = Parent.get().Node; - if (const auto *D = Node.get<Decl>()) { - if (isFunctionLikeDeclaration(D)) - return IsPrevCompound; - // Stop the search at any type declaration to avoid returning true for - // expressions in type declarations in functions, like: - // function foo() { struct X { - // int m = /*selection:*/ 1 + 2 /*selection end*/; }; }; - if (isa<TypeDecl>(D)) - return false; - } - IsPrevCompound = Node.get<CompoundStmt>() != nullptr; - } - return false; -} - -const Decl *CodeRangeASTSelection::getFunctionLikeNearestParent() const { - for (const auto &Parent : llvm::reverse(Parents)) { - const DynTypedNode &Node = Parent.get().Node; - if (const auto *D = Node.get<Decl>()) { - if (isFunctionLikeDeclaration(D)) - return D; - } - } - return nullptr; -} |
