diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -598,11 +598,12 @@ private: std::optional> Checksum; - std::optional Source; + /// An optional source. A nullptr means none. + MDString *Source; DIFile(LLVMContext &C, StorageType Storage, - std::optional> CS, - std::optional Src, ArrayRef Ops); + std::optional> CS, MDString *Src, + ArrayRef Ops); ~DIFile() = default; static DIFile *getImpl(LLVMContext &Context, StringRef Filename, @@ -615,15 +616,13 @@ MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); return getImpl(Context, getCanonicalMDString(Context, Filename), getCanonicalMDString(Context, Directory), MDChecksum, - Source ? std::optional( - getCanonicalMDString(Context, *Source)) - : std::nullopt, - Storage, ShouldCreate); + Source ? MDString::get(Context, *Source) : nullptr, Storage, + ShouldCreate); } static DIFile *getImpl(LLVMContext &Context, MDString *Filename, MDString *Directory, std::optional> CS, - std::optional Source, StorageType Storage, + MDString *Source, StorageType Storage, bool ShouldCreate = true); TempDIFile cloneImpl() const { @@ -640,7 +639,7 @@ DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory, std::optional> CS = std::nullopt, - std::optional Source = std::nullopt), + MDString *Source = nullptr), (Filename, Directory, CS, Source)) TempDIFile clone() const { return cloneImpl(); } @@ -654,7 +653,7 @@ return StringRefChecksum; } std::optional getSource() const { - return Source ? std::optional((*Source)->getString()) + return Source ? std::optional(Source->getString()) : std::nullopt; } @@ -663,7 +662,7 @@ std::optional> getRawChecksum() const { return Checksum; } - std::optional getRawSource() const { return Source; } + MDString *getRawSource() const { return Source; } static StringRef getChecksumKindAsString(ChecksumKind CSKind); static std::optional getChecksumKind(StringRef CSKindStr); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4996,11 +4996,11 @@ else if (checksumkind.Seen || checksum.Seen) return Lex.Error("'checksumkind' and 'checksum' must be provided together"); - std::optional OptSource; + MDString *Source = nullptr; if (source.Seen) - OptSource = source.Val; - Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val, - OptChecksum, OptSource)); + Source = source.Val; + Result = GET_OR_DISTINCT( + DIFile, (Context, filename.Val, directory.Val, OptChecksum, Source)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1621,11 +1621,10 @@ Checksum.emplace(static_cast(Record[3]), getMDString(Record[4])); MetadataList.assignValue( - GET_OR_DISTINCT(DIFile, (Context, getMDString(Record[1]), - getMDString(Record[2]), Checksum, - Record.size() > 5 ? std::optional( - getMDString(Record[5])) - : std::nullopt)), + GET_OR_DISTINCT(DIFile, + (Context, getMDString(Record[1]), + getMDString(Record[2]), Checksum, + Record.size() > 5 ? getMDString(Record[5]) : nullptr)), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1808,7 +1808,7 @@ } auto Source = N->getRawSource(); if (Source) - Record.push_back(VE.getMetadataOrNullID(*Source)); + Record.push_back(VE.getMetadataOrNullID(Source)); Stream.EmitRecord(bitc::METADATA_FILE, Record, Abbrev); Record.clear(); diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -801,8 +801,8 @@ } DIFile::DIFile(LLVMContext &C, StorageType Storage, - std::optional> CS, - std::optional Src, ArrayRef Ops) + std::optional> CS, MDString *Src, + ArrayRef Ops) : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops), Checksum(CS), Source(Src) {} @@ -834,15 +834,15 @@ DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename, MDString *Directory, std::optional> CS, - std::optional Source, StorageType Storage, + MDString *Source, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Filename) && "Expected canonical MDString"); assert(isCanonical(Directory) && "Expected canonical MDString"); assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString"); - assert((!Source || isCanonical(*Source)) && "Expected canonical MDString"); + // We do *NOT* expect Source to be a canonical MDString because nullptr + // means none, so we need something to represent the empty file. DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS, Source)); - Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr, - Source.value_or(nullptr)}; + Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr, Source}; DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops); } DICompileUnit::DICompileUnit(LLVMContext &C, StorageType Storage, diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -668,11 +668,11 @@ MDString *Filename; MDString *Directory; std::optional> Checksum; - std::optional Source; + MDString *Source; MDNodeKeyImpl(MDString *Filename, MDString *Directory, std::optional> Checksum, - std::optional Source) + MDString *Source) : Filename(Filename), Directory(Directory), Checksum(Checksum), Source(Source) {} MDNodeKeyImpl(const DIFile *N) @@ -687,8 +687,7 @@ unsigned getHashValue() const { return hash_combine(Filename, Directory, Checksum ? Checksum->Kind : 0, - Checksum ? Checksum->Value : nullptr, - Source.value_or(nullptr)); + Checksum ? Checksum->Value : nullptr, Source); } }; diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp --- a/llvm/unittests/IR/DebugInfoTest.cpp +++ b/llvm/unittests/IR/DebugInfoTest.cpp @@ -190,6 +190,24 @@ EXPECT_TRUE(isa(DVIs[0]->getValue(0))); } +TEST(DIBuiler, CreateFile) { + LLVMContext Ctx; + std::unique_ptr M(new Module("MyModule", Ctx)); + DIBuilder DIB(*M); + + DIFile *F = DIB.createFile("main.c", "/"); + EXPECT_EQ(std::nullopt, F->getSource()); + + std::optional> Checksum = std::nullopt; + std::optional Source = std::nullopt; + F = DIB.createFile("main.c", "/", Checksum, Source); + EXPECT_EQ(Source, F->getSource()); + + Source = ""; + F = DIB.createFile("main.c", "/", Checksum, Source); + EXPECT_EQ(Source, F->getSource()); +} + TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) { LLVMContext Ctx; std::unique_ptr M(new Module("MyModule", Ctx)); diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -2221,6 +2221,20 @@ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); } +TEST_F(DIFileTest, EmptySource) { + DIFile *N = DIFile::get(Context, "file", "dir"); + EXPECT_EQ(std::nullopt, N->getSource()); + + std::optional> Checksum = std::nullopt; + std::optional Source = std::nullopt; + N = DIFile::get(Context, "file", "dir", Checksum, Source); + EXPECT_EQ(Source, N->getSource()); + + Source = ""; + N = DIFile::get(Context, "file", "dir", Checksum, Source); + EXPECT_EQ(Source, N->getSource()); +} + TEST_F(DIFileTest, ScopeGetFile) { // Ensure that DIScope::getFile() returns itself. DIScope *N = DIFile::get(Context, "file", "dir");