Skip to content

Find unused / dead / extraneous code

Understand can surface code that is declared but never referenced — unused functions, variables, types, and unreachable statements. This is reference-based analysis: an entity is treated as "unused" when nothing in the analyzed source calls, reads, or otherwise references it.

Read the caveats before you delete anything

"Unused" here means "Understand found no reference in the code it analyzed." That is not proof the code is safe to delete. See What "unused" can and can't prove below — dynamic dispatch, templates, reflection, callbacks, and external linkage all produce false positives.

Option 1 — highlight unused entities in the editor

The lightest-weight option flags unused entities right in the source editor. Turn on Highlight Unused Entities in the editor settings (the Unused Entities option group). Unused identifiers are then drawn in a distinct colour, which you can change under Editor → Styles. This is the quickest way to notice dead locals and functions while you read code.

Option 2 — the unused-code CodeChecks

The systematic approach is CodeCheck. Several checks detect different flavours of dead code:

Check Detects
Unused Entities (STI_UNUSED, alias CPP_U010) Any entity with no incoming references
Unused Functions (RECOMMENDED_13, alias CPP_F003) Defined functions never called
Unused Local Variables (CPP_V007) Locals declared but never used
Unused Global Variables (CPP_V008) Globals declared but never used
Unreachable Code (RECOMMENDED_12, alias CPP_C034) Statements that can never execute

A ready-made configuration, Unused Code Subset, bundles the unused-functions, unused local/global variable, and unreachable-code checks (plus duplicate- and commented-line checks) so you can enable them in one step — add the broader Unused Entities check yourself if you want it. Turn them on, run the checks, and read the results in the Violation Browser. New to CodeCheck? Start with Run your first check.

MISRA / AUTOSAR users

If you're already checking against a standard, unused-code rules are part of it — e.g. MISRA C 2023 rules 2.7 (unused parameters), 2.3 (unused type declarations), and 2.4 (unused tag declarations). You may not need the SciTools checks separately.

Option 3 — the Unused Code reports

Two built-in interactive reports aggregate the findings into a shareable summary (for the full set of shipped reports, see which report should I use?):

  • Unused Code Report — a per-file table of unused functions, unused locals, unused globals, unreachable code, duplicate lines, and commented-out lines, with Unused Entities and Unused Lines charts. It reads the CodeCheck violations above, so it requires the Unused Code Subset checks to have been run in the background first.
  • Unused Functions Table — lists every unused function with its file, line, and kind. It computes unused-ness directly (no prior CodeCheck run needed) and works across Ada, C/C++, C#, Fortran, Java, Jovial, Pascal, Python, VHDL, and Web. Its options let you ignore virtual functions and ignore member functions to cut false positives (see below), and exclude standard-library functions.

Run a report headless by its exact name:

und report "Unused Functions Table" out_directory myProject.und
und report "Unused Code Report" out_directory myProject.und

See Run Understand from the command line. (Report export requires a license with exporting enabled.)

What "unused" can and can't prove

Understand decides "unused" by counting incoming references — an entity is dead when it has no call, use, read, or specialization references pointing at it. A few exceptions are built in: main is never reported, destructors are treated as used, and for virtual functions the analysis follows overrides.

Because this is static, reference-based analysis, expect false positives wherever a use isn't visible in the source as a direct reference:

  • Dynamic dispatch / virtual polymorphism — a method reached only through a base-class pointer may look unused. (This is why the Unused Functions report offers "Ignore Virtual Functions" by default.)
  • Templates — instantiations can make member functions look unused. (Hence "Ignore Member Functions".)
  • Reflection, callbacks, and address-taken indirect calls — if something is invoked by name lookup, a function pointer, or a framework, Understand won't see a reference.
  • External linkage / public API — an entity exported for callers outside the analyzed project has no in-project reference. By default the Unused Entities check excludes "interface" entities (non- private declarations in headers) for exactly this reason.

Documenting an intentional non-use

In C/C++ you can silence a legitimate unused warning with a (void) cast or the [[maybe_unused]] attribute — the checks honour both. Elsewhere, treat the report as a candidate list to review, not a delete list. Cross-check a candidate with the Information Browser (its "Callby"/"Usedby" references) before removing it.