27class HeuristicResolverImpl {
29 HeuristicResolverImpl(ASTContext &Ctx) : Ctx(Ctx) {}
33 std::vector<const NamedDecl *>
34 resolveMemberExpr(
const CXXDependentScopeMemberExpr *ME);
35 std::vector<const NamedDecl *>
36 resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE);
37 std::vector<const NamedDecl *> resolveTypeOfCallExpr(
const CallExpr *CE);
38 std::vector<const NamedDecl *> resolveCalleeOfCallExpr(
const CallExpr *CE);
39 std::vector<const NamedDecl *>
40 resolveUsingValueDecl(
const UnresolvedUsingValueDecl *UUVD);
41 std::vector<const NamedDecl *>
42 resolveDependentNameType(
const DependentNameType *DNT);
43 std::vector<const NamedDecl *> resolveTemplateSpecializationType(
44 const DependentTemplateSpecializationType *DTST);
45 QualType resolveNestedNameSpecifierToType(
const NestedNameSpecifier *NNS);
52 llvm::SmallSet<const DependentNameType *, 4> SeenDependentNameTypes;
63 std::vector<const NamedDecl *>
64 resolveDependentMember(QualType
T, DeclarationName Name,
65 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter);
69 QualType resolveExprToType(
const Expr *
E);
70 std::vector<const NamedDecl *> resolveExprToDecls(
const Expr *
E);
75 TagDecl *resolveTypeToTagDecl(
const Type *
T);
84 std::vector<const NamedDecl *>
85 lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
86 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter);
89 DeclarationName Name);
94const auto NoFilter = [](
const NamedDecl *
D) {
return true; };
95const auto NonStaticFilter = [](
const NamedDecl *
D) {
96 return D->isCXXInstanceMember();
98const auto StaticFilter = [](
const NamedDecl *
D) {
99 return !
D->isCXXInstanceMember();
101const auto ValueFilter = [](
const NamedDecl *
D) {
return isa<ValueDecl>(
D); };
102const auto TypeFilter = [](
const NamedDecl *
D) {
return isa<TypeDecl>(
D); };
103const auto TemplateFilter = [](
const NamedDecl *
D) {
104 return isa<TemplateDecl>(
D);
107QualType resolveDeclsToType(
const std::vector<const NamedDecl *> &Decls,
109 if (Decls.size() != 1)
111 if (
const auto *TD = dyn_cast<TypeDecl>(Decls[0])) {
114 if (
const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
115 return VD->getType();
120TemplateName getReferencedTemplateName(
const Type *
T) {
121 if (
const auto *TST =
T->
getAs<TemplateSpecializationType>()) {
122 return TST->getTemplateName();
124 if (
const auto *DTST =
T->
getAs<DeducedTemplateSpecializationType>()) {
125 return DTST->getTemplateName();
127 return TemplateName();
133TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(
const Type *
T) {
139 if (
const auto *DNT =
T->
getAs<DependentNameType>()) {
140 T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx)
147 if (
auto *TT =
T->
getAs<TagType>()) {
148 return TT->getDecl();
151 if (
const auto *ICNT =
T->
getAs<InjectedClassNameType>())
152 T = ICNT->getInjectedSpecializationType().getTypePtrOrNull();
156 TemplateName TN = getReferencedTemplateName(
T);
160 const ClassTemplateDecl *TD =
161 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
165 return TD->getTemplatedDecl();
168QualType HeuristicResolverImpl::getPointeeType(QualType
T) {
179 auto ArrowOps = resolveDependentMember(
181 if (ArrowOps.empty())
190 auto *TST =
T->
getAs<TemplateSpecializationType>();
193 if (TST->template_arguments().size() == 0)
195 const TemplateArgument &FirstArg = TST->template_arguments()[0];
198 return FirstArg.getAsType();
201std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
202 const CXXDependentScopeMemberExpr *ME) {
214 if (NestedNameSpecifier *NNS = ME->getQualifier()) {
215 if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS);
216 !QualifierType.isNull()) {
218 resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
231 Expr *
Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
232 QualType BaseType = ME->getBaseType();
235 if (BaseType.isNull())
238 if (
const auto *BT = BaseType->getAs<BuiltinType>()) {
242 if (
Base && BT->getKind() == BuiltinType::Dependent) {
243 BaseType = resolveExprToType(
Base);
244 if (BaseType.isNull())
248 if (
const auto *AT = BaseType->getContainedAutoType()) {
254 if (AT->isUndeducedAutoType()) {
255 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Base)) {
256 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
258 BaseType = resolveExprToType(VD->getInit());
263 return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
266std::vector<const NamedDecl *>
267HeuristicResolverImpl::resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE) {
268 return resolveDependentMember(
269 resolveNestedNameSpecifierToType(RE->getQualifier()), RE->getDeclName(),
273std::vector<const NamedDecl *>
274HeuristicResolverImpl::resolveTypeOfCallExpr(
const CallExpr *CE) {
275 QualType CalleeType = resolveExprToType(CE->getCallee());
276 if (CalleeType.isNull())
278 if (
const auto *FnTypePtr = CalleeType->getAs<PointerType>())
279 CalleeType = FnTypePtr->getPointeeType();
280 if (
const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
282 resolveTypeToTagDecl(FnType->getReturnType().getTypePtr())) {
289std::vector<const NamedDecl *>
290HeuristicResolverImpl::resolveCalleeOfCallExpr(
const CallExpr *CE) {
291 if (
const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
295 return resolveExprToDecls(CE->getCallee());
298std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
299 const UnresolvedUsingValueDecl *UUVD) {
300 return resolveDependentMember(QualType(UUVD->getQualifier()->getAsType(), 0),
301 UUVD->getNameInfo().getName(), ValueFilter);
304std::vector<const NamedDecl *>
305HeuristicResolverImpl::resolveDependentNameType(
const DependentNameType *DNT) {
306 if (
auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted)
308 return resolveDependentMember(
309 resolveNestedNameSpecifierToType(DNT->getQualifier()),
310 DNT->getIdentifier(), TypeFilter);
313std::vector<const NamedDecl *>
314HeuristicResolverImpl::resolveTemplateSpecializationType(
315 const DependentTemplateSpecializationType *DTST) {
316 return resolveDependentMember(
317 resolveNestedNameSpecifierToType(DTST->getQualifier()),
318 DTST->getIdentifier(), TemplateFilter);
321std::vector<const NamedDecl *>
322HeuristicResolverImpl::resolveExprToDecls(
const Expr *
E) {
323 if (
const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(
E)) {
324 return resolveMemberExpr(ME);
326 if (
const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(
E)) {
327 return resolveDeclRefExpr(RE);
329 if (
const auto *OE = dyn_cast<OverloadExpr>(
E)) {
330 return {OE->decls_begin(), OE->decls_end()};
332 if (
const auto *CE = dyn_cast<CallExpr>(
E)) {
333 return resolveTypeOfCallExpr(CE);
335 if (
const auto *ME = dyn_cast<MemberExpr>(
E))
336 return {ME->getMemberDecl()};
341QualType HeuristicResolverImpl::resolveExprToType(
const Expr *
E) {
342 std::vector<const NamedDecl *> Decls = resolveExprToDecls(
E);
344 return resolveDeclsToType(Decls, Ctx);
349QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType(
350 const NestedNameSpecifier *NNS) {
358 switch (NNS->getKind()) {
361 return QualType(NNS->getAsType(), 0);
363 return resolveDeclsToType(
364 resolveDependentMember(
365 resolveNestedNameSpecifierToType(NNS->getPrefix()),
366 NNS->getAsIdentifier(), TypeFilter),
381 DeclarationName Name) {
382 Path.Decls = RD->lookup(Name).begin();
390bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
392 DeclarationName Name) {
393 TagDecl *TD = resolveTypeToTagDecl(
Specifier->getType().getTypePtr());
394 if (
const auto *RD = dyn_cast_if_present<CXXRecordDecl>(TD)) {
400std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
401 CXXRecordDecl *RD, DeclarationName Name,
402 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
403 std::vector<const NamedDecl *> Results;
406 bool AnyOrdinaryMembers =
false;
407 for (
const NamedDecl *ND : RD->lookup(Name)) {
409 AnyOrdinaryMembers =
true;
411 Results.push_back(ND);
413 if (AnyOrdinaryMembers)
419 if (!RD->lookupInBases(
421 return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
428 Results.push_back(*I);
433std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
434 QualType QT, DeclarationName Name,
435 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
436 const Type *
T = QT.getTypePtrOrNull();
439 TagDecl *TD = resolveTypeToTagDecl(
T);
442 if (
auto *ED = dyn_cast<EnumDecl>(TD)) {
443 auto Result = ED->lookup(Name);
446 if (
auto *RD = dyn_cast<CXXRecordDecl>(TD)) {
447 if (!RD->hasDefinition())
449 RD = RD->getDefinition();
450 return lookupDependentName(RD, Name, [&](
const NamedDecl *ND) {
453 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND)) {
454 return MD->getMethodQualifiers().compatiblyIncludes(QT.getQualifiers(),
466 return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME);
470 return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE);
472std::vector<const NamedDecl *>
474 return HeuristicResolverImpl(Ctx).resolveTypeOfCallExpr(CE);
476std::vector<const NamedDecl *>
478 return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(CE);
482 return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD);
486 return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
488std::vector<const NamedDecl *>
491 return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
495 return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
498 return HeuristicResolverImpl(Ctx).getPointeeType(
T);
Defines the clang::ASTContext interface.
static bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name)
static bool isOrdinaryMember(const NamedDecl *ND)
static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, DeclarationName Name)
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
static QualType getPointeeType(const MemRegion *R)
C Language Family Type Representation.
const NestedNameSpecifier * Specifier
DeclarationNameTable DeclarationNames
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
Represents a C++ member access expression where the actual member referenced could not be resolved be...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
lookup_result::iterator lookup_iterator
@ IDNS_Ordinary
Ordinary names.
@ IDNS_Member
Members, declared with object declarations within tag definitions.
@ IDNS_Tag
Tags, declared with 'struct foo;' and referenced with 'struct foo'.
Represents a qualified type name for which the type name is dependent.
A qualified reference to a name whose declaration cannot yet be resolved.
Represents a template specialization type whose template cannot be resolved, e.g.
std::vector< const NamedDecl * > resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) const
const QualType getPointeeType(QualType T) const
std::vector< const NamedDecl * > resolveMemberExpr(const CXXDependentScopeMemberExpr *ME) const
QualType resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const
std::vector< const NamedDecl * > resolveCalleeOfCallExpr(const CallExpr *CE) const
std::vector< const NamedDecl * > resolveTypeOfCallExpr(const CallExpr *CE) const
std::vector< const NamedDecl * > resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const
std::vector< const NamedDecl * > resolveTemplateSpecializationType(const DependentTemplateSpecializationType *DTST) const
std::vector< const NamedDecl * > resolveDependentNameType(const DependentNameType *DNT) const
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
@ TypeSpec
A type, stored as a Type*.
@ TypeSpecWithTemplate
A type that was preceded by the 'template' keyword, stored as a Type*.
@ Identifier
An identifier, stored as an IdentifierInfo*.
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
@ Type
The template argument is a type.
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
QualType getCanonicalTypeInternal() const
const T * getAs() const
Member-template getAs<specific type>'.
Represents a dependent using declaration which was not marked with typename.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
const FunctionProtoType * T