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"
21const auto NoFilter = [](
const NamedDecl *D) {
return true; };
23 return D->isCXXInstanceMember();
26 return !D->isCXXInstanceMember();
28const auto ValueFilter = [](
const NamedDecl *D) {
return isa<ValueDecl>(D); };
29const auto TypeFilter = [](
const NamedDecl *D) {
return isa<TypeDecl>(D); };
31 return isa<TemplateDecl>(D);
36const Type *resolveDeclsToType(
const std::vector<const NamedDecl *> &Decls,
38 if (Decls.size() != 1)
40 if (
const auto *TD = dyn_cast<TypeDecl>(Decls[0])) {
41 return Ctx.getTypeDeclType(TD).getTypePtr();
43 if (
const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
44 return VD->getType().getTypePtrOrNull();
54CXXRecordDecl *HeuristicResolver::resolveTypeToRecordDecl(
const Type *T)
const {
58 T = T->getCanonicalTypeInternal().getTypePtr();
60 if (
const auto *DNT = T->getAs<DependentNameType>()) {
64 T = T->getCanonicalTypeInternal().getTypePtr();
67 if (
const auto *RT = T->getAs<RecordType>())
68 return dyn_cast<CXXRecordDecl>(RT->getDecl());
70 if (
const auto *ICNT = T->getAs<InjectedClassNameType>())
71 T = ICNT->getInjectedSpecializationType().getTypePtrOrNull();
75 const auto *TST = T->getAs<TemplateSpecializationType>();
79 const ClassTemplateDecl *TD = dyn_cast_or_null<ClassTemplateDecl>(
80 TST->getTemplateName().getAsTemplateDecl());
84 return TD->getTemplatedDecl();
91 if (T->isPointerType())
92 return T->castAs<PointerType>()->
getPointeeType().getTypePtrOrNull();
98 auto ArrowOps = resolveDependentMember(
100 if (ArrowOps.empty())
109 auto *TST = T->getAs<TemplateSpecializationType>();
112 if (TST->template_arguments().size() == 0)
114 const TemplateArgument &FirstArg = TST->template_arguments()[0];
115 if (FirstArg.getKind() != TemplateArgument::Type)
117 return FirstArg.getAsType().getTypePtrOrNull();
121 const CXXDependentScopeMemberExpr *ME)
const {
133 if (NestedNameSpecifier *NNS = ME->getQualifier()) {
136 resolveDependentMember(QualifierType, ME->getMember(),
NoFilter);
149 const Type *BaseType = ME->getBaseType().getTypePtrOrNull();
155 if (
const auto *BT = BaseType->getAs<BuiltinType>()) {
159 Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
160 if (Base && BT->getKind() == BuiltinType::Dependent) {
161 BaseType = resolveExprToType(Base);
164 return resolveDependentMember(BaseType, ME->getMember(),
NoFilter);
168 const DependentScopeDeclRefExpr *RE)
const {
169 return resolveDependentMember(RE->getQualifier()->getAsType(),
173std::vector<const NamedDecl *>
175 const auto *CalleeType = resolveExprToType(
CE->getCallee());
178 if (
const auto *FnTypePtr = CalleeType->getAs<PointerType>())
179 CalleeType = FnTypePtr->getPointeeType().getTypePtr();
180 if (
const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
182 resolveTypeToRecordDecl(FnType->getReturnType().getTypePtr())) {
189std::vector<const NamedDecl *>
191 if (
const auto *ND = dyn_cast_or_null<NamedDecl>(
CE->getCalleeDecl())) {
195 return resolveExprToDecls(
CE->getCallee());
199 const UnresolvedUsingValueDecl *UUVD)
const {
200 return resolveDependentMember(UUVD->getQualifier()->getAsType(),
205 const DependentNameType *DNT)
const {
206 return resolveDependentMember(
211std::vector<const NamedDecl *>
213 const DependentTemplateSpecializationType *DTST)
const {
214 return resolveDependentMember(
219std::vector<const NamedDecl *>
220HeuristicResolver::resolveExprToDecls(
const Expr *
E)
const {
221 if (
const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(
E)) {
224 if (
const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(
E)) {
227 if (
const auto *OE = dyn_cast<OverloadExpr>(
E)) {
228 return {OE->decls_begin(), OE->decls_end()};
230 if (
const auto *
CE = dyn_cast<CallExpr>(
E)) {
233 if (
const auto *ME = dyn_cast<MemberExpr>(
E))
234 return {ME->getMemberDecl()};
239const Type *HeuristicResolver::resolveExprToType(
const Expr *
E)
const {
240 std::vector<const NamedDecl *> Decls = resolveExprToDecls(
E);
242 return resolveDeclsToType(Decls, Ctx);
244 return E->getType().getTypePtr();
248 const NestedNameSpecifier *NNS)
const {
256 switch (NNS->getKind()) {
257 case NestedNameSpecifier::TypeSpec:
258 case NestedNameSpecifier::TypeSpecWithTemplate:
259 return NNS->getAsType();
260 case NestedNameSpecifier::Identifier: {
261 return resolveDeclsToType(
262 resolveDependentMember(
275bool isOrdinaryMember(
const NamedDecl *ND) {
276 return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag |
280bool findOrdinaryMember(
const CXXRecordDecl *RD, CXXBasePath &
Path,
281 DeclarationName
Name) {
282 Path.Decls = RD->lookup(
Name).begin();
283 for (DeclContext::lookup_iterator I =
Path.Decls,
E = I.end(); I !=
E; ++I)
284 if (isOrdinaryMember(*I))
292bool HeuristicResolver::findOrdinaryMemberInDependentClasses(
293 const CXXBaseSpecifier *Specifier, CXXBasePath &
Path,
294 DeclarationName
Name)
const {
296 resolveTypeToRecordDecl(Specifier->getType().getTypePtr());
299 return findOrdinaryMember(RD,
Path,
Name);
302std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName(
303 CXXRecordDecl *RD, DeclarationName
Name,
304 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter)
const {
305 std::vector<const NamedDecl *>
Results;
308 bool AnyOrdinaryMembers =
false;
309 for (
const NamedDecl *ND : RD->lookup(
Name)) {
310 if (isOrdinaryMember(ND))
311 AnyOrdinaryMembers =
true;
315 if (AnyOrdinaryMembers)
321 if (!RD->lookupInBases(
322 [&](
const CXXBaseSpecifier *Specifier, CXXBasePath &
Path) {
323 return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
327 for (DeclContext::lookup_iterator I = Paths.front().Decls,
E = I.end();
329 if (isOrdinaryMember(*I) && Filter(*I))
335std::vector<const NamedDecl *> HeuristicResolver::resolveDependentMember(
336 const Type *T, DeclarationName
Name,
337 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter)
const {
340 if (
auto *ET = T->getAs<EnumType>()) {
341 auto Result = ET->getDecl()->lookup(
Name);
342 return {Result.begin(), Result.end()};
344 if (
auto *RD = resolveTypeToRecordDecl(T)) {
345 if (!RD->hasDefinition())
347 RD = RD->getDefinition();
348 return lookupDependentName(RD,
Name, Filter);
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.
const auto TemplateFilter
const auto NonStaticFilter
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//