Skip to content

RULE-0-2-4 / A0-1-3: false positives for friend-accessed members, direct static calls, and pure virtual private methods #1168

Description

@castler

Affected rules

  • RULE-0-2-4
  • A0-1-3

Description

The cpp/misra/unused-limited-visibility-function (RULE-0-2-4) and cpp/autosar/unused-local-function (A0-1-3) queries report false positives for private member functions that are genuinely used. We found 57 false-positive findings out of 58 total on the eclipse-score/communication codebase.

The false positives fall into three distinct categories.


Category 1: Private methods called through friend class access

The query does not reliably resolve call sites that go through friend-class access.

Example

class SharedMemoryResource {
    friend class SharedMemoryFactoryImpl;
  private:
    static cpp::expected<std::shared_ptr<SharedMemoryResource>, os::Error> Create(...) noexcept;
    static cpp::expected<std::shared_ptr<SharedMemoryResource>, os::Error> Open(...) noexcept;
    uid_t getOwnerUid() const noexcept;
};

Create, Open, and getOwnerUid are all called from SharedMemoryFactoryImpl (a declared friend), but the query flags them as unused.


Category 2: Private template helpers / constructors only called via direct static dispatch

The query uses getTarget(call) from DynamicCallGraph, which resolves virtual dispatch. For non-virtual private methods or private template helpers called directly, the dynamic target may not be resolved, so the call goes unrecognised.

Example 1 – private delegating constructor:

template <typename FieldType, typename... Tags>
class ProxyFieldImpl {
  public:
    ProxyFieldImpl(ProxyBase& proxy_base, std::string_view field_name)
        : ProxyFieldImpl{field_name,
                         MakeSetMethodDispatchIfEnabled(proxy_base, field_name),  // called here
                         MakeGetMethodDispatchIfEnabled(proxy_base, field_name)}  // called here
    {}
  private:
    static std::unique_ptr<ProxyMethod<SetMethodSignature<FieldType>>>
    MakeSetMethodDispatchIfEnabled(ProxyBase&, std::string_view);  // flagged as unused

    static std::unique_ptr<ProxyMethod<GetMethodSignature<FieldType>>>
    MakeGetMethodDispatchIfEnabled(ProxyBase&, std::string_view);  // flagged as unused
};

Example 2 – singleton accessor pattern:

template <typename SampleType>
class ProxyEventBindingFactory {
  public:
    static auto Create(...) { return instance().Create(...); }  // calls instance()
  private:
    static IProxyEventBindingFactory<SampleType>& instance() noexcept;  // flagged as unused
};

Category 3: Pure virtual private member declarations

Pure virtual functions (= 0) are interface contracts that derived classes must override. They have no definition body and cannot be "called" directly. The query incorrectly includes them as candidates.

Example:

class ManagedMemoryResource {
  private:
    virtual const void* getEndAddress() const noexcept = 0;            // flagged
    virtual const MemoryResourceProxy* getMemoryResourceProxy() noexcept = 0;  // flagged
};

class SkeletonFieldBase {
  private:
    virtual Result<void> DoDeferredUpdate() noexcept = 0;  // flagged
};

class IMessagePassingService {
  private:
    virtual void UnregisterMethodCallHandler(QualityType, ProxyMethodInstanceIdentifier) = 0;  // flagged
};

Expected behavior

The query should only flag private / limited-visibility functions that are genuinely never called. It should not flag:

  • Private members invoked from friend classes.
  • Private helper functions that appear as direct static call targets.
  • Pure virtual member declarations (= 0).

Affected queries

  • cpp/misra/unused-limited-visibility-function (RULE-0-2-4)
  • cpp/autosar/unused-local-function (A0-1-3)

Both share cpp/common/src/codingstandards/cpp/rules/unusedlocalfunction/UnusedLocalFunction.qll.


Environment

  • CodeQL bundle: codeql-bundle-v2.21.4
  • Coding standards pack: 2.61.0
  • Downstream repo: eclipse-score/communication

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions