16#include "llvm/ADT/identity.h"
29class HeuristicResolverImpl {
31 HeuristicResolverImpl(ASTContext &Ctx) : Ctx(Ctx) {}
35 std::vector<const NamedDecl *>
36 resolveMemberExpr(
const CXXDependentScopeMemberExpr *ME);
37 std::vector<const NamedDecl *>
38 resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE);
39 std::vector<const NamedDecl *> resolveTypeOfCallExpr(
const CallExpr *CE);
40 std::vector<const NamedDecl *> resolveCalleeOfCallExpr(
const CallExpr *CE);
41 std::vector<const NamedDecl *>
42 resolveUsingValueDecl(
const UnresolvedUsingValueDecl *UUVD);
43 std::vector<const NamedDecl *>
44 resolveDependentNameType(
const DependentNameType *DNT);
45 std::vector<const NamedDecl *> resolveTemplateSpecializationType(
46 const DependentTemplateSpecializationType *DTST);
47 QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS);
49 std::vector<const NamedDecl *>
50 lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
51 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter);
52 TagDecl *resolveTypeToTagDecl(QualType
T);
53 QualType simplifyType(QualType Type,
const Expr *
E,
bool UnwrapPointer);
54 FunctionProtoTypeLoc getFunctionProtoTypeLoc(
const Expr *Fn);
71 std::vector<const NamedDecl *>
72 resolveDependentMember(QualType
T, DeclarationName Name,
73 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter);
77 QualType resolveExprToType(
const Expr *
E);
78 std::vector<const NamedDecl *> resolveExprToDecls(
const Expr *
E);
80 bool findOrdinaryMemberInDependentClasses(
const CXXBaseSpecifier *
Specifier,
82 DeclarationName Name);
87const auto NoFilter = [](
const NamedDecl *
D) {
return true; };
88const auto NonStaticFilter = [](
const NamedDecl *
D) {
89 return D->isCXXInstanceMember();
91const auto StaticFilter = [](
const NamedDecl *
D) {
92 return !
D->isCXXInstanceMember();
94const auto ValueFilter = [](
const NamedDecl *
D) {
return isa<ValueDecl>(
D); };
95const auto TypeFilter = [](
const NamedDecl *
D) {
return isa<TypeDecl>(
D); };
96const auto TemplateFilter = [](
const NamedDecl *
D) {
97 return isa<TemplateDecl>(
D);
100QualType resolveDeclsToType(
const std::vector<const NamedDecl *> &Decls,
102 if (Decls.size() != 1)
104 if (
const auto *TD = dyn_cast<TypeDecl>(Decls[0]))
106 if (
const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
107 return VD->getType();
113 if (
const auto *TST =
T->
getAs<TemplateSpecializationType>()) {
114 return TST->getTemplateName();
116 if (
const auto *DTST =
T->
getAs<DeducedTemplateSpecializationType>()) {
117 return DTST->getTemplateName();
125TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
126 const Type *
T = QT.getTypePtrOrNull();
133 if (
const auto *DNT =
T->
getAs<DependentNameType>()) {
134 T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx)
144 if (
const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
146 return CTSD->getSpecializedTemplate()->getTemplatedDecl();
156 const ClassTemplateDecl *TD =
157 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
161 return TD->getTemplatedDecl();
164QualType HeuristicResolverImpl::getPointeeType(QualType
T) {
175 auto ArrowOps = resolveDependentMember(
177 if (ArrowOps.empty())
186 auto *TST =
T->
getAs<TemplateSpecializationType>();
189 if (TST->template_arguments().size() == 0)
191 const TemplateArgument &FirstArg = TST->template_arguments()[0];
194 return FirstArg.getAsType();
197QualType HeuristicResolverImpl::simplifyType(QualType Type,
const Expr *
E,
198 bool UnwrapPointer) {
199 bool DidUnwrapPointer =
false;
203 struct TypeExprPair {
205 const Expr *
E =
nullptr;
207 TypeExprPair Current{
Type,
E};
208 auto SimplifyOneStep = [UnwrapPointer, &DidUnwrapPointer,
209 this](TypeExprPair
T) -> TypeExprPair {
212 DidUnwrapPointer =
true;
216 if (
const auto *RT =
T.
Type->getAs<ReferenceType>()) {
218 return {RT->getPointeeType()};
220 if (
const auto *BT =
T.
Type->getAs<BuiltinType>()) {
224 if (
T.E && BT->getKind() == BuiltinType::Dependent) {
225 return {resolveExprToType(
T.E),
T.E};
228 if (
const auto *AT =
T.
Type->getContainedAutoType()) {
236 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
T.E)) {
237 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
238 if (
auto *
Init = VD->getInit())
239 return {resolveExprToType(
Init),
Init};
244 if (
const auto *TTPT = dyn_cast_if_present<TemplateTypeParmType>(
T.
Type)) {
249 if (
const auto *TTPD = TTPT->getDecl()) {
250 if (TTPD->hasDefaultArgument()) {
251 const auto &DefaultArg = TTPD->getDefaultArgument().getArgument();
253 return {DefaultArg.getAsType()};
261 if (!
T.
Type.isNull() &&
262 (
T.
Type->isUndeducedAutoType() ||
T.
Type->isTemplateTypeParmType())) {
263 if (
auto *DRE = dyn_cast_if_present<DeclRefExpr>(
T.E)) {
264 auto *PrDecl = dyn_cast<ParmVarDecl>(DRE->getDecl());
265 if (PrDecl && PrDecl->isExplicitObjectParameter()) {
267 dyn_cast<TagDecl>(PrDecl->getDeclContext()->getParent());
277 size_t StepCount = 0;
278 const size_t MaxSteps = 64;
279 while (!Current.Type.isNull() && StepCount++ < MaxSteps) {
280 TypeExprPair
New = SimplifyOneStep(Current);
281 if (
New.Type == Current.Type)
285 if (UnwrapPointer && !DidUnwrapPointer)
290std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
291 const CXXDependentScopeMemberExpr *ME) {
303 if (NestedNameSpecifier NNS = ME->getQualifier()) {
304 if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS);
305 !QualifierType.isNull()) {
307 resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
320 Expr *
Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
321 QualType BaseType = ME->getBaseType();
322 BaseType = simplifyType(BaseType,
Base, ME->isArrow());
323 return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
326std::vector<const NamedDecl *>
327HeuristicResolverImpl::resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE) {
328 QualType
Qualifier = resolveNestedNameSpecifierToType(RE->getQualifier());
329 Qualifier = simplifyType(Qualifier,
nullptr,
false);
330 return resolveDependentMember(Qualifier, RE->getDeclName(), StaticFilter);
333std::vector<const NamedDecl *>
334HeuristicResolverImpl::resolveTypeOfCallExpr(
const CallExpr *CE) {
335 QualType CalleeType = resolveExprToType(CE->getCallee());
336 if (CalleeType.isNull())
338 if (
const auto *FnTypePtr = CalleeType->getAs<PointerType>())
339 CalleeType = FnTypePtr->getPointeeType();
340 if (
const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
341 if (
const auto *
D = resolveTypeToTagDecl(FnType->getReturnType())) {
348std::vector<const NamedDecl *>
349HeuristicResolverImpl::resolveCalleeOfCallExpr(
const CallExpr *CE) {
350 if (
const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
354 return resolveExprToDecls(CE->getCallee());
357std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
358 const UnresolvedUsingValueDecl *UUVD) {
359 NestedNameSpecifier
Qualifier = UUVD->getQualifier();
362 return resolveDependentMember(QualType(
Qualifier.getAsType(), 0),
363 UUVD->getNameInfo().getName(), ValueFilter);
366std::vector<const NamedDecl *>
367HeuristicResolverImpl::resolveDependentNameType(
const DependentNameType *DNT) {
368 if (
auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted)
370 return resolveDependentMember(
371 resolveNestedNameSpecifierToType(DNT->getQualifier()),
372 DNT->getIdentifier(), TypeFilter);
375std::vector<const NamedDecl *>
376HeuristicResolverImpl::resolveTemplateSpecializationType(
377 const DependentTemplateSpecializationType *DTST) {
378 const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
379 return resolveDependentMember(
380 resolveNestedNameSpecifierToType(DTN.getQualifier()),
381 DTN.getName().getIdentifier(), TemplateFilter);
384std::vector<const NamedDecl *>
385HeuristicResolverImpl::resolveExprToDecls(
const Expr *
E) {
386 if (
const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(
E)) {
387 return resolveMemberExpr(ME);
389 if (
const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(
E)) {
390 return resolveDeclRefExpr(RE);
392 if (
const auto *OE = dyn_cast<OverloadExpr>(
E)) {
393 return {OE->decls_begin(), OE->decls_end()};
395 if (
const auto *CE = dyn_cast<CallExpr>(
E)) {
396 return resolveTypeOfCallExpr(CE);
398 if (
const auto *ME = dyn_cast<MemberExpr>(
E))
399 return {ME->getMemberDecl()};
404QualType HeuristicResolverImpl::resolveExprToType(
const Expr *
E) {
405 std::vector<const NamedDecl *> Decls = resolveExprToDecls(
E);
407 return resolveDeclsToType(Decls, Ctx);
412QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType(
413 NestedNameSpecifier NNS) {
418 switch (NNS.getKind()) {
420 const auto *
T = NNS.getAsType();
423 if (
const auto *DTN = dyn_cast<DependentNameType>(
T))
424 return resolveDeclsToType(
425 resolveDependentMember(
426 resolveNestedNameSpecifierToType(DTN->getQualifier()),
427 DTN->getIdentifier(), TypeFilter),
429 return QualType(
T, 0);
443 DeclarationName Name) {
444 Path.Decls = RD->lookup(Name).begin();
452bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
454 DeclarationName Name) {
455 TagDecl *TD = resolveTypeToTagDecl(
Specifier->getType());
456 if (
const auto *RD = dyn_cast_if_present<CXXRecordDecl>(TD)) {
462std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
463 CXXRecordDecl *RD, DeclarationName Name,
464 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
465 std::vector<const NamedDecl *> Results;
468 bool AnyOrdinaryMembers =
false;
469 for (
const NamedDecl *ND : RD->lookup(Name)) {
471 AnyOrdinaryMembers =
true;
473 Results.push_back(ND);
475 if (AnyOrdinaryMembers)
481 if (!RD->lookupInBases(
483 return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
490 Results.push_back(*I);
495std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
496 QualType QT, DeclarationName Name,
497 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
498 TagDecl *TD = resolveTypeToTagDecl(QT);
501 if (
auto *ED = dyn_cast<EnumDecl>(TD)) {
502 auto Result = ED->lookup(Name);
505 if (
auto *RD = dyn_cast<CXXRecordDecl>(TD)) {
506 if (!RD->hasDefinition())
508 RD = RD->getDefinition();
509 return lookupDependentName(RD, Name, [&](
const NamedDecl *ND) {
512 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND)) {
513 return !MD->isInstance() ||
514 MD->getMethodQualifiers().compatiblyIncludes(QT.getQualifiers(),
524HeuristicResolverImpl::getFunctionProtoTypeLoc(
const Expr *Fn) {
526 const Expr *NakedFn =
Fn->IgnoreParenCasts();
527 if (
const auto *
T = NakedFn->getType().getTypePtr()->
getAs<TypedefType>()) {
528 Target =
T->getDecl()->getTypeSourceInfo()->getTypeLoc();
529 }
else if (
const auto *DR = dyn_cast<DeclRefExpr>(NakedFn)) {
530 const auto *
D = DR->getDecl();
531 if (
const auto *
const VD = dyn_cast<VarDecl>(
D)) {
532 Target = VD->getTypeSourceInfo()->getTypeLoc();
534 }
else if (
const auto *ME = dyn_cast<MemberExpr>(NakedFn)) {
535 const auto *MD = ME->getMemberDecl();
536 if (
const auto *FD = dyn_cast<FieldDecl>(MD)) {
537 Target = FD->getTypeSourceInfo()->getTypeLoc();
546 if (
auto P =
Target.getAs<PointerTypeLoc>()) {
550 if (
auto A =
Target.getAs<AttributedTypeLoc>()) {
551 Target = A.getModifiedLoc();
554 if (
auto P =
Target.getAs<ParenTypeLoc>()) {
561 if (
auto F =
Target.getAs<FunctionProtoTypeLoc>()) {
565 if (llvm::all_of(F.getParams(), llvm::identity<ParmVarDecl *>()))
576 return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME);
580 return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE);
582std::vector<const NamedDecl *>
584 return HeuristicResolverImpl(Ctx).resolveTypeOfCallExpr(CE);
586std::vector<const NamedDecl *>
588 return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(CE);
592 return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD);
596 return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
598std::vector<const NamedDecl *>
601 return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
605 return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
609 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
610 return HeuristicResolverImpl(Ctx).lookupDependentName(RD, Name, Filter);
613 return HeuristicResolverImpl(Ctx).getPointeeType(
T);
616 return HeuristicResolverImpl(Ctx).resolveTypeToTagDecl(
T);
619 bool UnwrapPointer) {
620 return HeuristicResolverImpl(Ctx).simplifyType(
Type,
E, UnwrapPointer);
625 return HeuristicResolverImpl(Ctx).getFunctionProtoTypeLoc(Fn);
Defines the clang::ASTContext interface.
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.
llvm::MachO::Target Target
static QualType getPointeeType(const MemRegion *R)
C Language Family Type Representation.
NestedNameSpecifier Specifier
DeclarationNameTable DeclarationNames
CanQualType getCanonicalTypeDeclType(const TypeDecl *TD) const
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents a C++ member access expression where the actual member referenced could not be resolved be...
Represents a C++ struct/union/class.
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'.
The name of a declaration.
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.
This represents one expression.
std::vector< const NamedDecl * > resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) const
const QualType getPointeeType(QualType T) const
QualType simplifyType(QualType Type, const Expr *E, bool UnwrapPointer)
std::vector< const NamedDecl * > resolveMemberExpr(const CXXDependentScopeMemberExpr *ME) const
FunctionProtoTypeLoc getFunctionProtoTypeLoc(const Expr *Fn) const
QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS) const
std::vector< const NamedDecl * > resolveCalleeOfCallExpr(const CallExpr *CE) const
TagDecl * resolveTypeToTagDecl(QualType T) 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
std::vector< const NamedDecl * > lookupDependentName(CXXRecordDecl *RD, DeclarationName Name, llvm::function_ref< bool(const NamedDecl *ND)> Filter)
This represents a decl that may have a name.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
@ Type
A type, stored as a Type*.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Represents the declaration of a struct/union/class/enum.
@ Type
The template argument is a type.
The base class of the type hierarchy.
bool isUndeducedAutoType() const
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
Type(TypeClass tc, QualType canon, TypeDependence Dependence)
TagDecl * getAsTagDecl() const
Retrieves the TagDecl that this type refers to, either because the type is a TagType or because it is...
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.
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ TSK_Undeclared
This template specialization was formed from a template-id but has not yet been declared,...