@@ -35,7 +35,6 @@ class HeuristicResolverImpl {
3535 resolveMemberExpr (const CXXDependentScopeMemberExpr *ME);
3636 std::vector<const NamedDecl *>
3737 resolveDeclRefExpr (const DependentScopeDeclRefExpr *RE);
38- std::vector<const NamedDecl *> resolveTypeOfCallExpr (const CallExpr *CE);
3938 std::vector<const NamedDecl *> resolveCalleeOfCallExpr (const CallExpr *CE);
4039 std::vector<const NamedDecl *>
4140 resolveUsingValueDecl (const UnresolvedUsingValueDecl *UUVD);
@@ -50,6 +49,7 @@ class HeuristicResolverImpl {
5049 llvm::function_ref<bool (const NamedDecl *ND)> Filter);
5150 TagDecl *resolveTypeToTagDecl (QualType T);
5251 QualType simplifyType (QualType Type, const Expr *E, bool UnwrapPointer);
52+ QualType resolveExprToType (const Expr *E);
5353 FunctionProtoTypeLoc getFunctionProtoTypeLoc (const Expr *Fn);
5454
5555private:
@@ -71,10 +71,8 @@ class HeuristicResolverImpl {
7171 resolveDependentMember (QualType T, DeclarationName Name,
7272 llvm::function_ref<bool (const NamedDecl *ND)> Filter);
7373
74- // Try to heuristically resolve the type of a possibly-dependent expression
75- // `E`.
76- QualType resolveExprToType (const Expr *E);
7774 std::vector<const NamedDecl *> resolveExprToDecls (const Expr *E);
75+ QualType resolveTypeOfCallExpr (const CallExpr *CE);
7876
7977 bool findOrdinaryMemberInDependentClasses (const CXXBaseSpecifier *Specifier,
8078 CXXBasePath &Path,
@@ -96,18 +94,25 @@ const auto TemplateFilter = [](const NamedDecl *D) {
9694 return isa<TemplateDecl>(D);
9795};
9896
99- QualType resolveDeclsToType (const std::vector< const NamedDecl *> &Decls,
100- ASTContext &Ctx ) {
101- if (Decls. size () != 1 ) // Names an overload set -- just bail.
102- return QualType ();
103- if (const auto *TD = dyn_cast<TypeDecl>(Decls[ 0 ] ))
97+ QualType resolveDeclToType (const NamedDecl *D, ASTContext &Ctx) {
98+ if ( const auto *TempD = dyn_cast<TemplateDecl>(D) ) {
99+ D = TempD-> getTemplatedDecl ();
100+ }
101+ if (const auto *TD = dyn_cast<TypeDecl>(D ))
104102 return Ctx.getCanonicalTypeDeclType (TD);
105- if (const auto *VD = dyn_cast<ValueDecl>(Decls[ 0 ] )) {
103+ if (const auto *VD = dyn_cast<ValueDecl>(D )) {
106104 return VD->getType ();
107105 }
108106 return QualType ();
109107}
110108
109+ QualType resolveDeclsToType (const std::vector<const NamedDecl *> &Decls,
110+ ASTContext &Ctx) {
111+ if (Decls.size () != 1 ) // Names an overload set -- just bail.
112+ return QualType ();
113+ return resolveDeclToType (Decls[0 ], Ctx);
114+ }
115+
111116TemplateName getReferencedTemplateName (const Type *T) {
112117 if (const auto *TST = T->getAs <TemplateSpecializationType>()) {
113118 return TST->getTemplateName ();
@@ -329,19 +334,29 @@ HeuristicResolverImpl::resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) {
329334 return resolveDependentMember (Qualifier, RE->getDeclName (), StaticFilter);
330335}
331336
332- std::vector<const NamedDecl *>
333- HeuristicResolverImpl::resolveTypeOfCallExpr (const CallExpr *CE) {
334- QualType CalleeType = resolveExprToType (CE->getCallee ());
335- if (CalleeType.isNull ())
336- return {};
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 ())) {
341- return {D};
337+ QualType HeuristicResolverImpl::resolveTypeOfCallExpr (const CallExpr *CE) {
338+ // resolveExprToType(CE->getCallee()) would bail in the case of multiple
339+ // overloads, as it can't produce a single type for them. We can be more
340+ // permissive here, and allow multiple overloads with a common return type.
341+ std::vector<const NamedDecl *> CalleeDecls =
342+ resolveExprToDecls (CE->getCallee ());
343+ QualType CommonReturnType;
344+ for (const NamedDecl *CalleeDecl : CalleeDecls) {
345+ QualType CalleeType = resolveDeclToType (CalleeDecl, Ctx);
346+ if (CalleeType.isNull ())
347+ continue ;
348+ if (const auto *FnTypePtr = CalleeType->getAs <PointerType>())
349+ CalleeType = FnTypePtr->getPointeeType ();
350+ if (const FunctionType *FnType = CalleeType->getAs <FunctionType>()) {
351+ QualType ReturnType =
352+ simplifyType (FnType->getReturnType (), nullptr , false );
353+ if (!CommonReturnType.isNull () && CommonReturnType != ReturnType) {
354+ return {}; // conflicting return types
355+ }
356+ CommonReturnType = ReturnType;
342357 }
343358 }
344- return {} ;
359+ return CommonReturnType ;
345360}
346361
347362std::vector<const NamedDecl *>
@@ -393,15 +408,41 @@ HeuristicResolverImpl::resolveExprToDecls(const Expr *E) {
393408 return {OE->decls_begin (), OE->decls_end ()};
394409 }
395410 if (const auto *CE = dyn_cast<CallExpr>(E)) {
396- return resolveTypeOfCallExpr (CE);
411+ QualType T = resolveTypeOfCallExpr (CE);
412+ if (const auto *D = resolveTypeToTagDecl (T)) {
413+ return {D};
414+ }
415+ return {};
397416 }
398417 if (const auto *ME = dyn_cast<MemberExpr>(E))
399418 return {ME->getMemberDecl ()};
419+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
420+ return {DRE->getDecl ()};
400421
401422 return {};
402423}
403424
404425QualType HeuristicResolverImpl::resolveExprToType (const Expr *E) {
426+ // resolveExprToDecls on a CallExpr only succeeds if the return type is
427+ // a TagDecl, but we may want the type of a call in other cases as well.
428+ // (FIXME: There are probably other cases where we can do something more
429+ // flexible than resoveExprToDecls + resolveDeclsToType, e.g. in the case
430+ // of OverloadExpr we can probably accept overloads with a common type).
431+ if (const auto *CE = dyn_cast<CallExpr>(E)) {
432+ if (QualType Resolved = resolveTypeOfCallExpr (CE); !Resolved.isNull ())
433+ return Resolved;
434+ }
435+ // Similarly, unwrapping a unary dereference operation does not work via
436+ // resolveExprToDecls.
437+ if (const auto *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts ())) {
438+ if (UO->getOpcode () == UnaryOperatorKind::UO_Deref) {
439+ if (auto Pointee = getPointeeType (resolveExprToType (UO->getSubExpr ()));
440+ !Pointee.isNull ()) {
441+ return Pointee;
442+ }
443+ }
444+ }
445+
405446 std::vector<const NamedDecl *> Decls = resolveExprToDecls (E);
406447 if (!Decls.empty ())
407448 return resolveDeclsToType (Decls, Ctx);
@@ -580,10 +621,6 @@ std::vector<const NamedDecl *> HeuristicResolver::resolveDeclRefExpr(
580621 return HeuristicResolverImpl (Ctx).resolveDeclRefExpr (RE);
581622}
582623std::vector<const NamedDecl *>
583- HeuristicResolver::resolveTypeOfCallExpr (const CallExpr *CE) const {
584- return HeuristicResolverImpl (Ctx).resolveTypeOfCallExpr (CE);
585- }
586- std::vector<const NamedDecl *>
587624HeuristicResolver::resolveCalleeOfCallExpr (const CallExpr *CE) const {
588625 return HeuristicResolverImpl (Ctx).resolveCalleeOfCallExpr (CE);
589626}
@@ -619,7 +656,9 @@ QualType HeuristicResolver::simplifyType(QualType Type, const Expr *E,
619656 bool UnwrapPointer) {
620657 return HeuristicResolverImpl (Ctx).simplifyType (Type, E, UnwrapPointer);
621658}
622-
659+ QualType HeuristicResolver::resolveExprToType (const Expr *E) const {
660+ return HeuristicResolverImpl (Ctx).resolveExprToType (E);
661+ }
623662FunctionProtoTypeLoc
624663HeuristicResolver::getFunctionProtoTypeLoc (const Expr *Fn) const {
625664 return HeuristicResolverImpl (Ctx).getFunctionProtoTypeLoc (Fn);
0 commit comments