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();
121TemplateName getReferencedTemplateName(
const Type *T) {
122 if (
const auto *TST =
T->getAs<TemplateSpecializationType>()) {
123 return TST->getTemplateName();
125 if (
const auto *DTST =
T->getAs<DeducedTemplateSpecializationType>()) {
126 return DTST->getTemplateName();
128 return TemplateName();
134CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(
const Type *T) {
138 T =
T->getCanonicalTypeInternal().getTypePtr();
140 if (
const auto *DNT =
T->getAs<DependentNameType>()) {
141 T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx);
144 T =
T->getCanonicalTypeInternal().getTypePtr();
147 if (
const auto *RT =
T->getAs<RecordType>())
148 return dyn_cast<CXXRecordDecl>(RT->getDecl());
150 if (
const auto *ICNT =
T->getAs<InjectedClassNameType>())
151 T = ICNT->getInjectedSpecializationType().getTypePtrOrNull();
155 TemplateName TN = getReferencedTemplateName(T);
159 const ClassTemplateDecl *TD =
160 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
164 return TD->getTemplatedDecl();
167const Type *HeuristicResolverImpl::getPointeeType(
const Type *T) {
171 if (
T->isPointerType())
172 return T->castAs<PointerType>()->getPointeeType().getTypePtrOrNull();
178 auto ArrowOps = resolveDependentMember(
179 T, Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow), NonStaticFilter);
180 if (ArrowOps.empty())
189 auto *TST =
T->getAs<TemplateSpecializationType>();
192 if (TST->template_arguments().size() == 0)
194 const TemplateArgument &FirstArg = TST->template_arguments()[0];
195 if (FirstArg.getKind() != TemplateArgument::Type)
197 return FirstArg.getAsType().getTypePtrOrNull();
200std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
201 const CXXDependentScopeMemberExpr *ME) {
213 if (NestedNameSpecifier *NNS = ME->getQualifier()) {
214 if (
const Type *QualifierType = resolveNestedNameSpecifierToType(NNS)) {
216 resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
229 const Type *BaseType = ME->getBaseType().getTypePtrOrNull();
231 BaseType = getPointeeType(BaseType);
235 if (
const auto *BT = BaseType->getAs<BuiltinType>()) {
239 Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
240 if (Base && BT->getKind() == BuiltinType::Dependent) {
241 BaseType = resolveExprToType(Base);
244 return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
247std::vector<const NamedDecl *>
248HeuristicResolverImpl::resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE) {
249 return resolveDependentMember(RE->getQualifier()->getAsType(),
250 RE->getDeclName(), StaticFilter);
253std::vector<const NamedDecl *>
254HeuristicResolverImpl::resolveTypeOfCallExpr(
const CallExpr *
CE) {
255 const auto *CalleeType = resolveExprToType(
CE->getCallee());
258 if (
const auto *FnTypePtr = CalleeType->getAs<PointerType>())
259 CalleeType = FnTypePtr->getPointeeType().getTypePtr();
260 if (
const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
262 resolveTypeToRecordDecl(FnType->getReturnType().getTypePtr())) {
269std::vector<const NamedDecl *>
270HeuristicResolverImpl::resolveCalleeOfCallExpr(
const CallExpr *
CE) {
271 if (
const auto *ND = dyn_cast_or_null<NamedDecl>(
CE->getCalleeDecl())) {
275 return resolveExprToDecls(
CE->getCallee());
278std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
279 const UnresolvedUsingValueDecl *UUVD) {
280 return resolveDependentMember(UUVD->getQualifier()->getAsType(),
281 UUVD->getNameInfo().getName(), ValueFilter);
284std::vector<const NamedDecl *>
285HeuristicResolverImpl::resolveDependentNameType(
const DependentNameType *DNT) {
286 if (
auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted)
288 return resolveDependentMember(
289 resolveNestedNameSpecifierToType(DNT->getQualifier()),
290 DNT->getIdentifier(), TypeFilter);
293std::vector<const NamedDecl *>
294HeuristicResolverImpl::resolveTemplateSpecializationType(
295 const DependentTemplateSpecializationType *DTST) {
296 return resolveDependentMember(
297 resolveNestedNameSpecifierToType(DTST->getQualifier()),
298 DTST->getIdentifier(), TemplateFilter);
301std::vector<const NamedDecl *>
302HeuristicResolverImpl::resolveExprToDecls(
const Expr *
E) {
303 if (
const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(
E)) {
304 return resolveMemberExpr(ME);
306 if (
const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(
E)) {
307 return resolveDeclRefExpr(RE);
309 if (
const auto *OE = dyn_cast<OverloadExpr>(
E)) {
310 return {OE->decls_begin(), OE->decls_end()};
312 if (
const auto *
CE = dyn_cast<CallExpr>(
E)) {
313 return resolveTypeOfCallExpr(
CE);
315 if (
const auto *ME = dyn_cast<MemberExpr>(
E))
316 return {ME->getMemberDecl()};
321const Type *HeuristicResolverImpl::resolveExprToType(
const Expr *
E) {
322 std::vector<const NamedDecl *> Decls = resolveExprToDecls(
E);
324 return resolveDeclsToType(Decls, Ctx);
326 return E->getType().getTypePtr();
329const Type *HeuristicResolverImpl::resolveNestedNameSpecifierToType(
330 const NestedNameSpecifier *NNS) {
338 switch (NNS->getKind()) {
339 case NestedNameSpecifier::TypeSpec:
340 case NestedNameSpecifier::TypeSpecWithTemplate:
341 return NNS->getAsType();
342 case NestedNameSpecifier::Identifier: {
343 return resolveDeclsToType(
344 resolveDependentMember(
345 resolveNestedNameSpecifierToType(NNS->getPrefix()),
346 NNS->getAsIdentifier(), TypeFilter),
355bool isOrdinaryMember(
const NamedDecl *ND) {
356 return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag |
360bool findOrdinaryMember(
const CXXRecordDecl *RD, CXXBasePath &
Path,
361 DeclarationName
Name) {
362 Path.Decls = RD->lookup(
Name).begin();
363 for (DeclContext::lookup_iterator I =
Path.Decls,
E = I.end(); I !=
E; ++I)
364 if (isOrdinaryMember(*I))
370bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
371 const CXXBaseSpecifier *Specifier, CXXBasePath &
Path,
372 DeclarationName
Name) {
374 resolveTypeToRecordDecl(Specifier->getType().getTypePtr());
377 return findOrdinaryMember(RD,
Path,
Name);
380std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
381 CXXRecordDecl *RD, DeclarationName
Name,
382 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
383 std::vector<const NamedDecl *>
Results;
386 bool AnyOrdinaryMembers =
false;
387 for (
const NamedDecl *ND : RD->lookup(
Name)) {
388 if (isOrdinaryMember(ND))
389 AnyOrdinaryMembers =
true;
393 if (AnyOrdinaryMembers)
399 if (!RD->lookupInBases(
400 [&](
const CXXBaseSpecifier *Specifier, CXXBasePath &
Path) {
401 return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
405 for (DeclContext::lookup_iterator I = Paths.front().Decls,
E = I.end();
407 if (isOrdinaryMember(*I) && Filter(*I))
413std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
414 const Type *T, DeclarationName
Name,
415 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
418 if (
auto *ET =
T->getAs<EnumType>()) {
419 auto Result = ET->getDecl()->lookup(
Name);
420 return {Result.begin(), Result.end()};
422 if (
auto *RD = resolveTypeToRecordDecl(T)) {
423 if (!RD->hasDefinition())
425 RD = RD->getDefinition();
426 return lookupDependentName(RD,
Name, Filter);
433 const CXXDependentScopeMemberExpr *ME)
const {
434 return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME);
437 const DependentScopeDeclRefExpr *RE)
const {
438 return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE);
440std::vector<const NamedDecl *>
442 return HeuristicResolverImpl(Ctx).resolveTypeOfCallExpr(
CE);
444std::vector<const NamedDecl *>
446 return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(
CE);
449 const UnresolvedUsingValueDecl *UUVD)
const {
450 return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD);
453 const DependentNameType *DNT)
const {
454 return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
456std::vector<const NamedDecl *>
458 const DependentTemplateSpecializationType *DTST)
const {
459 return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
462 const NestedNameSpecifier *NNS)
const {
463 return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
466 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++ -*-===//