annotate clang-tools-extra/clangd/AST.cpp @ 207:2e18cbf3894f

LLVM12
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 08 Jun 2021 06:07:14 +0900
parents 0572611fdcc8
children c4bab56944e8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===--- AST.cpp - Utility AST functions -----------------------*- C++ -*-===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 #include "AST.h"
anatofuz
parents:
diff changeset
10
anatofuz
parents:
diff changeset
11 #include "FindTarget.h"
anatofuz
parents:
diff changeset
12 #include "SourceCode.h"
anatofuz
parents:
diff changeset
13 #include "clang/AST/ASTContext.h"
anatofuz
parents:
diff changeset
14 #include "clang/AST/ASTTypeTraits.h"
anatofuz
parents:
diff changeset
15 #include "clang/AST/Decl.h"
anatofuz
parents:
diff changeset
16 #include "clang/AST/DeclBase.h"
anatofuz
parents:
diff changeset
17 #include "clang/AST/DeclCXX.h"
anatofuz
parents:
diff changeset
18 #include "clang/AST/DeclTemplate.h"
anatofuz
parents:
diff changeset
19 #include "clang/AST/DeclarationName.h"
anatofuz
parents:
diff changeset
20 #include "clang/AST/NestedNameSpecifier.h"
anatofuz
parents:
diff changeset
21 #include "clang/AST/PrettyPrinter.h"
anatofuz
parents:
diff changeset
22 #include "clang/AST/RecursiveASTVisitor.h"
anatofuz
parents:
diff changeset
23 #include "clang/AST/TemplateBase.h"
anatofuz
parents:
diff changeset
24 #include "clang/Basic/SourceLocation.h"
anatofuz
parents:
diff changeset
25 #include "clang/Basic/SourceManager.h"
anatofuz
parents:
diff changeset
26 #include "clang/Basic/Specifiers.h"
anatofuz
parents:
diff changeset
27 #include "clang/Index/USRGeneration.h"
anatofuz
parents:
diff changeset
28 #include "llvm/ADT/ArrayRef.h"
anatofuz
parents:
diff changeset
29 #include "llvm/ADT/Optional.h"
anatofuz
parents:
diff changeset
30 #include "llvm/ADT/STLExtras.h"
anatofuz
parents:
diff changeset
31 #include "llvm/ADT/StringRef.h"
anatofuz
parents:
diff changeset
32 #include "llvm/Support/Casting.h"
anatofuz
parents:
diff changeset
33 #include "llvm/Support/ScopedPrinter.h"
anatofuz
parents:
diff changeset
34 #include "llvm/Support/raw_ostream.h"
anatofuz
parents:
diff changeset
35 #include <string>
anatofuz
parents:
diff changeset
36 #include <vector>
anatofuz
parents:
diff changeset
37
anatofuz
parents:
diff changeset
38 namespace clang {
anatofuz
parents:
diff changeset
39 namespace clangd {
anatofuz
parents:
diff changeset
40
anatofuz
parents:
diff changeset
41 namespace {
anatofuz
parents:
diff changeset
42 llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>>
anatofuz
parents:
diff changeset
43 getTemplateSpecializationArgLocs(const NamedDecl &ND) {
anatofuz
parents:
diff changeset
44 if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) {
anatofuz
parents:
diff changeset
45 if (const ASTTemplateArgumentListInfo *Args =
anatofuz
parents:
diff changeset
46 Func->getTemplateSpecializationArgsAsWritten())
anatofuz
parents:
diff changeset
47 return Args->arguments();
anatofuz
parents:
diff changeset
48 } else if (auto *Cls =
anatofuz
parents:
diff changeset
49 llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) {
anatofuz
parents:
diff changeset
50 if (auto *Args = Cls->getTemplateArgsAsWritten())
anatofuz
parents:
diff changeset
51 return Args->arguments();
anatofuz
parents:
diff changeset
52 } else if (auto *Var =
anatofuz
parents:
diff changeset
53 llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) {
anatofuz
parents:
diff changeset
54 if (auto *Args = Var->getTemplateArgsAsWritten())
anatofuz
parents:
diff changeset
55 return Args->arguments();
anatofuz
parents:
diff changeset
56 } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND))
anatofuz
parents:
diff changeset
57 return Var->getTemplateArgsInfo().arguments();
anatofuz
parents:
diff changeset
58 // We return None for ClassTemplateSpecializationDecls because it does not
anatofuz
parents:
diff changeset
59 // contain TemplateArgumentLoc information.
anatofuz
parents:
diff changeset
60 return llvm::None;
anatofuz
parents:
diff changeset
61 }
anatofuz
parents:
diff changeset
62
anatofuz
parents:
diff changeset
63 template <class T>
anatofuz
parents:
diff changeset
64 bool isTemplateSpecializationKind(const NamedDecl *D,
anatofuz
parents:
diff changeset
65 TemplateSpecializationKind Kind) {
anatofuz
parents:
diff changeset
66 if (const auto *TD = dyn_cast<T>(D))
anatofuz
parents:
diff changeset
67 return TD->getTemplateSpecializationKind() == Kind;
anatofuz
parents:
diff changeset
68 return false;
anatofuz
parents:
diff changeset
69 }
anatofuz
parents:
diff changeset
70
anatofuz
parents:
diff changeset
71 bool isTemplateSpecializationKind(const NamedDecl *D,
anatofuz
parents:
diff changeset
72 TemplateSpecializationKind Kind) {
anatofuz
parents:
diff changeset
73 return isTemplateSpecializationKind<FunctionDecl>(D, Kind) ||
anatofuz
parents:
diff changeset
74 isTemplateSpecializationKind<CXXRecordDecl>(D, Kind) ||
anatofuz
parents:
diff changeset
75 isTemplateSpecializationKind<VarDecl>(D, Kind);
anatofuz
parents:
diff changeset
76 }
anatofuz
parents:
diff changeset
77
anatofuz
parents:
diff changeset
78 // Store all UsingDirectiveDecls in parent contexts of DestContext, that were
anatofuz
parents:
diff changeset
79 // introduced before InsertionPoint.
anatofuz
parents:
diff changeset
80 llvm::DenseSet<const NamespaceDecl *>
anatofuz
parents:
diff changeset
81 getUsingNamespaceDirectives(const DeclContext *DestContext,
anatofuz
parents:
diff changeset
82 SourceLocation Until) {
anatofuz
parents:
diff changeset
83 const auto &SM = DestContext->getParentASTContext().getSourceManager();
anatofuz
parents:
diff changeset
84 llvm::DenseSet<const NamespaceDecl *> VisibleNamespaceDecls;
anatofuz
parents:
diff changeset
85 for (const auto *DC = DestContext; DC; DC = DC->getLookupParent()) {
anatofuz
parents:
diff changeset
86 for (const auto *D : DC->decls()) {
anatofuz
parents:
diff changeset
87 if (!SM.isWrittenInSameFile(D->getLocation(), Until) ||
anatofuz
parents:
diff changeset
88 !SM.isBeforeInTranslationUnit(D->getLocation(), Until))
anatofuz
parents:
diff changeset
89 continue;
anatofuz
parents:
diff changeset
90 if (auto *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D))
anatofuz
parents:
diff changeset
91 VisibleNamespaceDecls.insert(
anatofuz
parents:
diff changeset
92 UDD->getNominatedNamespace()->getCanonicalDecl());
anatofuz
parents:
diff changeset
93 }
anatofuz
parents:
diff changeset
94 }
anatofuz
parents:
diff changeset
95 return VisibleNamespaceDecls;
anatofuz
parents:
diff changeset
96 }
anatofuz
parents:
diff changeset
97
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
98 // Goes over all parents of SourceContext until we find a common ancestor for
150
anatofuz
parents:
diff changeset
99 // DestContext and SourceContext. Any qualifier including and above common
anatofuz
parents:
diff changeset
100 // ancestor is redundant, therefore we stop at lowest common ancestor.
anatofuz
parents:
diff changeset
101 // In addition to that stops early whenever IsVisible returns true. This can be
anatofuz
parents:
diff changeset
102 // used to implement support for "using namespace" decls.
anatofuz
parents:
diff changeset
103 std::string
anatofuz
parents:
diff changeset
104 getQualification(ASTContext &Context, const DeclContext *DestContext,
anatofuz
parents:
diff changeset
105 const DeclContext *SourceContext,
anatofuz
parents:
diff changeset
106 llvm::function_ref<bool(NestedNameSpecifier *)> IsVisible) {
anatofuz
parents:
diff changeset
107 std::vector<const NestedNameSpecifier *> Parents;
anatofuz
parents:
diff changeset
108 bool ReachedNS = false;
anatofuz
parents:
diff changeset
109 for (const DeclContext *CurContext = SourceContext; CurContext;
anatofuz
parents:
diff changeset
110 CurContext = CurContext->getLookupParent()) {
anatofuz
parents:
diff changeset
111 // Stop once we reach a common ancestor.
anatofuz
parents:
diff changeset
112 if (CurContext->Encloses(DestContext))
anatofuz
parents:
diff changeset
113 break;
anatofuz
parents:
diff changeset
114
anatofuz
parents:
diff changeset
115 NestedNameSpecifier *NNS = nullptr;
anatofuz
parents:
diff changeset
116 if (auto *TD = llvm::dyn_cast<TagDecl>(CurContext)) {
anatofuz
parents:
diff changeset
117 // There can't be any more tag parents after hitting a namespace.
anatofuz
parents:
diff changeset
118 assert(!ReachedNS);
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
119 (void)ReachedNS;
150
anatofuz
parents:
diff changeset
120 NNS = NestedNameSpecifier::Create(Context, nullptr, false,
anatofuz
parents:
diff changeset
121 TD->getTypeForDecl());
anatofuz
parents:
diff changeset
122 } else {
anatofuz
parents:
diff changeset
123 ReachedNS = true;
anatofuz
parents:
diff changeset
124 auto *NSD = llvm::cast<NamespaceDecl>(CurContext);
anatofuz
parents:
diff changeset
125 NNS = NestedNameSpecifier::Create(Context, nullptr, NSD);
anatofuz
parents:
diff changeset
126 // Anonymous and inline namespace names are not spelled while qualifying a
anatofuz
parents:
diff changeset
127 // name, so skip those.
anatofuz
parents:
diff changeset
128 if (NSD->isAnonymousNamespace() || NSD->isInlineNamespace())
anatofuz
parents:
diff changeset
129 continue;
anatofuz
parents:
diff changeset
130 }
anatofuz
parents:
diff changeset
131 // Stop if this namespace is already visible at DestContext.
anatofuz
parents:
diff changeset
132 if (IsVisible(NNS))
anatofuz
parents:
diff changeset
133 break;
anatofuz
parents:
diff changeset
134
anatofuz
parents:
diff changeset
135 Parents.push_back(NNS);
anatofuz
parents:
diff changeset
136 }
anatofuz
parents:
diff changeset
137
anatofuz
parents:
diff changeset
138 // Go over name-specifiers in reverse order to create necessary qualification,
anatofuz
parents:
diff changeset
139 // since we stored inner-most parent first.
anatofuz
parents:
diff changeset
140 std::string Result;
anatofuz
parents:
diff changeset
141 llvm::raw_string_ostream OS(Result);
anatofuz
parents:
diff changeset
142 for (const auto *Parent : llvm::reverse(Parents))
anatofuz
parents:
diff changeset
143 Parent->print(OS, Context.getPrintingPolicy());
anatofuz
parents:
diff changeset
144 return OS.str();
anatofuz
parents:
diff changeset
145 }
anatofuz
parents:
diff changeset
146
anatofuz
parents:
diff changeset
147 } // namespace
anatofuz
parents:
diff changeset
148
anatofuz
parents:
diff changeset
149 bool isImplicitTemplateInstantiation(const NamedDecl *D) {
anatofuz
parents:
diff changeset
150 return isTemplateSpecializationKind(D, TSK_ImplicitInstantiation);
anatofuz
parents:
diff changeset
151 }
anatofuz
parents:
diff changeset
152
anatofuz
parents:
diff changeset
153 bool isExplicitTemplateSpecialization(const NamedDecl *D) {
anatofuz
parents:
diff changeset
154 return isTemplateSpecializationKind(D, TSK_ExplicitSpecialization);
anatofuz
parents:
diff changeset
155 }
anatofuz
parents:
diff changeset
156
anatofuz
parents:
diff changeset
157 bool isImplementationDetail(const Decl *D) {
anatofuz
parents:
diff changeset
158 return !isSpelledInSource(D->getLocation(),
anatofuz
parents:
diff changeset
159 D->getASTContext().getSourceManager());
anatofuz
parents:
diff changeset
160 }
anatofuz
parents:
diff changeset
161
anatofuz
parents:
diff changeset
162 SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM) {
anatofuz
parents:
diff changeset
163 auto L = D.getLocation();
anatofuz
parents:
diff changeset
164 if (isSpelledInSource(L, SM))
anatofuz
parents:
diff changeset
165 return SM.getSpellingLoc(L);
anatofuz
parents:
diff changeset
166 return SM.getExpansionLoc(L);
anatofuz
parents:
diff changeset
167 }
anatofuz
parents:
diff changeset
168
anatofuz
parents:
diff changeset
169 std::string printQualifiedName(const NamedDecl &ND) {
anatofuz
parents:
diff changeset
170 std::string QName;
anatofuz
parents:
diff changeset
171 llvm::raw_string_ostream OS(QName);
anatofuz
parents:
diff changeset
172 PrintingPolicy Policy(ND.getASTContext().getLangOpts());
anatofuz
parents:
diff changeset
173 // Note that inline namespaces are treated as transparent scopes. This
anatofuz
parents:
diff changeset
174 // reflects the way they're most commonly used for lookup. Ideally we'd
anatofuz
parents:
diff changeset
175 // include them, but at query time it's hard to find all the inline
anatofuz
parents:
diff changeset
176 // namespaces to query: the preamble doesn't have a dedicated list.
anatofuz
parents:
diff changeset
177 Policy.SuppressUnwrittenScope = true;
anatofuz
parents:
diff changeset
178 ND.printQualifiedName(OS, Policy);
anatofuz
parents:
diff changeset
179 OS.flush();
anatofuz
parents:
diff changeset
180 assert(!StringRef(QName).startswith("::"));
anatofuz
parents:
diff changeset
181 return QName;
anatofuz
parents:
diff changeset
182 }
anatofuz
parents:
diff changeset
183
anatofuz
parents:
diff changeset
184 static bool isAnonymous(const DeclarationName &N) {
anatofuz
parents:
diff changeset
185 return N.isIdentifier() && !N.getAsIdentifierInfo();
anatofuz
parents:
diff changeset
186 }
anatofuz
parents:
diff changeset
187
anatofuz
parents:
diff changeset
188 NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND) {
anatofuz
parents:
diff changeset
189 if (auto *V = llvm::dyn_cast<DeclaratorDecl>(&ND))
anatofuz
parents:
diff changeset
190 return V->getQualifierLoc();
anatofuz
parents:
diff changeset
191 if (auto *T = llvm::dyn_cast<TagDecl>(&ND))
anatofuz
parents:
diff changeset
192 return T->getQualifierLoc();
anatofuz
parents:
diff changeset
193 return NestedNameSpecifierLoc();
anatofuz
parents:
diff changeset
194 }
anatofuz
parents:
diff changeset
195
anatofuz
parents:
diff changeset
196 std::string printUsingNamespaceName(const ASTContext &Ctx,
anatofuz
parents:
diff changeset
197 const UsingDirectiveDecl &D) {
anatofuz
parents:
diff changeset
198 PrintingPolicy PP(Ctx.getLangOpts());
anatofuz
parents:
diff changeset
199 std::string Name;
anatofuz
parents:
diff changeset
200 llvm::raw_string_ostream Out(Name);
anatofuz
parents:
diff changeset
201
anatofuz
parents:
diff changeset
202 if (auto *Qual = D.getQualifier())
anatofuz
parents:
diff changeset
203 Qual->print(Out, PP);
anatofuz
parents:
diff changeset
204 D.getNominatedNamespaceAsWritten()->printName(Out);
anatofuz
parents:
diff changeset
205 return Out.str();
anatofuz
parents:
diff changeset
206 }
anatofuz
parents:
diff changeset
207
anatofuz
parents:
diff changeset
208 std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
anatofuz
parents:
diff changeset
209 std::string Name;
anatofuz
parents:
diff changeset
210 llvm::raw_string_ostream Out(Name);
anatofuz
parents:
diff changeset
211 PrintingPolicy PP(Ctx.getLangOpts());
anatofuz
parents:
diff changeset
212 // We don't consider a class template's args part of the constructor name.
anatofuz
parents:
diff changeset
213 PP.SuppressTemplateArgsInCXXConstructors = true;
anatofuz
parents:
diff changeset
214
anatofuz
parents:
diff changeset
215 // Handle 'using namespace'. They all have the same name - <using-directive>.
anatofuz
parents:
diff changeset
216 if (auto *UD = llvm::dyn_cast<UsingDirectiveDecl>(&ND)) {
anatofuz
parents:
diff changeset
217 Out << "using namespace ";
anatofuz
parents:
diff changeset
218 if (auto *Qual = UD->getQualifier())
anatofuz
parents:
diff changeset
219 Qual->print(Out, PP);
anatofuz
parents:
diff changeset
220 UD->getNominatedNamespaceAsWritten()->printName(Out);
anatofuz
parents:
diff changeset
221 return Out.str();
anatofuz
parents:
diff changeset
222 }
anatofuz
parents:
diff changeset
223
anatofuz
parents:
diff changeset
224 if (isAnonymous(ND.getDeclName())) {
anatofuz
parents:
diff changeset
225 // Come up with a presentation for an anonymous entity.
anatofuz
parents:
diff changeset
226 if (isa<NamespaceDecl>(ND))
anatofuz
parents:
diff changeset
227 return "(anonymous namespace)";
anatofuz
parents:
diff changeset
228 if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND)) {
anatofuz
parents:
diff changeset
229 if (Cls->isLambda())
anatofuz
parents:
diff changeset
230 return "(lambda)";
anatofuz
parents:
diff changeset
231 return ("(anonymous " + Cls->getKindName() + ")").str();
anatofuz
parents:
diff changeset
232 }
anatofuz
parents:
diff changeset
233 if (isa<EnumDecl>(ND))
anatofuz
parents:
diff changeset
234 return "(anonymous enum)";
anatofuz
parents:
diff changeset
235 return "(anonymous)";
anatofuz
parents:
diff changeset
236 }
anatofuz
parents:
diff changeset
237
anatofuz
parents:
diff changeset
238 // Print nested name qualifier if it was written in the source code.
anatofuz
parents:
diff changeset
239 if (auto *Qualifier = getQualifierLoc(ND).getNestedNameSpecifier())
anatofuz
parents:
diff changeset
240 Qualifier->print(Out, PP);
anatofuz
parents:
diff changeset
241 // Print the name itself.
anatofuz
parents:
diff changeset
242 ND.getDeclName().print(Out, PP);
anatofuz
parents:
diff changeset
243 // Print template arguments.
anatofuz
parents:
diff changeset
244 Out << printTemplateSpecializationArgs(ND);
anatofuz
parents:
diff changeset
245
anatofuz
parents:
diff changeset
246 return Out.str();
anatofuz
parents:
diff changeset
247 }
anatofuz
parents:
diff changeset
248
anatofuz
parents:
diff changeset
249 std::string printTemplateSpecializationArgs(const NamedDecl &ND) {
anatofuz
parents:
diff changeset
250 std::string TemplateArgs;
anatofuz
parents:
diff changeset
251 llvm::raw_string_ostream OS(TemplateArgs);
anatofuz
parents:
diff changeset
252 PrintingPolicy Policy(ND.getASTContext().getLangOpts());
anatofuz
parents:
diff changeset
253 if (llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>> Args =
anatofuz
parents:
diff changeset
254 getTemplateSpecializationArgLocs(ND)) {
anatofuz
parents:
diff changeset
255 printTemplateArgumentList(OS, *Args, Policy);
anatofuz
parents:
diff changeset
256 } else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) {
anatofuz
parents:
diff changeset
257 if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) {
anatofuz
parents:
diff changeset
258 // ClassTemplateSpecializationDecls do not contain
anatofuz
parents:
diff changeset
259 // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we
anatofuz
parents:
diff changeset
260 // create a new argument location list from TypeSourceInfo.
anatofuz
parents:
diff changeset
261 auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>();
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
262 llvm::SmallVector<TemplateArgumentLoc> ArgLocs;
150
anatofuz
parents:
diff changeset
263 ArgLocs.reserve(STL.getNumArgs());
anatofuz
parents:
diff changeset
264 for (unsigned I = 0; I < STL.getNumArgs(); ++I)
anatofuz
parents:
diff changeset
265 ArgLocs.push_back(STL.getArgLoc(I));
anatofuz
parents:
diff changeset
266 printTemplateArgumentList(OS, ArgLocs, Policy);
anatofuz
parents:
diff changeset
267 } else {
anatofuz
parents:
diff changeset
268 // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST,
anatofuz
parents:
diff changeset
269 // e.g. friend decls. Currently we fallback to Template Arguments without
anatofuz
parents:
diff changeset
270 // location information.
anatofuz
parents:
diff changeset
271 printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy);
anatofuz
parents:
diff changeset
272 }
anatofuz
parents:
diff changeset
273 }
anatofuz
parents:
diff changeset
274 OS.flush();
anatofuz
parents:
diff changeset
275 return TemplateArgs;
anatofuz
parents:
diff changeset
276 }
anatofuz
parents:
diff changeset
277
anatofuz
parents:
diff changeset
278 std::string printNamespaceScope(const DeclContext &DC) {
anatofuz
parents:
diff changeset
279 for (const auto *Ctx = &DC; Ctx != nullptr; Ctx = Ctx->getParent())
anatofuz
parents:
diff changeset
280 if (const auto *NS = dyn_cast<NamespaceDecl>(Ctx))
anatofuz
parents:
diff changeset
281 if (!NS->isAnonymousNamespace() && !NS->isInlineNamespace())
anatofuz
parents:
diff changeset
282 return printQualifiedName(*NS) + "::";
anatofuz
parents:
diff changeset
283 return "";
anatofuz
parents:
diff changeset
284 }
anatofuz
parents:
diff changeset
285
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
286 static llvm::StringRef
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
287 getNameOrErrForObjCInterface(const ObjCInterfaceDecl *ID) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
288 return ID ? ID->getName() : "<<error-type>>";
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
289 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
290
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
291 std::string printObjCMethod(const ObjCMethodDecl &Method) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
292 std::string Name;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
293 llvm::raw_string_ostream OS(Name);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
294
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
295 OS << (Method.isInstanceMethod() ? '-' : '+') << '[';
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
296
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
297 // Should always be true.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
298 if (const ObjCContainerDecl *C =
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
299 dyn_cast<ObjCContainerDecl>(Method.getDeclContext()))
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
300 OS << printObjCContainer(*C);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
301
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
302 Method.getSelector().print(OS << ' ');
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
303 if (Method.isVariadic())
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
304 OS << ", ...";
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
305
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
306 OS << ']';
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
307 OS.flush();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
308 return Name;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
309 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
310
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
311 std::string printObjCContainer(const ObjCContainerDecl &C) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
312 if (const ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(&C)) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
313 std::string Name;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
314 llvm::raw_string_ostream OS(Name);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
315 const ObjCInterfaceDecl *Class = Category->getClassInterface();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
316 OS << getNameOrErrForObjCInterface(Class) << '(' << Category->getName()
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
317 << ')';
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
318 OS.flush();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
319 return Name;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
320 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
321 if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(&C)) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
322 std::string Name;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
323 llvm::raw_string_ostream OS(Name);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
324 const ObjCInterfaceDecl *Class = CID->getClassInterface();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
325 OS << getNameOrErrForObjCInterface(Class) << '(' << CID->getName() << ')';
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
326 OS.flush();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
327 return Name;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
328 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
329 return C.getNameAsString();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
330 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
331
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
332 SymbolID getSymbolID(const Decl *D) {
150
anatofuz
parents:
diff changeset
333 llvm::SmallString<128> USR;
anatofuz
parents:
diff changeset
334 if (index::generateUSRForDecl(D, USR))
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
335 return {};
150
anatofuz
parents:
diff changeset
336 return SymbolID(USR);
anatofuz
parents:
diff changeset
337 }
anatofuz
parents:
diff changeset
338
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
339 SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI,
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
340 const SourceManager &SM) {
150
anatofuz
parents:
diff changeset
341 if (MI == nullptr)
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
342 return {};
150
anatofuz
parents:
diff changeset
343 llvm::SmallString<128> USR;
anatofuz
parents:
diff changeset
344 if (index::generateUSRForMacro(MacroName, MI->getDefinitionLoc(), SM, USR))
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
345 return {};
150
anatofuz
parents:
diff changeset
346 return SymbolID(USR);
anatofuz
parents:
diff changeset
347 }
anatofuz
parents:
diff changeset
348
anatofuz
parents:
diff changeset
349 std::string printType(const QualType QT, const DeclContext &CurContext) {
anatofuz
parents:
diff changeset
350 std::string Result;
anatofuz
parents:
diff changeset
351 llvm::raw_string_ostream OS(Result);
anatofuz
parents:
diff changeset
352 PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy());
anatofuz
parents:
diff changeset
353 PP.SuppressTagKeyword = true;
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
354 PP.SuppressUnwrittenScope = true;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
355
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
356 class PrintCB : public PrintingCallbacks {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
357 public:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
358 PrintCB(const DeclContext *CurContext) : CurContext(CurContext) {}
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
359 virtual ~PrintCB() {}
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
360 virtual bool isScopeVisible(const DeclContext *DC) const override {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
361 return DC->Encloses(CurContext);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
362 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
363
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
364 private:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
365 const DeclContext *CurContext;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
366 };
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
367 PrintCB PCB(&CurContext);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
368 PP.Callbacks = &PCB;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
369
150
anatofuz
parents:
diff changeset
370 QT.print(OS, PP);
anatofuz
parents:
diff changeset
371 return OS.str();
anatofuz
parents:
diff changeset
372 }
anatofuz
parents:
diff changeset
373
anatofuz
parents:
diff changeset
374 QualType declaredType(const TypeDecl *D) {
anatofuz
parents:
diff changeset
375 if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
anatofuz
parents:
diff changeset
376 if (const auto *TSI = CTSD->getTypeAsWritten())
anatofuz
parents:
diff changeset
377 return TSI->getType();
anatofuz
parents:
diff changeset
378 return D->getASTContext().getTypeDeclType(D);
anatofuz
parents:
diff changeset
379 }
anatofuz
parents:
diff changeset
380
anatofuz
parents:
diff changeset
381 namespace {
anatofuz
parents:
diff changeset
382 /// Computes the deduced type at a given location by visiting the relevant
anatofuz
parents:
diff changeset
383 /// nodes. We use this to display the actual type when hovering over an "auto"
anatofuz
parents:
diff changeset
384 /// keyword or "decltype()" expression.
anatofuz
parents:
diff changeset
385 /// FIXME: This could have been a lot simpler by visiting AutoTypeLocs but it
anatofuz
parents:
diff changeset
386 /// seems that the AutoTypeLocs that can be visited along with their AutoType do
anatofuz
parents:
diff changeset
387 /// not have the deduced type set. Instead, we have to go to the appropriate
anatofuz
parents:
diff changeset
388 /// DeclaratorDecl/FunctionDecl and work our back to the AutoType that does have
anatofuz
parents:
diff changeset
389 /// a deduced type set. The AST should be improved to simplify this scenario.
anatofuz
parents:
diff changeset
390 class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
anatofuz
parents:
diff changeset
391 SourceLocation SearchedLocation;
anatofuz
parents:
diff changeset
392
anatofuz
parents:
diff changeset
393 public:
anatofuz
parents:
diff changeset
394 DeducedTypeVisitor(SourceLocation SearchedLocation)
anatofuz
parents:
diff changeset
395 : SearchedLocation(SearchedLocation) {}
anatofuz
parents:
diff changeset
396
anatofuz
parents:
diff changeset
397 // Handle auto initializers:
anatofuz
parents:
diff changeset
398 //- auto i = 1;
anatofuz
parents:
diff changeset
399 //- decltype(auto) i = 1;
anatofuz
parents:
diff changeset
400 //- auto& i = 1;
anatofuz
parents:
diff changeset
401 //- auto* i = &a;
anatofuz
parents:
diff changeset
402 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
anatofuz
parents:
diff changeset
403 if (!D->getTypeSourceInfo() ||
anatofuz
parents:
diff changeset
404 D->getTypeSourceInfo()->getTypeLoc().getBeginLoc() != SearchedLocation)
anatofuz
parents:
diff changeset
405 return true;
anatofuz
parents:
diff changeset
406
anatofuz
parents:
diff changeset
407 if (auto *AT = D->getType()->getContainedAutoType()) {
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
408 DeducedType = AT->desugar();
150
anatofuz
parents:
diff changeset
409 }
anatofuz
parents:
diff changeset
410 return true;
anatofuz
parents:
diff changeset
411 }
anatofuz
parents:
diff changeset
412
anatofuz
parents:
diff changeset
413 // Handle auto return types:
anatofuz
parents:
diff changeset
414 //- auto foo() {}
anatofuz
parents:
diff changeset
415 //- auto& foo() {}
anatofuz
parents:
diff changeset
416 //- auto foo() -> int {}
anatofuz
parents:
diff changeset
417 //- auto foo() -> decltype(1+1) {}
anatofuz
parents:
diff changeset
418 //- operator auto() const { return 10; }
anatofuz
parents:
diff changeset
419 bool VisitFunctionDecl(FunctionDecl *D) {
anatofuz
parents:
diff changeset
420 if (!D->getTypeSourceInfo())
anatofuz
parents:
diff changeset
421 return true;
anatofuz
parents:
diff changeset
422 // Loc of auto in return type (c++14).
anatofuz
parents:
diff changeset
423 auto CurLoc = D->getReturnTypeSourceRange().getBegin();
anatofuz
parents:
diff changeset
424 // Loc of "auto" in operator auto()
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
425 if (CurLoc.isInvalid() && isa<CXXConversionDecl>(D))
150
anatofuz
parents:
diff changeset
426 CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
anatofuz
parents:
diff changeset
427 // Loc of "auto" in function with trailing return type (c++11).
anatofuz
parents:
diff changeset
428 if (CurLoc.isInvalid())
anatofuz
parents:
diff changeset
429 CurLoc = D->getSourceRange().getBegin();
anatofuz
parents:
diff changeset
430 if (CurLoc != SearchedLocation)
anatofuz
parents:
diff changeset
431 return true;
anatofuz
parents:
diff changeset
432
anatofuz
parents:
diff changeset
433 const AutoType *AT = D->getReturnType()->getContainedAutoType();
anatofuz
parents:
diff changeset
434 if (AT && !AT->getDeducedType().isNull()) {
anatofuz
parents:
diff changeset
435 DeducedType = AT->getDeducedType();
anatofuz
parents:
diff changeset
436 } else if (auto DT = dyn_cast<DecltypeType>(D->getReturnType())) {
anatofuz
parents:
diff changeset
437 // auto in a trailing return type just points to a DecltypeType and
anatofuz
parents:
diff changeset
438 // getContainedAutoType does not unwrap it.
anatofuz
parents:
diff changeset
439 if (!DT->getUnderlyingType().isNull())
anatofuz
parents:
diff changeset
440 DeducedType = DT->getUnderlyingType();
anatofuz
parents:
diff changeset
441 } else if (!D->getReturnType().isNull()) {
anatofuz
parents:
diff changeset
442 DeducedType = D->getReturnType();
anatofuz
parents:
diff changeset
443 }
anatofuz
parents:
diff changeset
444 return true;
anatofuz
parents:
diff changeset
445 }
anatofuz
parents:
diff changeset
446
anatofuz
parents:
diff changeset
447 // Handle non-auto decltype, e.g.:
anatofuz
parents:
diff changeset
448 // - auto foo() -> decltype(expr) {}
anatofuz
parents:
diff changeset
449 // - decltype(expr);
anatofuz
parents:
diff changeset
450 bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
anatofuz
parents:
diff changeset
451 if (TL.getBeginLoc() != SearchedLocation)
anatofuz
parents:
diff changeset
452 return true;
anatofuz
parents:
diff changeset
453
anatofuz
parents:
diff changeset
454 // A DecltypeType's underlying type can be another DecltypeType! E.g.
anatofuz
parents:
diff changeset
455 // int I = 0;
anatofuz
parents:
diff changeset
456 // decltype(I) J = I;
anatofuz
parents:
diff changeset
457 // decltype(J) K = J;
anatofuz
parents:
diff changeset
458 const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr());
anatofuz
parents:
diff changeset
459 while (DT && !DT->getUnderlyingType().isNull()) {
anatofuz
parents:
diff changeset
460 DeducedType = DT->getUnderlyingType();
anatofuz
parents:
diff changeset
461 DT = dyn_cast<DecltypeType>(DeducedType.getTypePtr());
anatofuz
parents:
diff changeset
462 }
anatofuz
parents:
diff changeset
463 return true;
anatofuz
parents:
diff changeset
464 }
anatofuz
parents:
diff changeset
465
anatofuz
parents:
diff changeset
466 QualType DeducedType;
anatofuz
parents:
diff changeset
467 };
anatofuz
parents:
diff changeset
468 } // namespace
anatofuz
parents:
diff changeset
469
anatofuz
parents:
diff changeset
470 llvm::Optional<QualType> getDeducedType(ASTContext &ASTCtx,
anatofuz
parents:
diff changeset
471 SourceLocation Loc) {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
472 if (!Loc.isValid())
150
anatofuz
parents:
diff changeset
473 return {};
anatofuz
parents:
diff changeset
474 DeducedTypeVisitor V(Loc);
anatofuz
parents:
diff changeset
475 V.TraverseAST(ASTCtx);
anatofuz
parents:
diff changeset
476 if (V.DeducedType.isNull())
anatofuz
parents:
diff changeset
477 return llvm::None;
anatofuz
parents:
diff changeset
478 return V.DeducedType;
anatofuz
parents:
diff changeset
479 }
anatofuz
parents:
diff changeset
480
anatofuz
parents:
diff changeset
481 std::string getQualification(ASTContext &Context,
anatofuz
parents:
diff changeset
482 const DeclContext *DestContext,
anatofuz
parents:
diff changeset
483 SourceLocation InsertionPoint,
anatofuz
parents:
diff changeset
484 const NamedDecl *ND) {
anatofuz
parents:
diff changeset
485 auto VisibleNamespaceDecls =
anatofuz
parents:
diff changeset
486 getUsingNamespaceDirectives(DestContext, InsertionPoint);
anatofuz
parents:
diff changeset
487 return getQualification(
anatofuz
parents:
diff changeset
488 Context, DestContext, ND->getDeclContext(),
anatofuz
parents:
diff changeset
489 [&](NestedNameSpecifier *NNS) {
anatofuz
parents:
diff changeset
490 if (NNS->getKind() != NestedNameSpecifier::Namespace)
anatofuz
parents:
diff changeset
491 return false;
anatofuz
parents:
diff changeset
492 const auto *CanonNSD = NNS->getAsNamespace()->getCanonicalDecl();
anatofuz
parents:
diff changeset
493 return llvm::any_of(VisibleNamespaceDecls,
anatofuz
parents:
diff changeset
494 [CanonNSD](const NamespaceDecl *NSD) {
anatofuz
parents:
diff changeset
495 return NSD->getCanonicalDecl() == CanonNSD;
anatofuz
parents:
diff changeset
496 });
anatofuz
parents:
diff changeset
497 });
anatofuz
parents:
diff changeset
498 }
anatofuz
parents:
diff changeset
499
anatofuz
parents:
diff changeset
500 std::string getQualification(ASTContext &Context,
anatofuz
parents:
diff changeset
501 const DeclContext *DestContext,
anatofuz
parents:
diff changeset
502 const NamedDecl *ND,
anatofuz
parents:
diff changeset
503 llvm::ArrayRef<std::string> VisibleNamespaces) {
anatofuz
parents:
diff changeset
504 for (llvm::StringRef NS : VisibleNamespaces) {
anatofuz
parents:
diff changeset
505 assert(NS.endswith("::"));
anatofuz
parents:
diff changeset
506 (void)NS;
anatofuz
parents:
diff changeset
507 }
anatofuz
parents:
diff changeset
508 return getQualification(
anatofuz
parents:
diff changeset
509 Context, DestContext, ND->getDeclContext(),
anatofuz
parents:
diff changeset
510 [&](NestedNameSpecifier *NNS) {
anatofuz
parents:
diff changeset
511 return llvm::any_of(VisibleNamespaces, [&](llvm::StringRef Namespace) {
anatofuz
parents:
diff changeset
512 std::string NS;
anatofuz
parents:
diff changeset
513 llvm::raw_string_ostream OS(NS);
anatofuz
parents:
diff changeset
514 NNS->print(OS, Context.getPrintingPolicy());
anatofuz
parents:
diff changeset
515 return OS.str() == Namespace;
anatofuz
parents:
diff changeset
516 });
anatofuz
parents:
diff changeset
517 });
anatofuz
parents:
diff changeset
518 }
anatofuz
parents:
diff changeset
519
anatofuz
parents:
diff changeset
520 bool hasUnstableLinkage(const Decl *D) {
anatofuz
parents:
diff changeset
521 // Linkage of a ValueDecl depends on the type.
anatofuz
parents:
diff changeset
522 // If that's not deduced yet, deducing it may change the linkage.
anatofuz
parents:
diff changeset
523 auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
anatofuz
parents:
diff changeset
524 return VD && !VD->getType().isNull() && VD->getType()->isUndeducedType();
anatofuz
parents:
diff changeset
525 }
anatofuz
parents:
diff changeset
526
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
527 bool isDeeplyNested(const Decl *D, unsigned MaxDepth) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
528 size_t ContextDepth = 0;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
529 for (auto *Ctx = D->getDeclContext(); Ctx && !Ctx->isTranslationUnit();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
530 Ctx = Ctx->getParent()) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
531 if (++ContextDepth == MaxDepth)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
532 return true;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
533 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
534 return false;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
535 }
150
anatofuz
parents:
diff changeset
536 } // namespace clangd
anatofuz
parents:
diff changeset
537 } // namespace clang