66#include < clang/AST/DeclCXX.h>
77#include < clang/AST/DeclTemplate.h>
88#include < clang/AST/ExprCXX.h>
9+ #include < clang/AST/IgnoreExpr.h>
910#include < clang/Basic/OperatorKinds.h>
1011#include < clang/Lex/Lexer.h>
1112#include < clang/Sema/EnterExpressionEvaluationContext.h>
@@ -160,7 +161,9 @@ std::vector<clang::Expr *> getOperands(clang::ASTContext &ctx,
160161 operands.assign (op->arg_begin (), op->arg_end ());
161162 if (!operands.empty () &&
162163 llvm::isa_and_nonnull<clang::CXXMethodDecl>(op->getDirectCallee ())) {
163- operands[0 ] = operands[0 ]->IgnoreParenImpCasts ();
164+ operands[0 ] =
165+ clang::IgnoreExprNodes (operands[0 ], clang::IgnoreParensSingleStep,
166+ clang::IgnoreImplicitCastsSingleStep);
164167 }
165168 } else if (auto call = llvm::dyn_cast<clang::CXXMemberCallExpr>(expr)) {
166169 operands.push_back (getObject (
@@ -353,6 +356,44 @@ void deduceFromExplicitArgs(clang::Sema &sema,
353356 }
354357}
355358
359+ std::optional<std::vector<clang::TemplateArgument>>
360+ deduceFromCallee (clang::Sema &sema, clang::FunctionTemplateDecl *rule,
361+ const clang::Expr *use) {
362+ auto returned = RuleDecls::GetReturned (rule->getTemplatedDecl ());
363+ if (!returned) {
364+ return std::nullopt ;
365+ }
366+ returned = RuleDecls::SkipImplicit (returned);
367+ if (auto call = llvm::dyn_cast<clang::CallExpr>(returned)) {
368+ returned = call->getCallee ()->IgnoreParenImpCasts ();
369+ }
370+ llvm::ArrayRef<clang::TemplateArgumentLoc> written;
371+ if (auto overload = llvm::dyn_cast<clang::OverloadExpr>(returned);
372+ overload && overload->hasExplicitTemplateArgs ()) {
373+ written = overload->template_arguments ();
374+ } else if (auto ref =
375+ llvm::dyn_cast<clang::DependentScopeDeclRefExpr>(returned);
376+ ref && ref->hasExplicitTemplateArgs ()) {
377+ written = ref->template_arguments ();
378+ } else {
379+ return std::nullopt ;
380+ }
381+ use = RuleDecls::SkipImplicit (use);
382+ const clang::Decl *used = nullptr ;
383+ if (auto call = llvm::dyn_cast<clang::CallExpr>(use)) {
384+ used = call->getDirectCallee ();
385+ } else if (auto ref = llvm::dyn_cast<clang::DeclRefExpr>(use)) {
386+ used = ref->getDecl ();
387+ }
388+ auto specialization = llvm::dyn_cast_or_null<clang::FunctionDecl>(used);
389+ if (!specialization || !specialization->getTemplateSpecializationArgs ()) {
390+ return std::nullopt ;
391+ }
392+ return RuleDecls::DeduceFromArguments (
393+ sema, rule->getTemplateParameters (), written,
394+ specialization->getTemplateSpecializationArgs ()->asArray ());
395+ }
396+
356397clang::TemplateArgumentListInfo getResultArgs (clang::Sema &sema,
357398 clang::FunctionTemplateDecl *rule,
358399 const clang::Expr *use) {
@@ -375,6 +416,13 @@ clang::TemplateArgumentListInfo getResultArgs(clang::Sema &sema,
375416 .getCanonicalType ()
376417 .getUnqualifiedType ())
377418 .value_or (std::vector<clang::TemplateArgument>(params->size ()));
419+ if (auto from_callee = deduceFromCallee (sema, rule, use)) {
420+ for (unsigned i = 0 ; i < deduced.size (); ++i) {
421+ if (deduced[i].isNull ()) {
422+ deduced[i] = (*from_callee)[i];
423+ }
424+ }
425+ }
378426 deduceMemberTypesFromOperands (sema, rule, use, deduced);
379427 deduceFromExplicitArgs (sema, rule, use, deduced);
380428 auto last = static_cast <unsigned >(deducible.find_last_unset ());
0 commit comments