Normalize include paths before source-cache lookup#976
Normalize include paths before source-cache lookup#9760pendev wants to merge 3 commits intoVexu:masterfrom
Conversation
Vexu
left a comment
There was a problem hiding this comment.
Could you also make addSourceFromOwnedBuffer take a []u8 for path so that it doesn't need to be duped twice? And a test would be nice.
How do want me to add the test case ? Is it okay to add a subdirectory for the includes needed for the test? |
|
There is already a directory for includes, you could look at |
|
Hey @Vexu My last commit is the refactor you suggested, I feel like it makes the function harder to call and would love a review on it 🙏 |
8ab77bd to
379a9a4
Compare
|
Looking at |
Signed-off-by: Francisco Freitas <francisco.freitas@ledger.fr>
Fix duplicate source loading when the same header is reached via different relative ../ paths (e.g. common/shared.h vs handler/../common/shared.h). Replace fmt.allocPrint-based path construction in FindInclude.check with std.fs.path.resolve, so logically identical paths are canonicalized before keying into the source cache. Also resolve search-path prefixes in the include-directory loop for the same reason. Signed-off-by: Francisco Freitas <francisco.freitas@ledger.fr>
379a9a4 to
bf10239
Compare
Applied this refactoring and dropped previous attempts at fixes. |
Signed-off-by: Francisco Freitas <francisco.freitas@ledger.fr>
| }, | ||
| } | ||
| for (comp.search_path.items) |include| { | ||
| const resolved_path = try std.fs.path.resolve(find.comp.gpa, &.{include.path}); |
There was a problem hiding this comment.
From the tests I did The resolve is needed for #include_next support.
PR: Normalize include paths before source-cache lookup
Summary
../paths (e.g.common/shared.hvshandler/../common/shared.h).std.fs.path.resolvePosixbefore keying into the source cache, so that logically identical files map to a single cache entry.Problem
The source cache in
Compilation.addSourceFromPathExtrawas keyed on the raw include-path string as provided by the preprocessor. When the same physical header file was included from different directories, each directory produced a different relative path containing../segments that were never collapsed.For example, given this layout:
When the preprocessor processes these includes, the cache sees two different keys for the same file:
main.ccommon/shared.hhandler/handler_types.hhandler/../common/shared.hBecause these two strings differ, the cache treated them as two distinct sources, even though they refer to the same file on disk. This caused:
#pragma oncefailures — the guard is per-source-ID, so the second load didn't recognize the file as already included, leading to duplicate type definitions or, in pathological./-loop cases, infinite self-include recursion.Reproducer
Create the following file tree:
common/shared.hhandler/handler_types.hmain.cWithout the fix, compiling
main.cwith arocc produces a duplicate definition error forshared_tbecause#pragma oncefails to deduplicate the two source-cache entries forcommon/shared.h.Fix
In
src/aro/Compilation.zig, insideaddSourceFromPathExtra:std.fs.path.resolvePosixto collapse/./"andX/../segments.