@@ -978,15 +978,18 @@ static QualType GetDerivedFunctionType(const CallExpr* CE) {
978978 });
979979 }
980980
981- static Expr* getOverloadExpr (Sema& S, DeclContext* DC , DiffRequest& R) {
981+ static Expr* getOverloadExpr (Sema& S, DeclContext* DC , DiffRequest& R,
982+ bool * foundAnyDecl = nullptr ) {
983+ if (foundAnyDecl)
984+ *foundAnyDecl = false ;
982985 // Error estimation only uses forward mode derivatives if they are
983986 // user-prodived to handle builtin derivatives. If found, we have to change
984987 // the mode of the request.
985988 if (R.EnableErrorEstimation && R.Mode == DiffMode::pullback &&
986989 utils::canUsePushforwardInRevMode (R.Function )) {
987990 R.Mode = DiffMode::pushforward;
988991 R.EnableErrorEstimation = false ;
989- if (Expr* overload = getOverloadExpr (S, DC , R)) {
992+ if (Expr* overload = getOverloadExpr (S, DC , R, foundAnyDecl )) {
990993 R.DVI .clear ();
991994 return overload;
992995 }
@@ -1026,6 +1029,9 @@ static QualType GetDerivedFunctionType(const CallExpr* CE) {
10261029 if (Found.empty ())
10271030 return nullptr ; // Nothing found.
10281031
1032+ if (foundAnyDecl)
1033+ *foundAnyDecl = true ;
1034+
10291035 TemplateSpecCandidateSet FailedCandidates (R.CallContext ->getBeginLoc (),
10301036 /* ForTakingAddress=*/ false );
10311037 if (Expr* overload =
@@ -1078,21 +1084,43 @@ static QualType GetDerivedFunctionType(const CallExpr* CE) {
10781084 }
10791085 } else
10801086 fnDecl = request.Function ;
1081- DeclContext* DC = customDerNS;
1082-
1083- if (isa<CXXMethodDecl>(fnDecl))
1084- DC = utils::LookupNSD (m_Sema, " class_functions" , /* shouldExist=*/ false ,
1085- DC );
1086- else
1087- DC = utils::FindDeclContext (m_Sema, DC , fnDecl->getDeclContext ());
1088-
1089- if (!DC )
1090- return false ;
1091-
10921087 assert (request.Mode != DiffMode::unknown &&
10931088 " Called lookup without specified DiffMode" );
10941089
1095- if (Expr* overload = getOverloadExpr (m_Sema, DC , request)) {
1090+ auto LookupOverload = [this , fnDecl, &request](NamespaceDecl* NSD ,
1091+ bool * foundAnyDecl) {
1092+ DeclContext* DC = NSD ;
1093+ if (isa<CXXMethodDecl>(fnDecl))
1094+ DC = utils::LookupNSD (m_Sema, " class_functions" ,
1095+ /* shouldExist=*/ false , DC );
1096+ else
1097+ DC = utils::FindDeclContext (m_Sema, DC , fnDecl->getDeclContext ());
1098+ if (!DC )
1099+ return static_cast <Expr*>(nullptr );
1100+ return getOverloadExpr (m_Sema, DC , request, foundAnyDecl);
1101+ };
1102+
1103+ // Look for the user overrides namespace nested inside custom_derivatives
1104+ NamespaceDecl* overridesNS = utils::LookupNSD (
1105+ m_Sema, " overrides" , /* shouldExist=*/ false , customDerNS);
1106+
1107+ // clad::custom_derivatives::overrides (user overrides, higher priority).
1108+ bool foundOverridesDecl = false ;
1109+ if (overridesNS) {
1110+ if (Expr* overload = LookupOverload (overridesNS, &foundOverridesDecl)) {
1111+ // Overload found. Mark the request as custom derivative overrides and
1112+ // save the set of overloads to process later.
1113+ request.CustomDerivative = overload;
1114+ return true ;
1115+ }
1116+ // Overrides declaration found but signature mismatch; do not fall back to
1117+ // builtin.
1118+ if (foundOverridesDecl)
1119+ return false ;
1120+ }
1121+
1122+ // clad::custom_derivatives (builtins, fallback).
1123+ if (Expr* overload = LookupOverload (customDerNS, nullptr )) {
10961124 // Overload found. Mark the request as custom derivative and save
10971125 // the set of overloads to process later.
10981126 request.CustomDerivative = overload;
0 commit comments