10#include "clang/AST/ASTContext.h"
11#include "clang/AST/CXXInheritance.h"
12#include "clang/AST/DeclTemplate.h"
13#include "clang/AST/ExprCXX.h"
14#include "clang/AST/Type.h"
28class HeuristicResolverImpl {
30 HeuristicResolverImpl(ASTContext &Ctx) : Ctx(Ctx) {}
34 std::vector<const NamedDecl *>
35 resolveMemberExpr(
const CXXDependentScopeMemberExpr *ME);
36 std::vector<const NamedDecl *>
37 resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE);
38 std::vector<const NamedDecl *> resolveTypeOfCallExpr(
const CallExpr *
CE);
39 std::vector<const NamedDecl *> resolveCalleeOfCallExpr(
const CallExpr *
CE);
40 std::vector<const NamedDecl *>
41 resolveUsingValueDecl(
const UnresolvedUsingValueDecl *UUVD);
42 std::vector<const NamedDecl *>
43 resolveDependentNameType(
const DependentNameType *DNT);
44 std::vector<const NamedDecl *> resolveTemplateSpecializationType(
45 const DependentTemplateSpecializationType *DTST);
46 const Type *resolveNestedNameSpecifierToType(
const NestedNameSpecifier *NNS);
47 const Type *getPointeeType(
const Type *T);
53 llvm::SmallSet<const DependentNameType *, 4> SeenDependentNameTypes;
64 std::vector<const NamedDecl *>
65 resolveDependentMember(
const Type *T, DeclarationName
Name,
66 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter);
70 const Type *resolveExprToType(
const Expr *
E);
71 std::vector<const NamedDecl *> resolveExprToDecls(
const Expr *
E);
76 CXXRecordDecl *resolveTypeToRecordDecl(
const Type *T);
85 std::vector<const NamedDecl *>
86 lookupDependentName(CXXRecordDecl *RD, DeclarationName
Name,
87 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter);
88 bool findOrdinaryMemberInDependentClasses(
const CXXBaseSpecifier *Specifier,
90 DeclarationName
Name);
95const auto NoFilter = [](
const NamedDecl *D) {
return true; };
96const auto NonStaticFilter = [](
const NamedDecl *D) {
97 return D->isCXXInstanceMember();
99const auto StaticFilter = [](
const NamedDecl *D) {
100 return !D->isCXXInstanceMember();
102const auto ValueFilter = [](
const NamedDecl *D) {
return isa<ValueDecl>(D); };
103const auto TypeFilter = [](
const NamedDecl *D) {
return isa<TypeDecl>(D); };
104const auto TemplateFilter = [](
const NamedDecl *D) {
105 return isa<TemplateDecl>(D);
108const Type *resolveDeclsToType(
const std::vector<const NamedDecl *> &Decls,
110 if (Decls.size() != 1)
112 if (
const auto *TD = dyn_cast<TypeDecl>(Decls[0])) {
113 return Ctx.getTypeDeclType(TD).getTypePtr();
115 if (
const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
116 return VD->getType().getTypePtrOrNull();
124CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(
const Type *T) {
128 T =
T->getCanonicalTypeInternal().getTypePtr();
130 if (
const auto *DNT =
T->getAs<DependentNameType>()) {
131 T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx);
134 T =
T->getCanonicalTypeInternal().getTypePtr();
137 if (
const auto *RT =
T->getAs<RecordType>())
138 return dyn_cast<CXXRecordDecl>(RT->getDecl());
140 if (
const auto *ICNT =
T->getAs<InjectedClassNameType>())
141 T = ICNT->getInjectedSpecializationType().getTypePtrOrNull();
145 const auto *TST =
T->getAs<TemplateSpecializationType>();
149 const ClassTemplateDecl *TD = dyn_cast_or_null<ClassTemplateDecl>(
150 TST->getTemplateName().getAsTemplateDecl());
154 return TD->getTemplatedDecl();
157const Type *HeuristicResolverImpl::getPointeeType(
const Type *T) {
161 if (
T->isPointerType())
162 return T->castAs<PointerType>()->getPointeeType().getTypePtrOrNull();
168 auto ArrowOps = resolveDependentMember(
169 T, Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow), NonStaticFilter);
170 if (ArrowOps.empty())
179 auto *TST =
T->getAs<TemplateSpecializationType>();
182 if (TST->template_arguments().size() == 0)
184 const TemplateArgument &FirstArg = TST->template_arguments()[0];
185 if (FirstArg.getKind() != TemplateArgument::Type)
187 return FirstArg.getAsType().getTypePtrOrNull();
190std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
191 const CXXDependentScopeMemberExpr *ME) {
203 if (NestedNameSpecifier *NNS = ME->getQualifier()) {
204 if (
const Type *QualifierType = resolveNestedNameSpecifierToType(NNS)) {
206 resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
219 const Type *BaseType = ME->getBaseType().getTypePtrOrNull();
221 BaseType = getPointeeType(BaseType);
225 if (
const auto *BT = BaseType->getAs<BuiltinType>()) {
229 Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
230 if (Base && BT->getKind() == BuiltinType::Dependent) {
231 BaseType = resolveExprToType(Base);
234 return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
237std::vector<const NamedDecl *>
238HeuristicResolverImpl::resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE) {
239 return resolveDependentMember(RE->getQualifier()->getAsType(),
240 RE->getDeclName(), StaticFilter);
243std::vector<const NamedDecl *>
244HeuristicResolverImpl::resolveTypeOfCallExpr(
const CallExpr *
CE) {
245 const auto *CalleeType = resolveExprToType(
CE->getCallee());
248 if (
const auto *FnTypePtr = CalleeType->getAs<PointerType>())
249 CalleeType = FnTypePtr->getPointeeType().getTypePtr();
250 if (
const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
252 resolveTypeToRecordDecl(FnType->getReturnType().getTypePtr())) {
259std::vector<const NamedDecl *>
260HeuristicResolverImpl::resolveCalleeOfCallExpr(
const CallExpr *
CE) {
261 if (
const auto *ND = dyn_cast_or_null<NamedDecl>(
CE->getCalleeDecl())) {
265 return resolveExprToDecls(
CE->getCallee());
268std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
269 const UnresolvedUsingValueDecl *UUVD) {
270 return resolveDependentMember(UUVD->getQualifier()->getAsType(),
271 UUVD->getNameInfo().getName(), ValueFilter);
274std::vector<const NamedDecl *>
275HeuristicResolverImpl::resolveDependentNameType(
const DependentNameType *DNT) {
276 if (
auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted)
278 return resolveDependentMember(
279 resolveNestedNameSpecifierToType(DNT->getQualifier()),
280 DNT->getIdentifier(), TypeFilter);
283std::vector<const NamedDecl *>
284HeuristicResolverImpl::resolveTemplateSpecializationType(
285 const DependentTemplateSpecializationType *DTST) {
286 return resolveDependentMember(
287 resolveNestedNameSpecifierToType(DTST->getQualifier()),
288 DTST->getIdentifier(), TemplateFilter);
291std::vector<const NamedDecl *>
292HeuristicResolverImpl::resolveExprToDecls(
const Expr *
E) {
293 if (
const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(
E)) {
294 return resolveMemberExpr(ME);
296 if (
const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(
E)) {
297 return resolveDeclRefExpr(RE);
299 if (
const auto *OE = dyn_cast<OverloadExpr>(
E)) {
300 return {OE->decls_begin(), OE->decls_end()};
302 if (
const auto *
CE = dyn_cast<CallExpr>(
E)) {
303 return resolveTypeOfCallExpr(
CE);
305 if (
const auto *ME = dyn_cast<MemberExpr>(
E))
306 return {ME->getMemberDecl()};
311const Type *HeuristicResolverImpl::resolveExprToType(
const Expr *
E) {
312 std::vector<const NamedDecl *> Decls = resolveExprToDecls(
E);
314 return resolveDeclsToType(Decls, Ctx);
316 return E->getType().getTypePtr();
319const Type *HeuristicResolverImpl::resolveNestedNameSpecifierToType(
320 const NestedNameSpecifier *NNS) {
328 switch (NNS->getKind()) {
329 case NestedNameSpecifier::TypeSpec:
330 case NestedNameSpecifier::TypeSpecWithTemplate:
331 return NNS->getAsType();
332 case NestedNameSpecifier::Identifier: {
333 return resolveDeclsToType(
334 resolveDependentMember(
335 resolveNestedNameSpecifierToType(NNS->getPrefix()),
336 NNS->getAsIdentifier(), TypeFilter),
345bool isOrdinaryMember(
const NamedDecl *ND) {
346 return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag |
350bool findOrdinaryMember(
const CXXRecordDecl *RD, CXXBasePath &
Path,
351 DeclarationName
Name) {
352 Path.Decls = RD->lookup(
Name).begin();
353 for (DeclContext::lookup_iterator I =
Path.Decls,
E = I.end(); I !=
E; ++I)
354 if (isOrdinaryMember(*I))
360bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
361 const CXXBaseSpecifier *Specifier, CXXBasePath &
Path,
362 DeclarationName
Name) {
364 resolveTypeToRecordDecl(Specifier->getType().getTypePtr());
367 return findOrdinaryMember(RD,
Path,
Name);
370std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
371 CXXRecordDecl *RD, DeclarationName
Name,
372 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
373 std::vector<const NamedDecl *>
Results;
376 bool AnyOrdinaryMembers =
false;
377 for (
const NamedDecl *ND : RD->lookup(
Name)) {
378 if (isOrdinaryMember(ND))
379 AnyOrdinaryMembers =
true;
383 if (AnyOrdinaryMembers)
389 if (!RD->lookupInBases(
390 [&](
const CXXBaseSpecifier *Specifier, CXXBasePath &
Path) {
391 return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
395 for (DeclContext::lookup_iterator I = Paths.front().Decls,
E = I.end();
397 if (isOrdinaryMember(*I) && Filter(*I))
403std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
404 const Type *T, DeclarationName
Name,
405 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
408 if (
auto *ET =
T->getAs<EnumType>()) {
409 auto Result = ET->getDecl()->lookup(
Name);
410 return {Result.begin(), Result.end()};
412 if (
auto *RD = resolveTypeToRecordDecl(T)) {
413 if (!RD->hasDefinition())
415 RD = RD->getDefinition();
416 return lookupDependentName(RD,
Name, Filter);
423 const CXXDependentScopeMemberExpr *ME)
const {
424 return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME);
427 const DependentScopeDeclRefExpr *RE)
const {
428 return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE);
430std::vector<const NamedDecl *>
432 return HeuristicResolverImpl(Ctx).resolveTypeOfCallExpr(
CE);
434std::vector<const NamedDecl *>
436 return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(
CE);
439 const UnresolvedUsingValueDecl *UUVD)
const {
440 return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD);
443 const DependentNameType *DNT)
const {
444 return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
446std::vector<const NamedDecl *>
448 const DependentTemplateSpecializationType *DTST)
const {
449 return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
452 const NestedNameSpecifier *NNS)
const {
453 return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
456 return HeuristicResolverImpl(Ctx).getPointeeType(T);
llvm::SmallString< 256U > Name
std::vector< CodeCompletionResult > Results
std::vector< const NamedDecl * > resolveMemberExpr(const CXXDependentScopeMemberExpr *ME) const
std::vector< const NamedDecl * > resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) const
const Type * getPointeeType(const Type *T) const
std::vector< const NamedDecl * > resolveDependentNameType(const DependentNameType *DNT) const
std::vector< const NamedDecl * > resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const
std::vector< const NamedDecl * > resolveCalleeOfCallExpr(const CallExpr *CE) const
const Type * resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const
std::vector< const NamedDecl * > resolveTemplateSpecializationType(const DependentTemplateSpecializationType *DTST) const
std::vector< const NamedDecl * > resolveTypeOfCallExpr(const CallExpr *CE) const
std::string Path
A typedef to represent a file path.
@ Type
An inlay hint that for a type annotation.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//