[AST] Fix UB appearing due to strict aliasing rule violation (#85286)

This fixes the following tests which are now crashing due to hitting
unreachable "no buffer containing location found" in
`SourceManager::findBufferContainingLoc`:

- attr/attr_dynamic_member_lookup.swift
- AutoDiff/Sema/DerivativeRegistrationCrossModule/main.swift
- Constraints/construction.swift
- Constraints/members.swift
- NameLookup/accessibility.swift
- Sema/call_as_function_simple.swift

The root cause of the crash is as follows. All the tests involve
emitting `InaccessibleMemberFailure` error diagnostic (see
`InaccessibleMemberFailure::diagnoseAsError`). When `DeclNameLoc
nameLoc` is initialized via default constructor and is not re-assigned
with smth meaningful later, the check `nameLoc.isValid()` returns `true`
even though it should be `false`. It turns out that we treat `const void
*LocationInfo` as `SourceLoc` and hope that if `LocationInfo` is
`nullptr`, casting this to `SourceLoc` would produce a "default"
`SourceLoc` with `Pointer` member set to `nullptr`. But such a cast (see
`getSourceLocs()` member of `DeclNameLoc`) is undefined behavior. So,
the compiler assumes that `Pointer` member of `SourceLoc` we try to cast
to is not `nullptr` (due to strict aliasing rule), which leads to
`nameLoc.isValid()` being mistakenly computed as `true`.

This patch resolves the issue by handling this special case separately.
This commit is contained in:
Daniil Kovalev
2025-11-04 10:53:30 +03:00
committed by GitHub
parent ba47e23f51
commit 971e696b96

View File

@@ -60,8 +60,11 @@ class DeclNameLoc {
/// Retrieve a pointer to either the only source location that was
/// stored or to the array of source locations that was stored.
SourceLoc const * getSourceLocs() const {
if (NumArgumentLabels == 0 && !HasModuleSelectorLoc)
if (NumArgumentLabels == 0 && !HasModuleSelectorLoc) {
if (LocationInfo == nullptr)
return nullptr;
return reinterpret_cast<SourceLoc const *>(&LocationInfo);
}
return reinterpret_cast<SourceLoc const *>(LocationInfo);
}
@@ -110,7 +113,10 @@ public:
/// Retrieve the location of the base name.
SourceLoc getBaseNameLoc() const {
return getSourceLocs()[BaseNameIndex];
const SourceLoc *SourceLocs = getSourceLocs();
if (SourceLocs == nullptr)
return SourceLoc();
return SourceLocs[BaseNameIndex];
}
/// Retrieve the location of the left parentheses.