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 (
@@ -323,6 +326,44 @@ void deduceFromExplicitArgs(clang::Sema &sema,
323326 }
324327}
325328
329+ std::optional<std::vector<clang::TemplateArgument>>
330+ deduceFromCallee (clang::Sema &sema, clang::FunctionTemplateDecl *rule,
331+ const clang::Expr *use) {
332+ auto returned = RuleDecls::GetReturned (rule->getTemplatedDecl ());
333+ if (!returned) {
334+ return std::nullopt ;
335+ }
336+ returned = RuleDecls::SkipImplicit (returned);
337+ if (auto call = llvm::dyn_cast<clang::CallExpr>(returned)) {
338+ returned = call->getCallee ()->IgnoreParenImpCasts ();
339+ }
340+ llvm::ArrayRef<clang::TemplateArgumentLoc> written;
341+ if (auto overload = llvm::dyn_cast<clang::OverloadExpr>(returned);
342+ overload && overload->hasExplicitTemplateArgs ()) {
343+ written = overload->template_arguments ();
344+ } else if (auto ref =
345+ llvm::dyn_cast<clang::DependentScopeDeclRefExpr>(returned);
346+ ref && ref->hasExplicitTemplateArgs ()) {
347+ written = ref->template_arguments ();
348+ } else {
349+ return std::nullopt ;
350+ }
351+ use = RuleDecls::SkipImplicit (use);
352+ const clang::Decl *used = nullptr ;
353+ if (auto call = llvm::dyn_cast<clang::CallExpr>(use)) {
354+ used = call->getDirectCallee ();
355+ } else if (auto ref = llvm::dyn_cast<clang::DeclRefExpr>(use)) {
356+ used = ref->getDecl ();
357+ }
358+ auto specialization = llvm::dyn_cast_or_null<clang::FunctionDecl>(used);
359+ if (!specialization || !specialization->getTemplateSpecializationArgs ()) {
360+ return std::nullopt ;
361+ }
362+ return RuleDecls::DeduceFromArguments (
363+ sema, rule->getTemplateParameters (), written,
364+ specialization->getTemplateSpecializationArgs ()->asArray ());
365+ }
366+
326367clang::TemplateArgumentListInfo getResultArgs (clang::Sema &sema,
327368 clang::FunctionTemplateDecl *rule,
328369 const clang::Expr *use) {
@@ -345,6 +386,13 @@ clang::TemplateArgumentListInfo getResultArgs(clang::Sema &sema,
345386 .getCanonicalType ()
346387 .getUnqualifiedType ())
347388 .value_or (std::vector<clang::TemplateArgument>(params->size ()));
389+ if (auto from_callee = deduceFromCallee (sema, rule, use)) {
390+ for (unsigned i = 0 ; i < deduced.size (); ++i) {
391+ if (deduced[i].isNull ()) {
392+ deduced[i] = (*from_callee)[i];
393+ }
394+ }
395+ }
348396 deduceMemberTypesFromOperands (sema, rule, use, deduced);
349397 deduceFromExplicitArgs (sema, rule, use, deduced);
350398 auto last = static_cast <unsigned >(deducible.find_last_unset ());
0 commit comments