1 //===--- LocateSymbol.cpp - Find locations providing a symbol -------------===//
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-exception
7 //===----------------------------------------------------------------------===//
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"
20 namespace clang::include_cleaner
{
23 template <typename T
> Hints
completeIfDefinition(T
*D
) {
24 return D
->isThisDeclarationADefinition() ? Hints::CompleteSymbol
28 Hints
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
;
40 std::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 a
46 // library. Some useful signals could be derived by checking the DeclContext.
47 // Most incidental forward decls look like:
49 // class SourceManager; // likely an incidental forward decl.
50 // namespace my_own_ns {}
52 for (auto *Redecl
: D
.redecls())
53 Result
.push_back({Redecl
->getLocation(), declHints(Redecl
)});
57 std::vector
<Hinted
<SymbolLocation
>> locateMacro(const Macro
&M
) {
58 // FIXME: Should we also provide physical locations?
59 if (auto SS
= tooling::stdlib::Symbol::named("", M
.Name
->getName()))
60 return {{*SS
, Hints::CompleteSymbol
}};
61 return {{M
.Definition
, Hints::CompleteSymbol
}};
65 std::vector
<Hinted
<SymbolLocation
>> locateSymbol(const Symbol
&S
) {
67 case Symbol::Declaration
:
68 return locateDecl(S
.declaration());
70 return locateMacro(S
.macro());
72 llvm_unreachable("Unknown Symbol::Kind enum");
75 } // namespace clang::include_cleaner