Add an opt-in mechanism for non-differentiable types. - #1930
Merged
Conversation
| /// declaration -- non-differentiable, by specializing clad::Tag for it. Use at | ||
| /// global scope. The type may contain commas, e.g. | ||
| /// CLAD_NONDIFFERENTIABLE_TYPE(std::map<int, double>); | ||
| #define CLAD_NONDIFFERENTIABLE_TYPE(...) \ |
Contributor
There was a problem hiding this comment.
warning: variadic macro 'CLAD_NONDIFFERENTIABLE_TYPE' used; consider using a 'constexpr' variadic template function [cppcoreguidelines-macro-usage]
#define CLAD_NONDIFFERENTIABLE_TYPE(...) \
^| class CLAD_NONDIFFERENTIABLE Tag<::std::basic_streambuf<C, Tr>> {}; | ||
| template <class C, class Tr> | ||
| class CLAD_NONDIFFERENTIABLE Tag<::std::basic_ios<C, Tr>> {}; | ||
| template <> class CLAD_NONDIFFERENTIABLE Tag<::std::ios_base> {}; |
Contributor
There was a problem hiding this comment.
warning: no header providing "std::ios_base" is directly included [misc-include-cleaner]
include/clad/Differentiator/STLBuiltins.h:9:
- #include <iosfwd>
+ #include <ios>
+ #include <iosfwd>| // The value-level macro marks a single type; a template instantiation is | ||
| // only that specialization. Marking the whole family needs a clad::Tag | ||
| // partial specialization the macro cannot express. | ||
| if (isa<clang::ClassTemplateSpecializationDecl>(RD)) |
Contributor
There was a problem hiding this comment.
warning: no header providing "clang::ClassTemplateSpecializationDecl" is directly included [misc-include-cleaner]
lib/Differentiator/DerivativeBuilder.cpp:52:
- #include <cstddef>
+ #include <clang/AST/DeclTemplate.h>
+ #include <cstddef>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
vgvassilev
force-pushed
the
clad-nondiff-engine
branch
2 times, most recently
from
July 29, 2026 16:23
094ae6a to
72afcb2
Compare
When clad has no custom derivative for a called function it synthesizes one by cloning the function's body. For a type whose internals are not meant to be differentiated -- a standard-library primitive, an I/O stream -- that clone is at best wasteful and at worst ill-formed: cloning std::string's char-pointer constructor emits a static reverse-forward propagator that dereferences a null `this` and crashes CodeGen. A type is now non-differentiable when it carries the `non_differentiable` annotation -- on the type itself for code the user owns (CLAD_NONDIFFERENTIABLE), or on a clad::Tag<T> specialization for a foreign type the user cannot annotate at its declaration (CLAD_NONDIFFERENTIABLE_TYPE). utils::isNonDifferentiableType detects it, so clad never clones such a type's constructor or member bodies, and callOperatesOnNonDifferentiableType extends the treatment to a call whose object is opaque (e.g. a std::ostream operation). Seed std::string, std::allocator and the stream family in STLBuiltins.h. -fclad-porting-hints prints the paste-able CLAD_NONDIFFERENTIABLE_TYPE spelling and, for a reverse-forward pass, the elidable_reverse_forw route with its signature -- pointing at existing mechanisms rather than inventing new ones. isElidableConstructor is renamed to constructorReverseForwIsElidable and documented so its "a trivial copy is a shallow share" coverage is discoverable; that made a separate data-less-copy heuristic unnecessary. The user guide documents both macros; tests cover marker-based construction opacity (StringConstructor) and a marked-type call (NonDifferentiableMarkedType).
vgvassilev
force-pushed
the
clad-nondiff-engine
branch
from
July 29, 2026 17:29
72afcb2 to
42cb8e2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When clad has no custom derivative for a called function it synthesizes one by cloning the function's body. For a type whose internals are not meant to be differentiated -- a standard-library primitive, an I/O stream -- that clone is at best wasteful and at worst ill-formed: cloning std::string's char-pointer constructor emits a static reverse-forward propagator that dereferences a null
thisand crashes CodeGen.A type is now non-differentiable when it carries the
non_differentiableannotation -- on the type itself for code the user owns (CLAD_NONDIFFERENTIABLE), or on a clad::Tag specialization for a foreign type the user cannot annotate at its declaration (CLAD_NONDIFFERENTIABLE_TYPE). utils::isNonDifferentiableType detects it, so clad never clones such a type's constructor or member bodies, and callOperatesOnNonDifferentiableType extends the treatment to a call whose object is opaque (e.g. a std::ostream operation). Seed std::string, std::allocator and the stream family in STLBuiltins.h.-fclad-porting-hints prints the paste-able CLAD_NONDIFFERENTIABLE_TYPE spelling and, for a reverse-forward pass, the elidable_reverse_forw route with its signature -- pointing at existing mechanisms rather than inventing new ones. isElidableConstructor is renamed to constructorReverseForwIsElidable and documented so its "a trivial copy is a shallow share" coverage is discoverable; that made a separate data-less-copy heuristic unnecessary.
The user guide documents both macros; tests cover marker-based construction opacity (StringConstructor) and a marked-type call (NonDifferentiableMarkedType).