# cmake-0004 — AddSource: O(n²) std::find_if per call in Unity build loop

**Severity:** HIGH
**File:** `Source/cmTarget.cxx`
**Lines:** 1428–1444
**CWE:** CWE-407 (Algorithmic Complexity — Quadratic)

## Description

`cmTarget::AddSource()` performs a linear `std::find_if` over the entire
`Sources.Entries` vector on every call:

```cpp
// Source/cmTarget.cxx:1432-1434
auto const& sources = this->impl->Sources.Entries;
if (std::find_if(sources.begin(), sources.end(),
                 TargetPropertyEntryFinder(sfl)) == sources.end()) {
```

`AddSource` is called in a `for` loop over `unity_files` in
`cmLocalGenerator.cxx:3353`:

```cpp
for (UnitySource const& file : unity_files) {
    target->AddSource(file.Path, true);   // O(n) scan each iteration
```

For a Unity build with S source files, constructing the unity file list
costs O(S²) in total. Unity builds are precisely the scenario where S is
large (hundreds to thousands of files per target).

## Fix

Maintain a parallel `std::unordered_set<std::string> SourcePathsSet` in
`cmTargetInternals`. On each `AddSource` call, attempt a set insertion
first; if already present, skip the `find_if` and `WriteDirect` entirely.

**Patch:** `patch/cmake-0004-addsource-unordered-set.patch`
**Unit test:** `unit/AddSourceAlgorithm.java`

## Complexity

| | Time |
|---|---|
| Before | O(S²) |
| After | O(S) amortised |

## Speedup estimate

At S=1000 sources: ~500× fewer comparisons on the hot path.
Measured HIGH: Unity builds with thousands of sources are a documented
CMake use-case (Qt, Chromium, large game engines).
