Skip to content

Replace static LookupResult caches with per-instance members in VisitorBase - #1838

Open
Elvand-Lie wants to merge 3 commits into
vgvassilev:masterfrom
Elvand-Lie:fix/static-lookup-cache-and-ownership
Open

Replace static LookupResult caches with per-instance members in VisitorBase#1838
Elvand-Lie wants to merge 3 commits into
vgvassilev:masterfrom
Elvand-Lie:fix/static-lookup-cache-and-ownership

Conversation

@Elvand-Lie

@Elvand-Lie Elvand-Lie commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Fixes #1837

Problem

GetCladTapePush(), GetCladTapePop(), GetCladTapeBack(), and GetCladZeroInit() in VisitorBase each use a function-local static variable to cache their LookupResult. Since LookupResult holds pointers into the current ASTContext/Sema, these statics become dangling when multiple translation units are processed in the same process (e.g., in Cling).

Solution

Replace all four static llvm::Optional<LookupResult> locals with per-instance members on VisitorBase:

  • m_TapePushLookup
  • m_TapePopLookup
  • m_TapeBackLookup
  • m_TapeZeroInitLookup

Each lookup is performed lazily on first use and dies with the visitor instance, so there is no cross-TU contamination.

Files changed

  • include/clad/Differentiator/VisitorBase.h -- add four llvm_Optional<LookupResult> members, add #include <vector>
  • lib/Differentiator/VisitorBase.cpp -- replace static caches with member access in all four functions

Testing

This is an internal refactor that preserves external behavior. The stale-pointer bug requires a multi-TU interactive session (Cling) to reproduce, which is not covered by the existing test suite.

GetCladTapePush, GetCladTapePop, GetCladTapeBack, and GetCladZeroInit
each used a function-local static llvm::Optional<LookupResult> to
cache their lookup. LookupResult objects hold pointers into the
current ASTContext/Sema, so static locals cause stale AST references
when multiple translation units are processed in the same process
(e.g., in Cling's interactive mode).

Replace all four statics with per-instance llvm::Optional<LookupResult>
members on VisitorBase: m_TapePushLookup, m_TapePopLookup,
m_TapeBackLookup, and m_TapeZeroInitLookup. Each lookup is performed
lazily on first use and dies with the visitor instance.

Fixes: vgvassilev#1837
@Elvand-Lie
Elvand-Lie force-pushed the fix/static-lookup-cache-and-ownership branch from 08fb226 to 35c5fa5 Compare June 18, 2026 18:22
@Elvand-Lie Elvand-Lie changed the title Fix static LookupResult caching and raw-pointer ownership in VisitorBase Replace static LookupResult caches with per-instance members in VisitorBase Jun 18, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions


/// Per-instance cache for tape lookup results. These are tied to the
/// current Sema/ASTContext and must not be shared across translation units.
clad_compat::llvm_Optional<clang::LookupResult> m_TapePushLookup;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_TapePushLookup' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

    clad_compat::llvm_Optional<clang::LookupResult> m_TapePushLookup;
                                                    ^

/// Per-instance cache for tape lookup results. These are tied to the
/// current Sema/ASTContext and must not be shared across translation units.
clad_compat::llvm_Optional<clang::LookupResult> m_TapePushLookup;
clad_compat::llvm_Optional<clang::LookupResult> m_TapePopLookup;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_TapePopLookup' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

    clad_compat::llvm_Optional<clang::LookupResult> m_TapePopLookup;
                                                    ^

/// current Sema/ASTContext and must not be shared across translation units.
clad_compat::llvm_Optional<clang::LookupResult> m_TapePushLookup;
clad_compat::llvm_Optional<clang::LookupResult> m_TapePopLookup;
clad_compat::llvm_Optional<clang::LookupResult> m_TapeBackLookup;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_TapeBackLookup' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

    clad_compat::llvm_Optional<clang::LookupResult> m_TapeBackLookup;
                                                    ^

clad_compat::llvm_Optional<clang::LookupResult> m_TapePushLookup;
clad_compat::llvm_Optional<clang::LookupResult> m_TapePopLookup;
clad_compat::llvm_Optional<clang::LookupResult> m_TapeBackLookup;
clad_compat::llvm_Optional<clang::LookupResult> m_TapeZeroInitLookup;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'm_TapeZeroInitLookup' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

    clad_compat::llvm_Optional<clang::LookupResult> m_TapeZeroInitLookup;
                                                    ^

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

if (!Result)
Result = LookupCladTapeMethod("pop");
return clad_compat::llvm_Optional_GetValue(Result);
if (!m_TapePopLookup)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: use auto when initializing with a template cast to avoid duplicating the type name [modernize-use-auto]

Suggested change
if (!m_TapePopLookup)
auto* pushDRE = m_Sema.BuildDeclarationNameExpr(CSS, pushLR, false)

@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Static LookupResult caches in VisitorBase cause stale AST pointers across translation units

1 participant