[clang] [llvm] [clang][modules] Separate parsing of modulemaps (PR #119740)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 12 10:36:50 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-adt

Author: Michael Spencer (Bigcheese)

<details>
<summary>Changes</summary>

This separates out parsing of modulemaps from updating the `clang::ModuleMap` information.

Currently this has no effect other than slightly changing diagnostics. Upcoming changes will use this to allow searching for modules without fully processing modulemaps.


This creates a new `modulemap` namespace because there are too many things called ModuleMap* right now that mean different things. I'd like to clean this up, but I'm not sure yet what I want to call everything.

This also drops the `SourceLocation` from `moduleMapFileRead`. This is never used in tree, and in future patches I plan to make the modulemap parser use a different `SourceManager` so that we can share modulemap parsing between `CompilerInstance`s. This will make the `SourceLocation` meaningless.

---

Patch is 101.49 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/119740.diff


11 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticLexKinds.td (+2) 
- (modified) clang/include/clang/Basic/Module.h (+24) 
- (modified) clang/include/clang/Lex/ModuleMap.h (+1-23) 
- (added) clang/include/clang/Lex/ModuleMapFile.h (+142) 
- (modified) clang/lib/Lex/CMakeLists.txt (+1) 
- (modified) clang/lib/Lex/ModuleMap.cpp (+189-1211) 
- (added) clang/lib/Lex/ModuleMapFile.cpp (+1248) 
- (modified) clang/test/Modules/Inputs/export_as_test.modulemap (+4) 
- (modified) clang/test/Modules/diagnostics.modulemap (+12-9) 
- (modified) clang/test/Modules/export_as_test.c (+2-3) 
- (modified) llvm/include/llvm/ADT/STLExtras.h (+9) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 959376b0847216..e5869619e69d35 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -914,6 +914,8 @@ def warn_mmap_redundant_export_as : Warning<
   InGroup<PrivateModule>;
 def err_mmap_submodule_export_as : Error<
   "only top-level modules can be re-exported as public">;
+def err_mmap_qualified_export_as : Error<
+  "a module can only be re-exported as another top-level module">;
 
 def warn_quoted_include_in_framework_header : Warning<
   "double-quoted include \"%0\" in framework header, "
diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h
index dd384c1d76c5fd..ef6e2ac95d0819 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -100,6 +100,30 @@ struct ASTFileSignature : std::array<uint8_t, 20> {
   }
 };
 
+/// The set of attributes that can be attached to a module.
+struct ModuleAttributes {
+  /// Whether this is a system module.
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned IsSystem : 1;
+
+  /// Whether this is an extern "C" module.
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned IsExternC : 1;
+
+  /// Whether this is an exhaustive set of configuration macros.
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned IsExhaustive : 1;
+
+  /// Whether files in this module can only include non-modular headers
+  /// and headers from used modules.
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned NoUndeclaredIncludes : 1;
+
+  ModuleAttributes()
+      : IsSystem(false), IsExternC(false), IsExhaustive(false),
+        NoUndeclaredIncludes(false) {}
+};
+
 /// Required to construct a Module.
 ///
 /// This tag type is only constructible by ModuleMap, guaranteeing it ownership
diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h
index 53e9e0ec83ddb1..9de1b3b546c115 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -232,29 +232,7 @@ class ModuleMap {
 
   llvm::DenseMap<Module *, unsigned> ModuleScopeIDs;
 
-  /// The set of attributes that can be attached to a module.
-  struct Attributes {
-    /// Whether this is a system module.
-    LLVM_PREFERRED_TYPE(bool)
-    unsigned IsSystem : 1;
-
-    /// Whether this is an extern "C" module.
-    LLVM_PREFERRED_TYPE(bool)
-    unsigned IsExternC : 1;
-
-    /// Whether this is an exhaustive set of configuration macros.
-    LLVM_PREFERRED_TYPE(bool)
-    unsigned IsExhaustive : 1;
-
-    /// Whether files in this module can only include non-modular headers
-    /// and headers from used modules.
-    LLVM_PREFERRED_TYPE(bool)
-    unsigned NoUndeclaredIncludes : 1;
-
-    Attributes()
-        : IsSystem(false), IsExternC(false), IsExhaustive(false),
-          NoUndeclaredIncludes(false) {}
-  };
+  using Attributes = ModuleAttributes;
 
   /// A directory for which framework modules can be inferred.
   struct InferredDirectory {
diff --git a/clang/include/clang/Lex/ModuleMapFile.h b/clang/include/clang/Lex/ModuleMapFile.h
new file mode 100644
index 00000000000000..8b79897876ad61
--- /dev/null
+++ b/clang/include/clang/Lex/ModuleMapFile.h
@@ -0,0 +1,142 @@
+//===- ModuleMapFile.h - Parsing and representation -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_MODULEMAPFILE_H
+#define LLVM_CLANG_LEX_MODULEMAPFILE_H
+
+#include "clang/Basic/LLVM.h"
+// TODO: Consider moving ModuleId to another header, parsing a modulemap file is
+//   intended to not depend on anything about the clang::Module class.
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <optional>
+#include <variant>
+
+namespace clang {
+
+class DiagnosticsEngine;
+class SourceManager;
+
+namespace modulemap {
+
+using Decl =
+    std::variant<struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl,
+                 struct ModuleDecl, struct ExcludeDecl, struct ExportDecl,
+                 struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl,
+                 struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl>;
+
+struct RequiresFeature {
+  SourceLocation Location;
+  StringRef Feature;
+  bool RequiredState = true;
+};
+
+struct RequiresDecl {
+  SourceLocation Location;
+  std::vector<RequiresFeature> Features;
+};
+
+struct HeaderDecl {
+  SourceLocation Location;
+  StringRef Path;
+  SourceLocation PathLoc;
+  std::optional<int64_t> Size;
+  std::optional<int64_t> MTime;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Private : 1;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Textual : 1;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Umbrella : 1;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Excluded : 1;
+};
+
+struct UmbrellaDirDecl {
+  SourceLocation Location;
+  StringRef Path;
+};
+
+struct ModuleDecl {
+  SourceLocation Location; /// Points to the first keyword in the decl.
+  ModuleId Id;
+  ModuleAttributes Attrs;
+  std::vector<Decl> Decls;
+
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Explicit : 1;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Framework : 1;
+};
+
+struct ExcludeDecl {
+  SourceLocation Location;
+  StringRef Module;
+};
+
+struct ExportDecl {
+  SourceLocation Location;
+  ModuleId Id;
+  bool Wildcard;
+};
+
+struct ExportAsDecl {
+  SourceLocation Location;
+  ModuleId Id;
+};
+
+struct ExternModuleDecl {
+  SourceLocation Location;
+  ModuleId Id;
+  StringRef Path;
+};
+
+struct UseDecl {
+  SourceLocation Location;
+  ModuleId Id;
+};
+
+struct LinkDecl {
+  SourceLocation Location;
+  StringRef Library;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Framework : 1;
+};
+
+struct ConfigMacrosDecl {
+  SourceLocation Location;
+  std::vector<StringRef> Macros;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Exhaustive : 1;
+};
+
+struct ConflictDecl {
+  SourceLocation Location;
+  ModuleId Id;
+  StringRef Message;
+};
+
+using TopLevelDecl =
+    std::variant<ModuleDecl, ExternModuleDecl>;
+
+struct ModuleMapFile {
+  std::vector<TopLevelDecl> Decls;
+};
+
+std::optional<ModuleMapFile> parseModuleMap(FileEntryRef File,
+                                            SourceManager &SM,
+                                            DiagnosticsEngine &Diags,
+                                            bool IsSystem, unsigned *Offset);
+void dumpModuleMapFile(ModuleMapFile &MMF, llvm::raw_ostream &out);
+
+} // namespace modulemap
+} // namespace clang
+
+#endif
diff --git a/clang/lib/Lex/CMakeLists.txt b/clang/lib/Lex/CMakeLists.txt
index 766336b89a2382..5a049a1d84fd0d 100644
--- a/clang/lib/Lex/CMakeLists.txt
+++ b/clang/lib/Lex/CMakeLists.txt
@@ -15,6 +15,7 @@ add_clang_library(clangLex
   MacroArgs.cpp
   MacroInfo.cpp
   ModuleMap.cpp
+  ModuleMapFile.cpp
   PPCaching.cpp
   PPCallbacks.cpp
   PPConditionalDirectiveRecord.cpp
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index ccf94f6345ff28..11b38db9eb6526 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -24,9 +24,7 @@
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/LexDiagnostic.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Lex/LiteralSupport.h"
-#include "clang/Lex/Token.h"
+#include "clang/Lex/ModuleMapFile.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
@@ -34,7 +32,6 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/Allocator.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Path.h"
@@ -1461,81 +1458,10 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
 //----------------------------------------------------------------------------//
 
 namespace clang {
-
-  /// A token in a module map file.
-  struct MMToken {
-    enum TokenKind {
-      Comma,
-      ConfigMacros,
-      Conflict,
-      EndOfFile,
-      HeaderKeyword,
-      Identifier,
-      Exclaim,
-      ExcludeKeyword,
-      ExplicitKeyword,
-      ExportKeyword,
-      ExportAsKeyword,
-      ExternKeyword,
-      FrameworkKeyword,
-      LinkKeyword,
-      ModuleKeyword,
-      Period,
-      PrivateKeyword,
-      UmbrellaKeyword,
-      UseKeyword,
-      RequiresKeyword,
-      Star,
-      StringLiteral,
-      IntegerLiteral,
-      TextualKeyword,
-      LBrace,
-      RBrace,
-      LSquare,
-      RSquare
-    } Kind;
-
-    SourceLocation::UIntTy Location;
-    unsigned StringLength;
-    union {
-      // If Kind != IntegerLiteral.
-      const char *StringData;
-
-      // If Kind == IntegerLiteral.
-      uint64_t IntegerValue;
-    };
-
-    void clear() {
-      Kind = EndOfFile;
-      Location = 0;
-      StringLength = 0;
-      StringData = nullptr;
-    }
-
-    bool is(TokenKind K) const { return Kind == K; }
-
-    SourceLocation getLocation() const {
-      return SourceLocation::getFromRawEncoding(Location);
-    }
-
-    uint64_t getInteger() const {
-      return Kind == IntegerLiteral ? IntegerValue : 0;
-    }
-
-    StringRef getString() const {
-      return Kind == IntegerLiteral ? StringRef()
-                                    : StringRef(StringData, StringLength);
-    }
-  };
-
   class ModuleMapParser {
-    Lexer &L;
+    modulemap::ModuleMapFile &MMF;
     SourceManager &SourceMgr;
 
-    /// Default target information, used only for string literal
-    /// parsing.
-    const TargetInfo *Target;
-
     DiagnosticsEngine &Diags;
     ModuleMap ⤅
 
@@ -1555,13 +1481,6 @@ namespace clang {
     /// Whether an error occurred.
     bool HadError = false;
 
-    /// Stores string data for the various string literals referenced
-    /// during parsing.
-    llvm::BumpPtrAllocator StringData;
-
-    /// The current token.
-    MMToken Tok;
-
     /// The active module.
     Module *ActiveModule = nullptr;
 
@@ -1575,305 +1494,45 @@ namespace clang {
     /// 'textual' to match the original intent.
     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
 
-    /// Consume the current token and return its location.
-    SourceLocation consumeToken();
-
-    /// Skip tokens until we reach the a token with the given kind
-    /// (or the end of the file).
-    void skipUntil(MMToken::TokenKind K);
-
-    bool parseModuleId(ModuleId &Id);
-    void parseModuleDecl();
-    void parseExternModuleDecl();
-    void parseRequiresDecl();
-    void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
-    void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
-    void parseExportDecl();
-    void parseExportAsDecl();
-    void parseUseDecl();
-    void parseLinkDecl();
-    void parseConfigMacros();
-    void parseConflict();
-    void parseInferredModuleDecl(bool Framework, bool Explicit);
+    void handleModuleDecl(const modulemap::ModuleDecl &MD);
+    void handleExternModuleDecl(const modulemap::ExternModuleDecl &EMD);
+    void handleRequiresDecl(const modulemap::RequiresDecl &RD);
+    void handleHeaderDecl(const modulemap::HeaderDecl &HD);
+    void handleUmbrellaDirDecl(const modulemap::UmbrellaDirDecl &UDD);
+    void handleExportDecl(const modulemap::ExportDecl &ED);
+    void handleExportAsDecl(const modulemap::ExportAsDecl &EAD);
+    void handleUseDecl(const modulemap::UseDecl &UD);
+    void handleLinkDecl(const modulemap::LinkDecl &LD);
+    void handleConfigMacros(const modulemap::ConfigMacrosDecl &CMD);
+    void handleConflict(const modulemap::ConflictDecl &CD);
+    void handleInferredModuleDecl(const modulemap::ModuleDecl &MD);
 
     /// Private modules are canonicalized as Foo_Private. Clang provides extra
     /// module map search logic to find the appropriate private module when PCH
     /// is used with implicit module maps. Warn when private modules are written
     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
-    void diagnosePrivateModules(SourceLocation ExplicitLoc,
-                                SourceLocation FrameworkLoc);
+    void diagnosePrivateModules(SourceLocation StartLoc);
 
     using Attributes = ModuleMap::Attributes;
 
-    bool parseOptionalAttributes(Attributes &Attrs);
-
   public:
-    ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
-                    const TargetInfo *Target, DiagnosticsEngine &Diags,
+    ModuleMapParser(modulemap::ModuleMapFile &MMF,
+                    SourceManager &SourceMgr, DiagnosticsEngine &Diags,
                     ModuleMap &Map, FileID ModuleMapFID,
                     DirectoryEntryRef Directory, bool IsSystem)
-        : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
-          ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem) {
-      Tok.clear();
-      consumeToken();
-    }
+        : MMF(MMF), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
+          ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem) {}
 
     bool parseModuleMapFile();
-
-    bool terminatedByDirective() { return false; }
-    SourceLocation getLocation() { return Tok.getLocation(); }
   };
 
 } // namespace clang
 
-SourceLocation ModuleMapParser::consumeToken() {
-  SourceLocation Result = Tok.getLocation();
-
-retry:
-  Tok.clear();
-  Token LToken;
-  L.LexFromRawLexer(LToken);
-  Tok.Location = LToken.getLocation().getRawEncoding();
-  switch (LToken.getKind()) {
-  case tok::raw_identifier: {
-    StringRef RI = LToken.getRawIdentifier();
-    Tok.StringData = RI.data();
-    Tok.StringLength = RI.size();
-    Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
-                 .Case("config_macros", MMToken::ConfigMacros)
-                 .Case("conflict", MMToken::Conflict)
-                 .Case("exclude", MMToken::ExcludeKeyword)
-                 .Case("explicit", MMToken::ExplicitKeyword)
-                 .Case("export", MMToken::ExportKeyword)
-                 .Case("export_as", MMToken::ExportAsKeyword)
-                 .Case("extern", MMToken::ExternKeyword)
-                 .Case("framework", MMToken::FrameworkKeyword)
-                 .Case("header", MMToken::HeaderKeyword)
-                 .Case("link", MMToken::LinkKeyword)
-                 .Case("module", MMToken::ModuleKeyword)
-                 .Case("private", MMToken::PrivateKeyword)
-                 .Case("requires", MMToken::RequiresKeyword)
-                 .Case("textual", MMToken::TextualKeyword)
-                 .Case("umbrella", MMToken::UmbrellaKeyword)
-                 .Case("use", MMToken::UseKeyword)
-                 .Default(MMToken::Identifier);
-    break;
-  }
-
-  case tok::comma:
-    Tok.Kind = MMToken::Comma;
-    break;
-
-  case tok::eof:
-    Tok.Kind = MMToken::EndOfFile;
-    break;
-
-  case tok::l_brace:
-    Tok.Kind = MMToken::LBrace;
-    break;
-
-  case tok::l_square:
-    Tok.Kind = MMToken::LSquare;
-    break;
-
-  case tok::period:
-    Tok.Kind = MMToken::Period;
-    break;
-
-  case tok::r_brace:
-    Tok.Kind = MMToken::RBrace;
-    break;
-
-  case tok::r_square:
-    Tok.Kind = MMToken::RSquare;
-    break;
-
-  case tok::star:
-    Tok.Kind = MMToken::Star;
-    break;
-
-  case tok::exclaim:
-    Tok.Kind = MMToken::Exclaim;
-    break;
-
-  case tok::string_literal: {
-    if (LToken.hasUDSuffix()) {
-      Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
-      HadError = true;
-      goto retry;
-    }
-
-    // Parse the string literal.
-    LangOptions LangOpts;
-    StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
-    if (StringLiteral.hadError)
-      goto retry;
-
-    // Copy the string literal into our string data allocator.
-    unsigned Length = StringLiteral.GetStringLength();
-    char *Saved = StringData.Allocate<char>(Length + 1);
-    memcpy(Saved, StringLiteral.GetString().data(), Length);
-    Saved[Length] = 0;
-
-    // Form the token.
-    Tok.Kind = MMToken::StringLiteral;
-    Tok.StringData = Saved;
-    Tok.StringLength = Length;
-    break;
-  }
-
-  case tok::numeric_constant: {
-    // We don't support any suffixes or other complications.
-    SmallString<32> SpellingBuffer;
-    SpellingBuffer.resize(LToken.getLength() + 1);
-    const char *Start = SpellingBuffer.data();
-    unsigned Length =
-        Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts);
-    uint64_t Value;
-    if (StringRef(Start, Length).getAsInteger(0, Value)) {
-      Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
-      HadError = true;
-      goto retry;
-    }
-
-    Tok.Kind = MMToken::IntegerLiteral;
-    Tok.IntegerValue = Value;
-    break;
-  }
-
-  case tok::comment:
-    goto retry;
-
-  case tok::hash:
-    // A module map can be terminated prematurely by
-    //   #pragma clang module contents
-    // When building the module, we'll treat the rest of the file as the
-    // contents of the module.
-    {
-      auto NextIsIdent = [&](StringRef Str) -> bool {
-        L.LexFromRawLexer(LToken);
-        return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
-               LToken.getRawIdentifier() == Str;
-      };
-      if (NextIsIdent("pragma") && NextIsIdent("clang") &&
-          NextIsIdent("module") && NextIsIdent("contents")) {
-        Tok.Kind = MMToken::EndOfFile;
-        break;
-      }
-    }
-    [[fallthrough]];
-
-  default:
-    Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
-    HadError = true;
-    goto retry;
-  }
-
-  return Result;
-}
-
-void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
-  unsigned braceDepth = 0;
-  unsigned squareDepth = 0;
-  do {
-    switch (Tok.Kind) {
-    case MMToken::EndOfFile:
-      return;
-
-    case MMToken::LBrace:
-      if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
-        return;
-
-      ++braceDepth;
-      break;
-
-    case MMToken::LSquare:
-      if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
-        return;
-
-      ++squareDepth;
-      break;
-
-    case MMToken::RBrace:
-      if (braceDepth > 0)
-        --braceDepth;
-      else if (Tok.is(K))
-        return;
-      break;
-
-    case MMToken::RSquare:
-      if (squareDepth > 0)
-        --squareDepth;
-      else if (Tok.is(K))
-        return;
-      break;
-
-    default:
-      if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
-        return;
-      break;
-    }
-
-   consumeToken();
-  } while (true);
-}
-
-/// Parse a module-id.
-///
-///   module-id:
-///     identifier
-///     identifier '.' module-id
-///
-/// \returns true if an error occurred, false otherwise.
-bool ModuleMapParser::parseModuleId(ModuleId &Id) {
-  Id.clear();
-  do {
-    if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
-      Id.push_back(
-          std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
-      consumeToken();
-    } else {
-      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
-      return true;
-    }
-
-    if (!Tok.is(MMToken::Period))
-      break;
-
-    consumeToken();
-  } while (true);
-
-  return false;
-}
-
-namespace {
-
-  /// Enumerates the known attributes.
-  enum AttributeKind {
-    /// An unknown attribute.
-    AT_unknown,
-
-    /// The 'system' attribute.
-    AT_system,
-
-    /// The 'extern_c' attribute.
-    AT_extern_c,
-
-    /// The 'exhaustive' attribute.
-    AT_exhaustive,
-
-    /// The 'no_undeclared_includes' attribute.
-    AT_no_undeclared_includes
-  };
-
-} // namespace
-
 /// Private modules are canonicalized as Foo_Private. Clang provides extra
 /// module map search logic to find the appropriate private module when PCH
 /// is used with implicit module maps. Warn when private modules are written
 /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
-void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
-                                             SourceLocation FrameworkLoc) {
+void ModuleMapParser::diagnosePrivateModules(SourceLocation StartLoc) {
   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
                              co...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/119740


More information about the llvm-commits mailing list