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 *> 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 QualType resolveExprToType(
const Expr *E);
54 FunctionProtoTypeLoc getFunctionProtoTypeLoc(
const Expr *Fn);
60 llvm::SmallPtrSet<const DependentNameType *, 4> SeenDependentNameTypes;
71 std::vector<const NamedDecl *>
72 resolveDependentMember(QualType T, DeclarationName Name,
73 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter);
75 std::vector<const NamedDecl *> resolveExprToDecls(
const Expr *E);
76 QualType resolveTypeOfCallExpr(
const CallExpr *CE);
78 bool findOrdinaryMemberInDependentClasses(
const CXXBaseSpecifier *Specifier,
80 DeclarationName Name);
85const auto NoFilter = [](
const NamedDecl *D) {
return true; };
86const auto NonStaticFilter = [](
const NamedDecl *D) {
87 return D->isCXXInstanceMember();
89const auto StaticFilter = [](
const NamedDecl *D) {
90 return !D->isCXXInstanceMember();
94const auto TemplateFilter = [](
const NamedDecl *D) {
99 if (
const auto *TempD = dyn_cast<TemplateDecl>(D)) {
100 D = TempD->getTemplatedDecl();
102 if (
const auto *TD = dyn_cast<TypeDecl>(D))
104 if (
const auto *VD = dyn_cast<ValueDecl>(D)) {
105 return VD->getType();
110QualType resolveDeclsToType(
const std::vector<const NamedDecl *> &Decls,
112 if (Decls.size() != 1)
114 return resolveDeclToType(Decls[0], Ctx);
118 if (
const auto *TST = T->getAs<TemplateSpecializationType>()) {
119 return TST->getTemplateName();
121 if (
const auto *DTST = T->getAs<DeducedTemplateSpecializationType>()) {
122 return DTST->getTemplateName();
131 const Type *T = QT.getTypePtrOrNull();
136 T = T->getCanonicalTypeInternal().getTypePtr();
138 if (
const auto *DNT = T->getAs<DependentNameType>()) {
139 T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx)
143 T = T->getCanonicalTypeInternal().getTypePtr();
146 if (
auto *TD = T->getAsTagDecl()) {
149 if (
const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
150 if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared) {
151 return CTSD->getSpecializedTemplate()->getTemplatedDecl();
161 const ClassTemplateDecl *TD =
162 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
166 return TD->getTemplatedDecl();
169QualType HeuristicResolverImpl::getPointeeType(QualType T) {
173 if (T->isPointerType())
180 auto ArrowOps = resolveDependentMember(
182 if (ArrowOps.empty())
191 auto *TST = T->getAs<TemplateSpecializationType>();
194 if (TST->template_arguments().size() == 0)
196 const TemplateArgument &FirstArg = TST->template_arguments()[0];
197 if (FirstArg.getKind() != TemplateArgument::Type)
199 return FirstArg.getAsType();
202QualType HeuristicResolverImpl::simplifyType(QualType
Type,
const Expr *E,
203 bool UnwrapPointer) {
204 bool DidUnwrapPointer =
false;
208 struct TypeExprPair {
210 const Expr *E =
nullptr;
212 TypeExprPair Current{Type, E};
213 auto SimplifyOneStep = [UnwrapPointer, &DidUnwrapPointer,
214 this](TypeExprPair T) -> TypeExprPair {
216 if (QualType Pointee =
getPointeeType(T.Type); !Pointee.isNull()) {
217 DidUnwrapPointer =
true;
221 if (
const auto *RT = T.Type->getAs<ReferenceType>()) {
223 return {RT->getPointeeType()};
225 if (
const auto *BT = T.Type->getAs<BuiltinType>()) {
229 if (T.E && BT->getKind() == BuiltinType::Dependent) {
230 return {resolveExprToType(T.E), T.E};
233 if (
const auto *AT = T.Type->getContainedAutoType()) {
240 if (T.E && AT->isUndeducedAutoType()) {
241 if (
const auto *DRE = dyn_cast<DeclRefExpr>(T.E)) {
242 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
243 if (
auto *Init = VD->getInit())
244 return {resolveExprToType(Init),
Init};
249 if (
const auto *TTPT = dyn_cast_if_present<TemplateTypeParmType>(T.Type)) {
254 if (
const auto *TTPD = TTPT->getDecl()) {
255 if (TTPD->hasDefaultArgument()) {
256 const auto &DefaultArg = TTPD->getDefaultArgument().getArgument();
257 if (DefaultArg.getKind() == TemplateArgument::Type) {
258 return {DefaultArg.getAsType()};
266 if (
const auto *TST =
267 dyn_cast_if_present<TemplateSpecializationType>(T.Type)) {
268 if (
const auto *TTPD = dyn_cast_if_present<TemplateTemplateParmDecl>(
269 TST->getTemplateName().getAsTemplateDecl())) {
270 if (TTPD->hasDefaultArgument()) {
271 const auto &DefaultArg = TTPD->getDefaultArgument().getArgument();
272 if (DefaultArg.getKind() == TemplateArgument::Template) {
273 if (
const auto *CTD = dyn_cast_if_present<ClassTemplateDecl>(
274 DefaultArg.getAsTemplate().getAsTemplateDecl())) {
285 if (!T.Type.isNull() &&
286 (T.Type->isUndeducedAutoType() || T.Type->isTemplateTypeParmType())) {
287 if (
auto *DRE = dyn_cast_if_present<DeclRefExpr>(T.E)) {
288 auto *PrDecl = dyn_cast<ParmVarDecl>(DRE->getDecl());
289 if (PrDecl && PrDecl->isExplicitObjectParameter()) {
291 dyn_cast<TagDecl>(PrDecl->getDeclContext()->getParent());
301 size_t StepCount = 0;
302 const size_t MaxSteps = 64;
303 while (!Current.Type.isNull() && StepCount++ < MaxSteps) {
304 TypeExprPair
New = SimplifyOneStep(Current);
305 if (
New.Type == Current.Type)
309 if (UnwrapPointer && !DidUnwrapPointer)
314std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
315 const CXXDependentScopeMemberExpr *ME) {
327 if (NestedNameSpecifier NNS = ME->getQualifier()) {
328 if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS);
329 !QualifierType.isNull()) {
331 resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
344 Expr *
Base = ME->isImplicitAccess() ?
nullptr : ME->getBase();
345 QualType BaseType = ME->getBaseType();
346 BaseType = simplifyType(BaseType, Base, ME->isArrow());
347 return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
350std::vector<const NamedDecl *>
351HeuristicResolverImpl::resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE) {
352 QualType
Qualifier = resolveNestedNameSpecifierToType(RE->getQualifier());
353 Qualifier = simplifyType(Qualifier,
nullptr,
false);
354 return resolveDependentMember(Qualifier, RE->getDeclName(), StaticFilter);
357QualType HeuristicResolverImpl::resolveTypeOfCallExpr(
const CallExpr *CE) {
361 std::vector<const NamedDecl *> CalleeDecls =
362 resolveExprToDecls(CE->getCallee());
363 QualType CommonReturnType;
364 for (
const NamedDecl *CalleeDecl : CalleeDecls) {
365 QualType CalleeType = resolveDeclToType(CalleeDecl, Ctx);
366 if (CalleeType.isNull())
368 if (
const auto *FnTypePtr = CalleeType->getAs<PointerType>())
369 CalleeType = FnTypePtr->getPointeeType();
370 if (
const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
371 QualType ReturnType =
372 simplifyType(FnType->getReturnType(),
nullptr,
false);
373 if (!CommonReturnType.isNull() && CommonReturnType != ReturnType) {
376 CommonReturnType = ReturnType;
379 return CommonReturnType;
382std::vector<const NamedDecl *>
383HeuristicResolverImpl::resolveCalleeOfCallExpr(
const CallExpr *CE) {
384 if (
const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
388 return resolveExprToDecls(CE->getCallee());
391std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
392 const UnresolvedUsingValueDecl *UUVD) {
393 NestedNameSpecifier
Qualifier = UUVD->getQualifier();
394 if (
Qualifier.getKind() != NestedNameSpecifier::Kind::Type)
396 return resolveDependentMember(QualType(
Qualifier.getAsType(), 0),
397 UUVD->getNameInfo().getName(), ValueFilter);
400std::vector<const NamedDecl *>
401HeuristicResolverImpl::resolveDependentNameType(
const DependentNameType *DNT) {
402 if (
auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted)
404 return resolveDependentMember(
405 resolveNestedNameSpecifierToType(DNT->getQualifier()),
406 DNT->getIdentifier(), TypeFilter);
409std::vector<const NamedDecl *>
410HeuristicResolverImpl::resolveTemplateSpecializationType(
411 const TemplateSpecializationType *TST) {
412 if (TST->getTemplateName().getKind() == TemplateName::DependentTemplate) {
413 const DependentTemplateStorage &DTN =
414 *TST->getTemplateName().getAsDependentTemplateName();
415 return resolveDependentMember(
416 resolveNestedNameSpecifierToType(DTN.getQualifier()),
417 DTN.getName().getIdentifier(), TemplateFilter);
422std::vector<const NamedDecl *>
423HeuristicResolverImpl::resolveExprToDecls(
const Expr *E) {
424 if (
const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(E)) {
425 return resolveMemberExpr(ME);
427 if (
const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(E)) {
428 return resolveDeclRefExpr(RE);
430 if (
const auto *OE = dyn_cast<OverloadExpr>(E)) {
431 return {OE->decls_begin(), OE->decls_end()};
433 if (
const auto *CE = dyn_cast<CallExpr>(E)) {
434 QualType T = resolveTypeOfCallExpr(CE);
435 if (
const auto *D = resolveTypeToTagDecl(T)) {
440 if (
const auto *ME = dyn_cast<MemberExpr>(E))
441 return {ME->getMemberDecl()};
442 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
443 return {DRE->getDecl()};
448QualType HeuristicResolverImpl::resolveExprToType(
const Expr *E) {
454 if (
const auto *CE = dyn_cast<CallExpr>(E)) {
455 if (QualType Resolved = resolveTypeOfCallExpr(CE); !Resolved.isNull())
465 if (
const auto *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts())) {
466 if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) {
467 if (
auto Pointee =
getPointeeType(resolveExprToType(UO->getSubExpr()));
474 std::vector<const NamedDecl *> Decls = resolveExprToDecls(E);
476 return resolveDeclsToType(Decls, Ctx);
481QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType(
482 NestedNameSpecifier NNS) {
487 switch (NNS.getKind()) {
488 case NestedNameSpecifier::Kind::Type: {
489 const auto *T = NNS.getAsType();
492 if (
const auto *DTN = dyn_cast<DependentNameType>(T))
493 return resolveDeclsToType(
494 resolveDependentMember(
495 resolveNestedNameSpecifierToType(DTN->getQualifier()),
496 DTN->getIdentifier(), TypeFilter),
498 return QualType(T, 0);
512 DeclarationName Name) {
513 Path.Decls = RD->lookup(Name).begin();
521bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
522 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
523 DeclarationName Name) {
524 TagDecl *TD = resolveTypeToTagDecl(
Specifier->getType());
525 if (
const auto *RD = dyn_cast_if_present<CXXRecordDecl>(TD)) {
531std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
532 CXXRecordDecl *RD, DeclarationName Name,
533 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
534 std::vector<const NamedDecl *> Results;
537 bool AnyOrdinaryMembers =
false;
538 for (
const NamedDecl *ND : RD->lookup(Name)) {
540 AnyOrdinaryMembers =
true;
542 Results.push_back(ND);
544 if (AnyOrdinaryMembers)
550 if (!RD->lookupInBases(
551 [&](
const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
552 return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
556 for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
559 Results.push_back(*I);
564std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
565 QualType QT, DeclarationName Name,
566 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
567 TagDecl *TD = resolveTypeToTagDecl(QT);
570 if (
auto *ED = dyn_cast<EnumDecl>(TD)) {
571 auto Result = ED->lookup(Name);
574 if (
auto *RD = dyn_cast<CXXRecordDecl>(TD)) {
575 if (!RD->hasDefinition())
577 RD = RD->getDefinition();
578 return lookupDependentName(RD, Name, [&](
const NamedDecl *ND) {
581 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND)) {
582 return !MD->isInstance() ||
583 MD->getMethodQualifiers().compatiblyIncludes(QT.getQualifiers(),
593HeuristicResolverImpl::getFunctionProtoTypeLoc(
const Expr *Fn) {
595 const Expr *NakedFn =
Fn->IgnoreParenCasts();
596 if (
const auto *T = NakedFn->getType().getTypePtr()->getAs<TypedefType>()) {
597 Target = T->getDecl()->getTypeSourceInfo()->getTypeLoc();
598 }
else if (
const auto *DR = dyn_cast<DeclRefExpr>(NakedFn)) {
599 const auto *D = DR->getDecl();
600 if (
const auto *
const VD = dyn_cast<VarDecl>(D)) {
601 Target = VD->getTypeSourceInfo()->getTypeLoc();
603 }
else if (
const auto *ME = dyn_cast<MemberExpr>(NakedFn)) {
604 const auto *MD = ME->getMemberDecl();
605 if (
const auto *FD = dyn_cast<FieldDecl>(MD)) {
606 Target = FD->getTypeSourceInfo()->getTypeLoc();
615 if (
auto P =
Target.getAs<PointerTypeLoc>()) {
616 Target = P.getPointeeLoc();
619 if (
auto A =
Target.getAs<AttributedTypeLoc>()) {
620 Target = A.getModifiedLoc();
623 if (
auto P =
Target.getAs<ParenTypeLoc>()) {
630 if (
auto F =
Target.getAs<FunctionProtoTypeLoc>()) {
634 if (!llvm::is_contained(F.getParams(),
nullptr))
645 return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME);
649 return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE);
651std::vector<const NamedDecl *>
653 return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(CE);
657 return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD);
660 const DependentNameType *DNT)
const {
661 return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
663std::vector<const NamedDecl *>
665 const TemplateSpecializationType *TST)
const {
666 return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(TST);
670 return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
674 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
675 return HeuristicResolverImpl(Ctx).lookupDependentName(RD, Name, Filter);
678 return HeuristicResolverImpl(Ctx).getPointeeType(T);
681 return HeuristicResolverImpl(Ctx).resolveTypeToTagDecl(T);
684 bool UnwrapPointer) {
685 return HeuristicResolverImpl(Ctx).simplifyType(
Type, E, UnwrapPointer);
688 return HeuristicResolverImpl(Ctx).resolveExprToType(E);
692 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.
Result
Implement __builtin_bit_cast and related operations.
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
QualType resolveExprToType(const Expr *E) 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.
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.
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',...
@ Type
The name was classified as a type.