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 *>
45 resolveTemplateSpecializationType(
const TemplateSpecializationType *TST);
46 QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS);
48 std::vector<const NamedDecl *>
49 lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
50 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter);
51 TagDecl *resolveTypeToTagDecl(QualType
T);
52 QualType simplifyType(QualType
Type,
const Expr *E,
bool UnwrapPointer);
53 FunctionProtoTypeLoc getFunctionProtoTypeLoc(
const Expr *Fn);
59 llvm::SmallPtrSet<const DependentNameType *, 4> SeenDependentNameTypes;
70 std::vector<const NamedDecl *>
71 resolveDependentMember(QualType
T, DeclarationName Name,
72 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter);
76 QualType resolveExprToType(
const Expr *E);
77 std::vector<const NamedDecl *> resolveExprToDecls(
const Expr *E);
79 bool findOrdinaryMemberInDependentClasses(
const CXXBaseSpecifier *Specifier,
81 DeclarationName Name);
86const auto NoFilter = [](
const NamedDecl *D) {
return true; };
87const auto NonStaticFilter = [](
const NamedDecl *D) {
88 return D->isCXXInstanceMember();
90const auto StaticFilter = [](
const NamedDecl *D) {
91 return !D->isCXXInstanceMember();
95const auto TemplateFilter = [](
const NamedDecl *D) {
99QualType resolveDeclsToType(
const std::vector<const NamedDecl *> &Decls,
101 if (Decls.size() != 1)
103 if (
const auto *TD = dyn_cast<TypeDecl>(Decls[0]))
105 if (
const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
106 return VD->getType();
112 if (
const auto *TST =
T->getAs<TemplateSpecializationType>()) {
113 return TST->getTemplateName();
115 if (
const auto *DTST =
T->getAs<DeducedTemplateSpecializationType>()) {
116 return DTST->getTemplateName();
125 const Type *
T = QT.getTypePtrOrNull();
132 if (
const auto *DNT =
T->
getAs<DependentNameType>()) {
133 T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx)
143 if (
const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
144 if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared) {
145 return CTSD->getSpecializedTemplate()->getTemplatedDecl();
155 const ClassTemplateDecl *TD =
156 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
160 return TD->getTemplatedDecl();
163QualType HeuristicResolverImpl::getPointeeType(QualType
T) {
174 auto ArrowOps = resolveDependentMember(
176 if (ArrowOps.empty())
185 auto *TST =
T->
getAs<TemplateSpecializationType>();
188 if (TST->template_arguments().size() == 0)
190 const TemplateArgument &FirstArg = TST->template_arguments()[0];
191 if (FirstArg.getKind() != TemplateArgument::Type)
193 return FirstArg.getAsType();
196QualType HeuristicResolverImpl::simplifyType(QualType
Type,
const Expr *E,
197 bool UnwrapPointer) {
198 bool DidUnwrapPointer =
false;
202 struct TypeExprPair {
204 const Expr *E =
nullptr;
206 TypeExprPair Current{Type, E};
207 auto SimplifyOneStep = [UnwrapPointer, &DidUnwrapPointer,
208 this](TypeExprPair
T) -> TypeExprPair {
211 DidUnwrapPointer =
true;
215 if (
const auto *RT =
T.
Type->getAs<ReferenceType>()) {
217 return {RT->getPointeeType()};
219 if (
const auto *BT =
T.
Type->getAs<BuiltinType>()) {
223 if (
T.E && BT->getKind() == BuiltinType::Dependent) {
224 return {resolveExprToType(
T.E),
T.E};
227 if (
const auto *AT =
T.
Type->getContainedAutoType()) {
235 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
T.E)) {
236 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
237 if (
auto *Init = VD->getInit())
238 return {resolveExprToType(Init),
Init};
243 if (
const auto *TTPT = dyn_cast_if_present<TemplateTypeParmType>(
T.
Type)) {
248 if (
const auto *TTPD = TTPT->getDecl()) {
249 if (TTPD->hasDefaultArgument()) {
250 const auto &DefaultArg = TTPD->getDefaultArgument().getArgument();
251 if (DefaultArg.getKind() == TemplateArgument::Type) {
252 return {DefaultArg.getAsType()};
260 if (!
T.
Type.isNull() &&
261 (
T.
Type->isUndeducedAutoType() ||
T.
Type->isTemplateTypeParmType())) {
262 if (
auto *DRE = dyn_cast_if_present<DeclRefExpr>(
T.E)) {
263 auto *PrDecl = dyn_cast<ParmVarDecl>(DRE->getDecl());
264 if (PrDecl && PrDecl->isExplicitObjectParameter()) {
266 dyn_cast<TagDecl>(PrDecl->getDeclContext()->getParent());
276 size_t StepCount = 0;
277 const size_t MaxSteps = 64;
278 while (!Current.Type.isNull() && StepCount++ < MaxSteps) {
279 TypeExprPair
New = SimplifyOneStep(Current);
280 if (
New.Type == Current.Type)
284 if (UnwrapPointer && !DidUnwrapPointer)
289std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
290 const CXXDependentScopeMemberExpr *ME) {
302 if (NestedNameSpecifier NNS = ME->getQualifier()) {
303 if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS);
304 !QualifierType.isNull()) {
306 resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
319 Expr *
Base = ME->isImplicitAccess() ?
nullptr : ME->getBase();
320 QualType BaseType = ME->getBaseType();
321 BaseType = simplifyType(BaseType, Base, ME->isArrow());
322 return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
325std::vector<const NamedDecl *>
326HeuristicResolverImpl::resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE) {
327 QualType
Qualifier = resolveNestedNameSpecifierToType(RE->getQualifier());
328 Qualifier = simplifyType(Qualifier,
nullptr,
false);
329 return resolveDependentMember(Qualifier, RE->getDeclName(), StaticFilter);
332std::vector<const NamedDecl *>
333HeuristicResolverImpl::resolveTypeOfCallExpr(
const CallExpr *CE) {
334 QualType CalleeType = resolveExprToType(CE->getCallee());
335 if (CalleeType.isNull())
337 if (
const auto *FnTypePtr = CalleeType->getAs<PointerType>())
338 CalleeType = FnTypePtr->getPointeeType();
339 if (
const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
340 if (
const auto *D = resolveTypeToTagDecl(FnType->getReturnType())) {
347std::vector<const NamedDecl *>
348HeuristicResolverImpl::resolveCalleeOfCallExpr(
const CallExpr *CE) {
349 if (
const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
353 return resolveExprToDecls(CE->getCallee());
356std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
357 const UnresolvedUsingValueDecl *UUVD) {
358 NestedNameSpecifier
Qualifier = UUVD->getQualifier();
359 if (
Qualifier.getKind() != NestedNameSpecifier::Kind::Type)
361 return resolveDependentMember(QualType(
Qualifier.getAsType(), 0),
362 UUVD->getNameInfo().getName(), ValueFilter);
365std::vector<const NamedDecl *>
366HeuristicResolverImpl::resolveDependentNameType(
const DependentNameType *DNT) {
367 if (
auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted)
369 return resolveDependentMember(
370 resolveNestedNameSpecifierToType(DNT->getQualifier()),
371 DNT->getIdentifier(), TypeFilter);
374std::vector<const NamedDecl *>
375HeuristicResolverImpl::resolveTemplateSpecializationType(
376 const TemplateSpecializationType *TST) {
377 const DependentTemplateStorage &DTN =
378 *TST->getTemplateName().getAsDependentTemplateName();
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()) {
419 case NestedNameSpecifier::Kind::Type: {
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(
453 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
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(
482 [&](
const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
483 return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
487 for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
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>()) {
547 Target = P.getPointeeLoc();
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::is_contained(F.getParams(),
nullptr))
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);
595 const DependentNameType *DNT)
const {
596 return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
598std::vector<const NamedDecl *>
600 const TemplateSpecializationType *TST)
const {
601 return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(TST);
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.
DeclarationNameTable DeclarationNames
CanQualType getCanonicalTypeDeclType(const TypeDecl *TD) const
CanQualType getCanonicalTagType(const TagDecl *TD) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
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.
A qualified reference to a name whose declaration cannot yet be resolved.
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
std::vector< const NamedDecl * > resolveTemplateSpecializationType(const TemplateSpecializationType *TST) 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 * > 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>::".
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Represents the declaration of a struct/union/class/enum.
Represents a C++ template name within the type system.
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.
bool Init(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
nullptr
This class represents a compute construct, representing a 'Kind' of βparallelβ, 'serial',...
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ Type
The name was classified as a type.