80 lines · cpp
1//===--- LocateSymbol.cpp - Find locations providing a symbol -------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "AnalysisInternal.h"10#include "clang-include-cleaner/Types.h"11#include "clang/AST/Decl.h"12#include "clang/AST/DeclBase.h"13#include "clang/AST/DeclCXX.h"14#include "clang/AST/DeclTemplate.h"15#include "clang/Tooling/Inclusions/StandardLibrary.h"16#include "llvm/Support/Casting.h"17#include <utility>18#include <vector>19 20namespace clang::include_cleaner {21namespace {22 23template <typename T> Hints completeIfDefinition(T *D) {24 return D->isThisDeclarationADefinition() ? Hints::CompleteSymbol25 : Hints::None;26}27 28Hints declHints(const Decl *D) {29 // Definition is only needed for classes and templates for completeness.30 if (auto *TD = llvm::dyn_cast<TagDecl>(D))31 return completeIfDefinition(TD);32 else if (auto *CTD = llvm::dyn_cast<ClassTemplateDecl>(D))33 return completeIfDefinition(CTD);34 else if (auto *FTD = llvm::dyn_cast<FunctionTemplateDecl>(D))35 return completeIfDefinition(FTD);36 // Any other declaration is assumed usable.37 return Hints::CompleteSymbol;38}39 40std::vector<Hinted<SymbolLocation>> locateDecl(const Decl &D) {41 std::vector<Hinted<SymbolLocation>> Result;42 // FIXME: Should we also provide physical locations?43 if (auto SS = tooling::stdlib::Recognizer()(&D))44 return {{*SS, Hints::CompleteSymbol}};45 // FIXME: Signal foreign decls, e.g. a forward declaration not owned by a46 // library. Some useful signals could be derived by checking the DeclContext.47 // Most incidental forward decls look like:48 // namespace clang {49 // class SourceManager; // likely an incidental forward decl.50 // namespace my_own_ns {}51 // }52 for (auto *Redecl : D.redecls())53 Result.push_back({Redecl->getLocation(), declHints(Redecl)});54 return Result;55}56 57std::vector<Hinted<SymbolLocation>> locateMacro(const Macro &M,58 const tooling::stdlib::Lang L) {59 // FIXME: Should we also provide physical locations?60 if (auto SS = tooling::stdlib::Symbol::named("", M.Name->getName(), L))61 return {{*SS, Hints::CompleteSymbol}};62 return {{M.Definition, Hints::CompleteSymbol}};63}64} // namespace65 66std::vector<Hinted<SymbolLocation>> locateSymbol(const Symbol &S,67 const LangOptions &LO) {68 const auto L = !LO.CPlusPlus && LO.C99 ? tooling::stdlib::Lang::C69 : tooling::stdlib::Lang::CXX;70 switch (S.kind()) {71 case Symbol::Declaration:72 return locateDecl(S.declaration());73 case Symbol::Macro:74 return locateMacro(S.macro(), L);75 }76 llvm_unreachable("Unknown Symbol::Kind enum");77}78 79} // namespace clang::include_cleaner80