Skip to content

Commit 492c997

Browse files
committed
[clang][cas] Fix dependency directive lookup for prefix-mapped paths
Currently we are failing to find dependency directives for prefix-mapped paths in the scanner, such as -include options. Match how ivfsoverlay marks remapped paths. We want to use the external (remapped) path when we lookup directives; currently the way to do that is getName() combined with ExposesExternalVFSPath; if in the future we add explicit API for this we can drop the status flag.
1 parent ce1ff05 commit 492c997

File tree

5 files changed

+88
-16
lines changed

5 files changed

+88
-16
lines changed

clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ bool ModuleDepCollector::isPrebuiltModule(const Module *M) {
650650
if (PrebuiltModuleFileIt == PrebuiltModuleFiles.end())
651651
return false;
652652
assert("Prebuilt module came from the expected AST file" &&
653-
PrebuiltModuleFileIt->second == M->getASTFile()->getName());
653+
PrebuiltModuleFileIt->second == M->getASTFile()->getNameAsRequested());
654654
return true;
655655
}
656656

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
// RUN: sed -e "s|DIR|%t|g" %t/cdb.json.template > %t/cdb.json
4+
5+
// RUN: clang-scan-deps -compilation-database %t/cdb.json \
6+
// RUN: -format experimental-include-tree-full -cas-path %t/cas \
7+
// RUN: -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc > %t/deps.json
8+
9+
//--- cdb.json.template
10+
[{
11+
"file": "tu.c",
12+
"directory": "DIR",
13+
"command": "clang DIR/tu.c -fsyntax-only -include DIR/prefix.h"
14+
}]
15+
16+
//--- prefix.h
17+
// Note: this is a bit hacky, but we rely on the fact that dep directives lexing
18+
// will not see #error during the scan.
19+
#error "failed to find dependency directives"
20+
21+
//--- tu.c

llvm/include/llvm/Support/PrefixMapper.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,24 @@ class PrefixMapper {
6060
/// Map \p Path, and saving the new (or existing) path in \p NewPath.
6161
///
6262
/// \pre \p Path is not a reference into \p NewPath.
63-
void map(StringRef Path, SmallVectorImpl<char> &NewPath);
64-
void map(StringRef Path, std::string &NewPath);
63+
/// \returns true if \c NewPath was mapped.
64+
bool map(StringRef Path, SmallVectorImpl<char> &NewPath);
65+
/// Map \p Path, and saving the new (or existing) path in \p NewPath.
66+
///
67+
/// \pre \p Path is not a reference into \p NewPath.
68+
/// \returns true if \c NewPath was mapped.
69+
bool map(StringRef Path, std::string &NewPath);
6570

6671
/// Map \p Path, returning \a std::string.
6772
std::string mapToString(StringRef Path);
6873

6974
/// Map \p Path in place.
70-
void mapInPlace(SmallVectorImpl<char> &Path);
71-
void mapInPlace(std::string &Path);
75+
/// \returns true if the path was modified.
76+
bool mapInPlace(SmallVectorImpl<char> &Path);
77+
78+
/// Map \p Path in place.
79+
/// \returns true if the path was modified.
80+
bool mapInPlace(std::string &Path);
7281

7382
protected:
7483
/// Map (or unmap) \p Path. On a match, fills \p Storage with the mapped path

llvm/lib/Support/PrefixMapper.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,18 +117,23 @@ std::optional<StringRef> PrefixMapper::mapImpl(StringRef Path,
117117
return std::nullopt;
118118
}
119119

120-
void PrefixMapper::map(StringRef Path, SmallVectorImpl<char> &NewPath) {
120+
bool PrefixMapper::map(StringRef Path, SmallVectorImpl<char> &NewPath) {
121121
NewPath.clear();
122122
std::optional<StringRef> Mapped = mapImpl(Path, NewPath);
123123
if (!NewPath.empty())
124-
return;
124+
return true;
125+
bool Modified = Mapped.has_value();
125126
if (!Mapped)
126127
Mapped = Path;
127128
NewPath.assign(Mapped->begin(), Mapped->end());
129+
return Modified;
128130
}
129131

130-
void PrefixMapper::map(StringRef Path, std::string &NewPath) {
131-
NewPath = mapToString(Path);
132+
bool PrefixMapper::map(StringRef Path, std::string &NewPath) {
133+
SmallString<256> Storage;
134+
std::optional<StringRef> Mapped = mapImpl(Path, Storage);
135+
NewPath = Mapped ? Mapped->str() : Path.str();
136+
return Mapped.has_value();
132137
}
133138

134139
std::string PrefixMapper::mapToString(StringRef Path) {
@@ -137,24 +142,26 @@ std::string PrefixMapper::mapToString(StringRef Path) {
137142
return Mapped ? Mapped->str() : Path.str();
138143
}
139144

140-
void PrefixMapper::mapInPlace(SmallVectorImpl<char> &Path) {
145+
bool PrefixMapper::mapInPlace(SmallVectorImpl<char> &Path) {
141146
SmallString<256> Storage;
142147
std::optional<StringRef> Mapped =
143148
mapImpl(StringRef(Path.begin(), Path.size()), Storage);
144149
if (!Mapped)
145-
return;
150+
return false;
146151
if (Storage.empty())
147152
Path.assign(Mapped->begin(), Mapped->end());
148153
else
149154
Storage.swap(Path);
155+
return true;
150156
}
151157

152-
void PrefixMapper::mapInPlace(std::string &Path) {
158+
bool PrefixMapper::mapInPlace(std::string &Path) {
153159
SmallString<256> Storage;
154160
std::optional<StringRef> Mapped = mapImpl(Path, Storage);
155161
if (!Mapped)
156-
return;
162+
return false;
157163
Path.assign(Mapped->begin(), Mapped->size());
164+
return true;
158165
}
159166

160167
void PrefixMapper::sort() {

llvm/lib/Support/PrefixMappingFileSystem.cpp

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/Support/PrefixMappingFileSystem.h"
10+
#include "llvm/CAS/CASReference.h"
1011
#include "llvm/Support/PrefixMapper.h"
1112
#include "llvm/Support/VirtualFileSystem.h"
1213

@@ -15,6 +16,31 @@ using namespace llvm::vfs;
1516

1617
namespace {
1718

19+
class PrefixMappingFile : public vfs::File {
20+
std::unique_ptr<vfs::File> Underlying;
21+
22+
public:
23+
PrefixMappingFile(std::unique_ptr<vfs::File> F) : Underlying(std::move(F)) {}
24+
25+
llvm::ErrorOr<Status> status() final {
26+
auto S = Underlying->status();
27+
if (S)
28+
S->ExposesExternalVFSPath = true;
29+
return S;
30+
}
31+
llvm::ErrorOr<std::string> getName() final { return Underlying->getName(); }
32+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
33+
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
34+
bool IsVolatile) final {
35+
return Underlying->getBuffer(Name, FileSize, RequiresNullTerminator,
36+
IsVolatile);
37+
}
38+
llvm::ErrorOr<std::optional<cas::ObjectRef>> getObjectRefForContent() final {
39+
return Underlying->getObjectRefForContent();
40+
}
41+
std::error_code close() final { return Underlying->close(); }
42+
};
43+
1844
class PrefixMappingFileSystem final : public ProxyFileSystem {
1945
mutable PrefixMapper Mapper;
2046

@@ -26,17 +52,26 @@ class PrefixMappingFileSystem final : public ProxyFileSystem {
2652
#define PREFIX_MAP_PATH(Old, New) \
2753
SmallString<256> New; \
2854
Old.toVector(New); \
29-
Mapper.mapInPlace(New);
55+
bool DidMap = Mapper.mapInPlace(New); \
56+
(void)DidMap; // Prevent unused variable warnings.
3057

3158
llvm::ErrorOr<Status> status(const Twine &Path) override {
3259
PREFIX_MAP_PATH(Path, MappedPath)
33-
return ProxyFileSystem::status(MappedPath);
60+
auto S = ProxyFileSystem::status(MappedPath);
61+
// If we remapped the path, indicate the external path.
62+
if (DidMap && S)
63+
S->ExposesExternalVFSPath = true;
64+
return S;
3465
}
3566

3667
llvm::ErrorOr<std::unique_ptr<File>>
3768
openFileForRead(const Twine &Path) override {
3869
PREFIX_MAP_PATH(Path, MappedPath)
39-
return ProxyFileSystem::openFileForRead(MappedPath);
70+
auto F = ProxyFileSystem::openFileForRead(MappedPath);
71+
// If we remapped the path, indicate the external path.
72+
if (DidMap && F)
73+
F = std::make_unique<PrefixMappingFile>(std::move(F.get()));
74+
return F;
4075
}
4176

4277
directory_iterator dir_begin(const Twine &Path,

0 commit comments

Comments
 (0)