Skip to content

RULE-0-0-1: False positives from orphan CFG BasicBlocks on virtual calls returning std::variant-based types #1143

@castler

Description

@castler

Affected rules

  • RULE-0-0-1

Description

RULE-0-0-1/UnreachableStatement.ql reports false positives for functions that call virtual methods returning std::variant-based types (commonly used for expected<void, Error> patterns). Multiple statements in such functions are flagged as unreachable even though all code paths are reachable.

Example

// repro.cpp — compile with: g++ -std=c++17 -c repro.cpp
#include <variant>
#include <string>

struct Error { std::string msg; };

template <typename E> class expected_void {
  std::variant<std::monostate, E> storage_;
public:
  constexpr expected_void() noexcept = default;
  expected_void(E e) : storage_{std::in_place_index<1>, static_cast<E&&>(e)} {}
  [[nodiscard]] constexpr bool has_value() const noexcept {
    return storage_.index() == 0U;
  }
};

class IService {
public:
  virtual expected_void<Error> DoWork(const std::string &s) const noexcept = 0;
  virtual ~IService() = default;
};

bool Fn(IService &svc) {
  const auto result = svc.DoWork("test");
  if (!result.has_value()) {
    return false;
  }
  return true;
}

void caller(IService &s) { Fn(s); }

Steps to reproduce

# 1. Create database with GCC
codeql database create repro_db --language=cpp \
  --command="g++ -std=c++17 -c repro.cpp -o repro.o"

# 2. Run query using codeql/misra-cpp-coding-standards@2.60.0
#    (which depends on codeql/cpp-all 5.0.0)
codeql query run --database=repro_db \
  --additional-packs ~/.codeql/packages \
  ~/.codeql/packages/codeql/misra-cpp-coding-standards/2.60.0/rules/RULE-0-0-1/UnreachableStatement.ql

False positive output

| svc        | Unreachable statement in function '$@'. | Fn | Fn |
| { ... }    | Unreachable statement in function '$@'. | Fn | Fn |
| return ... | Unreachable statement in function '$@'. | Fn | Fn |
| Fn         | Unreachable statement in function '$@'. | Fn | Fn |

All four flagged elements are clearly reachable — Fn is called from caller, svc is a parameter access, and both branches of the if are exercised.

Believed Root Cause

The GCC extractor + codeql/cpp-all <= 5.0.0 creates orphan BasicBlock nodes for functions involving virtual calls that return std::variant-based types with non-trivially-destructible alternatives (e.g., std::string). These orphan blocks have:

  • 0 predecessors AND 0 successors — completely disconnected from the CFG
  • They represent Expr nodes (variable accesses, function names, temporary object reuse), NOT Stmt nodes

The isReachable predicate starts from Function.getEntryPoint() and traverses predecessors, so these orphan blocks are correctly identified as not reachable. However, reporting them as unreachable statements is incorrect because:

  1. They are not statements — they are expression-level artifacts
  2. They are not connected to any control flow — they cannot be genuinely "unreachable code" in the MISRA sense

Triggering conditions

The false positive requires all of:

  • std::variant with a non-trivially-destructible alternative (e.g., std::string member)
  • A virtual method call returning the variant-based type
  • The method parameter must also be a non-trivial type (e.g., const std::string&)
  • Database built with GCC extractor
  • Query evaluated with codeql/cpp-all 5.0.0

Impact

In the eclipse-score/communication (https://github.com/eclipse-score/communication) project, this produces ~1182 false positives out of 3051 total findings when analyzed with the codeql/misra-cpp-coding-standards@2.60.0 pack (which depends on codeql/cpp-all 5.0.0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    false positive/false negativeAn issue related to observed false positives or false negatives.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions