Skip to content

Commit f1aa4d0

Browse files
committed
Manage ownership and assert on overlapping lifetimes
1 parent 037ca25 commit f1aa4d0

File tree

2 files changed

+47
-18
lines changed

2 files changed

+47
-18
lines changed

clang/include/clang/Serialization/ASTReader.h

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "llvm/ADT/iterator_range.h"
5151
#include "llvm/Bitstream/BitstreamReader.h"
5252
#include "llvm/Support/MemoryBuffer.h"
53+
#include "llvm/Support/SaveAndRestore.h"
5354
#include "llvm/Support/Timer.h"
5455
#include "llvm/Support/VersionTuple.h"
5556
#include <cassert>
@@ -1342,19 +1343,47 @@ class ASTReader
13421343
bool Complain = true);
13431344

13441345
/// Buffer we use as temporary storage backing resolved paths.
1345-
SmallString<256> PathBuf;
1346+
std::optional<SmallString<256>> PathBuf{{}};
1347+
1348+
/// A RAII wrapper around \c StringRef that temporarily takes ownership of the
1349+
/// underlying buffer and gives it back on destruction.
1350+
class TemporarilyOwnedStringRef {
1351+
StringRef String;
1352+
llvm::SaveAndRestore<std::optional<SmallString<256>>> TemporaryLoan;
1353+
1354+
public:
1355+
TemporarilyOwnedStringRef(StringRef S, std::optional<SmallString<256>> &Buf)
1356+
: String(S), TemporaryLoan(Buf, {}) {}
1357+
1358+
/// Returns the wrapped \c StringRef that must be outlived by \c this.
1359+
const StringRef *operator->() const { return &String; }
1360+
/// Returns the wrapped \c StringRef that must be outlived by \c this.
1361+
const StringRef &operator*() const { return String; }
1362+
};
13461363

13471364
public:
1348-
StringRef ResolveImportedPath(StringRef Path, ModuleFile &M) {
1349-
return ResolveImportedPath(PathBuf, Path, M);
1365+
/// Resolve \c Path in the context of module file \c M. The return value must
1366+
/// be destroyed before another call to \c ResolveImportPath.
1367+
TemporarilyOwnedStringRef ResolveImportedPath(StringRef Path, ModuleFile &M) {
1368+
return ResolveImportedPath(Path, M.BaseDirectory);
13501369
}
1351-
StringRef ResolveImportedPath(StringRef Path, StringRef Prefix) {
1352-
return ResolveImportedPath(PathBuf, Path, Prefix);
1370+
/// Resolve \c Path in the context of the \c Prefix directory. The return
1371+
/// value must be destroyed before another call to \c ResolveImportPath.
1372+
TemporarilyOwnedStringRef ResolveImportedPath(StringRef Path,
1373+
StringRef Prefix) {
1374+
assert(PathBuf && "Multiple overlapping calls to ResolveImportedPath");
1375+
StringRef ResolvedPath = ResolveImportedPath(*PathBuf, Path, Prefix);
1376+
return {ResolvedPath, PathBuf};
13531377
}
1378+
1379+
/// Resolve \c Path in the context of module file \c M. The \c Buffer must
1380+
/// outlive the returned \c StringRef.
13541381
static StringRef ResolveImportedPath(SmallVectorImpl<char> &Buffer,
13551382
StringRef Path, ModuleFile &M) {
13561383
return ResolveImportedPath(Buffer, Path, M.BaseDirectory);
13571384
}
1385+
/// Resolve \c Path in the context of the \c Prefix directory. The \c Buffer
1386+
/// must outlive the returned \c StringRef.
13581387
static StringRef ResolveImportedPath(SmallVectorImpl<char> &Buffer,
13591388
StringRef Path, StringRef Prefix);
13601389

clang/lib/Serialization/ASTReader.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,8 +2048,8 @@ HeaderFileInfoTrait::getFile(const internal_key_type &Key) {
20482048
if (!Key.Imported)
20492049
return FileMgr.getOptionalFileRef(Key.Filename);
20502050

2051-
StringRef Resolved = Reader.ResolveImportedPath(Key.Filename, M);
2052-
return FileMgr.getOptionalFileRef(Resolved);
2051+
auto Resolved = Reader.ResolveImportedPath(Key.Filename, M);
2052+
return FileMgr.getOptionalFileRef(*Resolved);
20532053
}
20542054

20552055
unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) {
@@ -2513,9 +2513,9 @@ InputFileInfo ASTReader::getInputFileInfo(ModuleFile &F, unsigned ID) {
25132513
uint16_t AsRequestedLength = Record[7];
25142514

25152515
std::string NameAsRequested =
2516-
ResolveImportedPath(Blob.substr(0, AsRequestedLength), F).str();
2516+
ResolveImportedPath(Blob.substr(0, AsRequestedLength), F)->str();
25172517
std::string Name =
2518-
ResolveImportedPath(Blob.substr(AsRequestedLength), F).str();
2518+
ResolveImportedPath(Blob.substr(AsRequestedLength), F)->str();
25192519

25202520
if (Name.empty())
25212521
Name = NameAsRequested;
@@ -3181,7 +3181,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
31813181
F.OriginalSourceFileID = FileID::get(Record[0]);
31823182
F.ActualOriginalSourceFileName = std::string(Blob);
31833183
F.OriginalSourceFileName =
3184-
ResolveImportedPath(F.ActualOriginalSourceFileName, F).str();
3184+
ResolveImportedPath(F.ActualOriginalSourceFileName, F)->str();
31853185
break;
31863186

31873187
case ORIGINAL_FILE_ID:
@@ -5895,8 +5895,8 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
58955895
// FIXME: This doesn't work for framework modules as `Filename` is the
58965896
// name as written in the module file and does not include
58975897
// `Headers/`, so this path will never exist.
5898-
StringRef Filename = ResolveImportedPath(Blob, F);
5899-
if (auto Umbrella = PP.getFileManager().getOptionalFileRef(Filename)) {
5898+
auto Filename = ResolveImportedPath(Blob, F);
5899+
if (auto Umbrella = PP.getFileManager().getOptionalFileRef(*Filename)) {
59005900
if (!CurrentModule->getUmbrellaHeaderAsWritten()) {
59015901
// FIXME: NameAsWritten
59025902
ModMap.setUmbrellaHeaderAsWritten(CurrentModule, *Umbrella, Blob, "");
@@ -5924,16 +5924,16 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
59245924
break;
59255925

59265926
case SUBMODULE_TOPHEADER: {
5927-
StringRef HeaderName = ResolveImportedPath(Blob, F);
5928-
CurrentModule->addTopHeaderFilename(HeaderName);
5927+
auto HeaderName = ResolveImportedPath(Blob, F);
5928+
CurrentModule->addTopHeaderFilename(*HeaderName);
59295929
break;
59305930
}
59315931

59325932
case SUBMODULE_UMBRELLA_DIR: {
59335933
// See comments in SUBMODULE_UMBRELLA_HEADER
5934-
StringRef Dirname = ResolveImportedPath(Blob, F);
5934+
auto Dirname = ResolveImportedPath(Blob, F);
59355935
if (auto Umbrella =
5936-
PP.getFileManager().getOptionalDirectoryRef(Dirname)) {
5936+
PP.getFileManager().getOptionalDirectoryRef(*Dirname)) {
59375937
if (!CurrentModule->getUmbrellaDirAsWritten()) {
59385938
// FIXME: NameAsWritten
59395939
ModMap.setUmbrellaDirAsWritten(CurrentModule, *Umbrella, Blob, "");
@@ -9589,13 +9589,13 @@ std::string ASTReader::ReadString(const RecordDataImpl &Record, unsigned &Idx) {
95899589
std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,
95909590
unsigned &Idx) {
95919591
std::string Filename = ReadString(Record, Idx);
9592-
return ResolveImportedPath(Filename, F).str();
9592+
return ResolveImportedPath(Filename, F)->str();
95939593
}
95949594

95959595
std::string ASTReader::ReadPath(StringRef BaseDirectory,
95969596
const RecordData &Record, unsigned &Idx) {
95979597
std::string Filename = ReadString(Record, Idx);
9598-
return ResolveImportedPath(Filename, BaseDirectory).str();
9598+
return ResolveImportedPath(Filename, BaseDirectory)->str();
95999599
}
96009600

96019601
VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,

0 commit comments

Comments
 (0)