diff --git a/clang/include/clang/ARCMigrate/FileRemapper.h b/clang/include/clang/ARCMigrate/FileRemapper.h index ceb3e67b50352..afcee363516a2 100644 --- a/clang/include/clang/ARCMigrate/FileRemapper.h +++ b/clang/include/clang/ARCMigrate/FileRemapper.h @@ -12,10 +12,10 @@ #include "clang/Basic/FileEntry.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include +#include namespace llvm { class MemoryBuffer; @@ -33,7 +33,7 @@ class FileRemapper { // FIXME: Reuse the same FileManager for multiple ASTContexts. std::unique_ptr FileMgr; - typedef llvm::PointerUnion Target; + using Target = std::variant; using MappingsTy = llvm::DenseMap; MappingsTy FromToMappings; diff --git a/clang/include/clang/Basic/FileEntry.h b/clang/include/clang/Basic/FileEntry.h index 23237a9326f84..bc65463735488 100644 --- a/clang/include/clang/Basic/FileEntry.h +++ b/clang/include/clang/Basic/FileEntry.h @@ -235,37 +235,6 @@ static_assert(std::is_trivially_copyable::value, namespace llvm { -template <> struct PointerLikeTypeTraits { - static inline void *getAsVoidPointer(clang::FileEntryRef File) { - return const_cast(&File.getMapEntry()); - } - - static inline clang::FileEntryRef getFromVoidPointer(void *Ptr) { - return clang::FileEntryRef( - *reinterpret_cast(Ptr)); - } - - static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits< - const clang::FileEntryRef::MapEntry *>::NumLowBitsAvailable; -}; - -template <> struct PointerLikeTypeTraits { - static inline void *getAsVoidPointer(clang::OptionalFileEntryRef File) { - if (!File) - return nullptr; - return PointerLikeTypeTraits::getAsVoidPointer(*File); - } - - static inline clang::OptionalFileEntryRef getFromVoidPointer(void *Ptr) { - if (!Ptr) - return std::nullopt; - return PointerLikeTypeTraits::getFromVoidPointer(Ptr); - } - - static constexpr int NumLowBitsAvailable = - PointerLikeTypeTraits::NumLowBitsAvailable; -}; - /// Specialisation of DenseMapInfo for FileEntryRef. template <> struct DenseMapInfo { static inline clang::FileEntryRef getEmptyKey() { diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index 676fd372493a3..6a7423938bdb8 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -35,6 +35,7 @@ #include #include #include +#include #include namespace llvm { @@ -162,7 +163,7 @@ class alignas(8) Module { std::string PresumedModuleMapFile; /// The umbrella header or directory. - llvm::PointerUnion Umbrella; + std::variant Umbrella; /// The module signature. ASTFileSignature Signature; @@ -665,18 +666,17 @@ class alignas(8) Module { /// Retrieve the umbrella directory as written. std::optional getUmbrellaDirAsWritten() const { - if (Umbrella && Umbrella.is()) + if (const auto *Dir = std::get_if(&Umbrella)) return DirectoryName{UmbrellaAsWritten, - UmbrellaRelativeToRootModuleDirectory, - Umbrella.get()}; + UmbrellaRelativeToRootModuleDirectory, *Dir}; return std::nullopt; } /// Retrieve the umbrella header as written. std::optional
getUmbrellaHeaderAsWritten() const { - if (Umbrella && Umbrella.is()) + if (const auto *Hdr = std::get_if(&Umbrella)) return Header{UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory, - Umbrella.get()}; + *Hdr}; return std::nullopt; } diff --git a/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h b/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h index e0f3570e5b2bc..500a7e11ab9ac 100644 --- a/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h +++ b/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h @@ -278,14 +278,15 @@ class VerifyDiagnosticConsumer: public DiagnosticConsumer, // These facilities are used for validation in debug builds. class UnparsedFileStatus { - llvm::PointerIntPair Data; + OptionalFileEntryRef File; + bool FoundDirectives; public: UnparsedFileStatus(OptionalFileEntryRef File, bool FoundDirectives) - : Data(File, FoundDirectives) {} + : File(File), FoundDirectives(FoundDirectives) {} - OptionalFileEntryRef getFile() const { return Data.getPointer(); } - bool foundDirectives() const { return Data.getInt(); } + OptionalFileEntryRef getFile() const { return File; } + bool foundDirectives() const { return FoundDirectives; } }; using ParsedFilesMap = llvm::DenseMap; diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h index fc49742ad4af2..054d4211b9c6d 100644 --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -20,8 +20,8 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -194,7 +194,7 @@ class ModuleMap { } }; - using AdditionalModMapsSet = llvm::SmallPtrSet; + using AdditionalModMapsSet = llvm::DenseSet; private: friend class ModuleMapParser; diff --git a/clang/lib/ARCMigrate/FileRemapper.cpp b/clang/lib/ARCMigrate/FileRemapper.cpp index bd8317e0a2451..7abc862ceecc2 100644 --- a/clang/lib/ARCMigrate/FileRemapper.cpp +++ b/clang/lib/ARCMigrate/FileRemapper.cpp @@ -134,9 +134,8 @@ bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) { infoOut << origPath << '\n'; infoOut << (uint64_t)origFE.getModificationTime() << '\n'; - if (I->second.is()) { - auto FE = I->second.get(); - SmallString<200> newPath = StringRef(FE.getName()); + if (const auto *FE = std::get_if(&I->second)) { + SmallString<200> newPath = StringRef(FE->getName()); fs::make_absolute(newPath); infoOut << newPath << '\n'; } else { @@ -150,7 +149,7 @@ bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) { return report("Could not create file: " + tempPath.str(), Diag); llvm::raw_fd_ostream newOut(fd, /*shouldClose=*/true); - llvm::MemoryBuffer *mem = I->second.get(); + llvm::MemoryBuffer *mem = std::get(I->second); newOut.write(mem->getBufferStart(), mem->getBufferSize()); newOut.close(); @@ -173,7 +172,7 @@ bool FileRemapper::overwriteOriginal(DiagnosticsEngine &Diag, for (MappingsTy::iterator I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) { FileEntryRef origFE = I->first; - assert(I->second.is()); + assert(std::holds_alternative(I->second)); if (!fs::exists(origFE.getName())) return report(StringRef("File does not exist: ") + origFE.getName(), Diag); @@ -183,7 +182,7 @@ bool FileRemapper::overwriteOriginal(DiagnosticsEngine &Diag, if (EC) return report(EC.message(), Diag); - llvm::MemoryBuffer *mem = I->second.get(); + llvm::MemoryBuffer *mem = std::get(I->second); Out.write(mem->getBufferStart(), mem->getBufferSize()); Out.close(); } @@ -197,25 +196,23 @@ void FileRemapper::forEachMapping( llvm::function_ref CaptureBuffer) const { for (auto &Mapping : FromToMappings) { - if (Mapping.second.is()) { - auto FE = Mapping.second.get(); - CaptureFile(Mapping.first.getName(), FE.getName()); + if (const auto *FE = std::get_if(&Mapping.second)) { + CaptureFile(Mapping.first.getName(), FE->getName()); continue; } CaptureBuffer( Mapping.first.getName(), - Mapping.second.get()->getMemBufferRef()); + std::get(Mapping.second)->getMemBufferRef()); } } void FileRemapper::applyMappings(PreprocessorOptions &PPOpts) const { for (MappingsTy::const_iterator I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) { - if (I->second.is()) { - auto FE = I->second.get(); - PPOpts.addRemappedFile(I->first.getName(), FE.getName()); + if (const auto *FE = std::get_if(&I->second)) { + PPOpts.addRemappedFile(I->first.getName(), FE->getName()); } else { - llvm::MemoryBuffer *mem = I->second.get(); + llvm::MemoryBuffer *mem = std::get(I->second); PPOpts.addRemappedFile(I->first.getName(), mem); } } @@ -230,18 +227,20 @@ void FileRemapper::remap(StringRef filePath, remap(*File, std::move(memBuf)); } -void FileRemapper::remap(FileEntryRef file, - std::unique_ptr memBuf) { - Target &targ = FromToMappings[file]; - resetTarget(targ); - targ = memBuf.release(); +void FileRemapper::remap(FileEntryRef File, + std::unique_ptr MemBuf) { + auto [It, New] = FromToMappings.insert({File, nullptr}); + if (!New) + resetTarget(It->second); + It->second = MemBuf.release(); } -void FileRemapper::remap(FileEntryRef file, FileEntryRef newfile) { - Target &targ = FromToMappings[file]; - resetTarget(targ); - targ = newfile; - ToFromMappings.insert({newfile, file}); +void FileRemapper::remap(FileEntryRef File, FileEntryRef NewFile) { + auto [It, New] = FromToMappings.insert({File, nullptr}); + if (!New) + resetTarget(It->second); + It->second = NewFile; + ToFromMappings.insert({NewFile, File}); } OptionalFileEntryRef FileRemapper::getOriginalFile(StringRef filePath) { @@ -259,13 +258,11 @@ OptionalFileEntryRef FileRemapper::getOriginalFile(StringRef filePath) { } void FileRemapper::resetTarget(Target &targ) { - if (!targ) - return; - - if (llvm::MemoryBuffer *oldmem = targ.dyn_cast()) { + if (std::holds_alternative(targ)) { + llvm::MemoryBuffer *oldmem = std::get(targ); delete oldmem; } else { - FileEntryRef toFE = targ.get(); + FileEntryRef toFE = std::get(targ); ToFromMappings.erase(toFE); } } diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 7879a11179b6d..cc2e5be98d32d 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -265,10 +265,10 @@ bool Module::fullModuleNameIs(ArrayRef nameParts) const { } OptionalDirectoryEntryRef Module::getEffectiveUmbrellaDir() const { - if (Umbrella && Umbrella.is()) - return Umbrella.get().getDir(); - if (Umbrella && Umbrella.is()) - return Umbrella.get(); + if (const auto *Hdr = std::get_if(&Umbrella)) + return Hdr->getDir(); + if (const auto *Dir = std::get_if(&Umbrella)) + return *Dir; return std::nullopt; } diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 4c8b64a374b47..cf1c0cc5284f3 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -1623,7 +1623,7 @@ bool HeaderSearch::findUsableModuleForHeader( ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) { if (needModuleLookup(RequestingModule, SuggestedModule)) { // If there is a module that corresponds to this header, suggest it. - hasModuleMap(File.getName(), Root, IsSystemHeaderDir); + hasModuleMap(File.getNameAsRequested(), Root, IsSystemHeaderDir); return suggestModule(*this, File, RequestingModule, SuggestedModule); } return true; diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index f65a5f145c043..7fd92bff80484 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -2426,7 +2426,8 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, Header.Kind = Map.headerRoleToKind(Role); // Check whether we already have an umbrella. - if (Header.IsUmbrella && ActiveModule->Umbrella) { + if (Header.IsUmbrella && + !std::holds_alternative(ActiveModule->Umbrella)) { Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) << ActiveModule->getFullModuleName(); HadError = true; @@ -2523,7 +2524,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { SourceLocation DirNameLoc = consumeToken(); // Check whether we already have an umbrella. - if (ActiveModule->Umbrella) { + if (!std::holds_alternative(ActiveModule->Umbrella)) { Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) << ActiveModule->getFullModuleName(); HadError = true; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index cce403d7c6c44..9061efb6511db 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -4175,7 +4175,7 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, return OutOfDate; } - llvm::SmallPtrSet AdditionalStoredMaps; + ModuleMap::AdditionalModMapsSet AdditionalStoredMaps; for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) { // FIXME: we should use input files rather than storing names. std::string Filename = ReadPath(F, Record, Idx); diff --git a/clang/test/Modules/Inputs/all-product-headers.yaml b/clang/test/Modules/Inputs/all-product-headers.yaml new file mode 100644 index 0000000000000..53d683f2ad2ec --- /dev/null +++ b/clang/test/Modules/Inputs/all-product-headers.yaml @@ -0,0 +1,33 @@ +{ + 'version': 0, + 'case-sensitive': 'false', + 'roots': [ + { + 'type': 'directory', + 'name': "DUMMY_DIR/build/A.framework/PrivateHeaders" + 'contents': [ + { + 'type': 'file', + 'name': "A.h", + 'external-contents': "DUMMY_DIR/sources/A.h" + } + ] + }, + { + 'type': 'directory', + 'name': "DUMMY_DIR/build/A.framework/Modules" + 'contents': [ + { + 'type': 'file', + 'name': "module.modulemap", + 'external-contents': "DUMMY_DIR/build/module.modulemap" + }, + { + 'type': 'file', + 'name': "module.private.modulemap", + 'external-contents': "DUMMY_DIR/build/module.private.modulemap" + } + ] + } + ] +} diff --git a/clang/test/Modules/modulemap-collision.m b/clang/test/Modules/modulemap-collision.m new file mode 100644 index 0000000000000..5ada45da3dae1 --- /dev/null +++ b/clang/test/Modules/modulemap-collision.m @@ -0,0 +1,15 @@ +// REQUIRES: shell + +// RUN: rm -rf %t +// RUN: mkdir -p %t/sources %t/build +// RUN: echo "// A.h" > %t/sources/A.h +// RUN: echo "framework module A {}" > %t/sources/module.modulemap +// RUN: echo "framework module A.Private { umbrella header \"A.h\" }" > %t/sources/module.private.modulemap +// RUN: cp %t/sources/module.modulemap %t/build/module.modulemap +// RUN: cp %t/sources/module.private.modulemap %t/build/module.private.modulemap + +// RUN: sed -e "s:DUMMY_DIR:%t:g" %S/Inputs/all-product-headers.yaml > %t/build/all-product-headers.yaml +// RUN: %clang_cc1 -fsyntax-only -ivfsoverlay %t/build/all-product-headers.yaml -F%t/build -fmodules -fimplicit-module-maps -Wno-private-module -fmodules-cache-path=%t/cache -x objective-c %s -verify + +// expected-no-diagnostics +#import