Skip to content

Revert "Reapply "[C++20][Modules] Implement P1857R3 Modules Dependency Discovery" (#173130)"#173549

Merged
yronglin merged 1 commit intollvm:mainfrom
yronglin:revert_173130
Dec 25, 2025
Merged

Revert "Reapply "[C++20][Modules] Implement P1857R3 Modules Dependency Discovery" (#173130)"#173549
yronglin merged 1 commit intollvm:mainfrom
yronglin:revert_173130

Conversation

@yronglin
Copy link
Contributor

This reverts commit 0d1c396.

@yronglin yronglin requested a review from Endilll as a code owner December 25, 2025 11:55
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Dec 25, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 25, 2025

@llvm/pr-subscribers-clang

Author: None (yronglin)

Changes

This reverts commit 0d1c396.


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

44 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (-1)
  • (modified) clang/docs/StandardCPlusPlusModules.rst (+27)
  • (modified) clang/include/clang/Basic/DiagnosticLexKinds.td (+2-17)
  • (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+4-6)
  • (modified) clang/include/clang/Basic/IdentifierTable.h (+10-28)
  • (modified) clang/include/clang/Basic/TokenKinds.def (-8)
  • (modified) clang/include/clang/Basic/TokenKinds.h (-4)
  • (modified) clang/include/clang/Frontend/CompilerInstance.h (+1-1)
  • (modified) clang/include/clang/Lex/CodeCompletionHandler.h (-8)
  • (modified) clang/include/clang/Lex/DependencyDirectivesScanner.h (-16)
  • (modified) clang/include/clang/Lex/ModuleLoader.h (-1)
  • (modified) clang/include/clang/Lex/Preprocessor.h (+61-135)
  • (modified) clang/include/clang/Lex/Token.h (-4)
  • (modified) clang/include/clang/Lex/TokenLexer.h (-12)
  • (modified) clang/include/clang/Parse/Parser.h (+4-5)
  • (modified) clang/lib/Basic/IdentifierTable.cpp (+2-14)
  • (modified) clang/lib/Basic/TokenKinds.cpp (-12)
  • (modified) clang/lib/DependencyScanning/ModuleDepCollector.cpp (+1-2)
  • (modified) clang/lib/Frontend/CompilerInstance.cpp (+4-8)
  • (modified) clang/lib/Frontend/InitPreprocessor.cpp (-7)
  • (modified) clang/lib/Frontend/PrintPreprocessedOutput.cpp (+1-32)
  • (modified) clang/lib/Lex/DependencyDirectivesScanner.cpp (+15-149)
  • (modified) clang/lib/Lex/Lexer.cpp (+10-46)
  • (modified) clang/lib/Lex/PPDirectives.cpp (+31-441)
  • (modified) clang/lib/Lex/Preprocessor.cpp (+209-277)
  • (modified) clang/lib/Lex/TokenConcatenation.cpp (+3-5)
  • (modified) clang/lib/Lex/TokenLexer.cpp (+1-29)
  • (modified) clang/lib/Parse/Parser.cpp (+77-47)
  • (modified) clang/lib/Sema/SemaModule.cpp (+24-7)
  • (modified) clang/test/CXX/basic/basic.link/p3.cpp (+8-7)
  • (modified) clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp (+1-1)
  • (removed) clang/test/CXX/drs/cwg2947.cpp (-81)
  • (modified) clang/test/CXX/lex/lex.pptoken/p3-2a.cpp (+14-19)
  • (modified) clang/test/CXX/module/basic/basic.link/module-declaration.cpp (+2-2)
  • (removed) clang/test/CXX/module/cpp.pre/p1.cpp (-207)
  • (modified) clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm (+4-4)
  • (removed) clang/test/Lexer/cxx20-module-directive.cpp (-11)
  • (modified) clang/test/Modules/pr121066.cpp (+1-3)
  • (modified) clang/test/Modules/preprocess-named-modules.cppm (+1-1)
  • (modified) clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp (+1-2)
  • (modified) clang/unittests/Lex/DependencyDirectivesScannerTest.cpp (+5-43)
  • (modified) clang/unittests/Lex/ModuleDeclStateTest.cpp (+1-1)
  • (modified) clang/www/cxx_dr_status.html (+1-1)
  • (modified) clang/www/cxx_status.html (+9-2)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7bf003f700448..2319ff13f7864 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -209,7 +209,6 @@ C++20 Feature Support
 - Clang now normalizes constraints before checking whether they are satisfied, as mandated by the standard.
   As a result, Clang no longer incorrectly diagnoses substitution failures in template arguments only
   used in concept-ids, and produces better diagnostics for satisfaction failure. (#GH61811) (#GH135190)
-- Clang now supports `P1857R3 <https://wg21.link/p1857r3>`_ Modules Dependency Discovery. (#GH54047)
 
 C++17 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/docs/StandardCPlusPlusModules.rst b/clang/docs/StandardCPlusPlusModules.rst
index f6ab17ede46fa..71988d0fced98 100644
--- a/clang/docs/StandardCPlusPlusModules.rst
+++ b/clang/docs/StandardCPlusPlusModules.rst
@@ -1384,6 +1384,33 @@ declarations which use it. Thus, the preferred name will not be displayed in
 the debugger as expected. This is tracked by
 `#56490 <https://github.com/llvm/llvm-project/issues/56490>`_.
 
+Don't emit macros about module declaration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is covered by `P1857R3 <https://wg21.link/P1857R3>`_. It is mentioned here
+because we want users to be aware that we don't yet implement it.
+
+A direct approach to write code that can be compiled by both modules and
+non-module builds may look like:
+
+.. code-block:: c++
+
+  MODULE
+  IMPORT header_name
+  EXPORT_MODULE MODULE_NAME;
+  IMPORT header_name
+  EXPORT ...
+
+The intent of this is that this file can be compiled like a module unit or a
+non-module unit depending on the definition of some macros. However, this usage
+is forbidden by P1857R3 which is not yet implemented in Clang. This means that
+is possible to write invalid modules which will no longer be accepted once
+P1857R3 is implemented. This is tracked by
+`#54047 <https://github.com/llvm/llvm-project/issues/54047>`_.
+
+Until then, it is recommended not to mix macros with module declarations.
+
+
 Inconsistent filename suffix requirement for importable module units
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 77feea9f869e9..a72d3f37b1b72 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -503,8 +503,8 @@ def warn_cxx98_compat_variadic_macro : Warning<
   InGroup<CXX98CompatPedantic>, DefaultIgnore;
 def ext_named_variadic_macro : Extension<
   "named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
-def err_embedded_directive : Error<"embedding a %select{#|C++ }0%1 directive "
-                                   "within macro arguments is not supported">;
+def err_embedded_directive : Error<
+  "embedding a #%0 directive within macro arguments is not supported">;
 def ext_embedded_directive : Extension<
   "embedding a directive within macro arguments has undefined behavior">,
   InGroup<DiagGroup<"embedded-directive">>;
@@ -998,21 +998,6 @@ def warn_module_conflict : Warning<
   InGroup<ModuleConflict>;
 
 // C++20 modules
-def err_pp_module_name_is_macro : Error<
-  "%select{module|partition}0 name component %1 cannot be a object-like macro">;
-def err_pp_module_expected_ident : Error<
-  "expected %select{identifier after '.' in |}0module name">;
-def err_pp_unexpected_tok_after_module_name : Error<
-  "unexpected preprocessing token '%0' after module name, "
-  "only ';' and '[' (start of attribute specifier sequence) are allowed">;
-def warn_pp_extra_tokens_at_module_directive_eol
-    : Warning<"extra tokens after semicolon in '%0' directive">,
-      InGroup<ExtraTokens>;
-def err_pp_module_decl_in_header
-    : Error<"module declaration must not come from an #include directive">;
-def err_pp_cond_span_module_decl
-    : Error<"module directive lines are not allowed on lines controlled "
-    "by preprocessor conditionals">;
 def err_header_import_semi_in_macro : Error<
   "semicolon terminating header import declaration cannot be produced "
   "by a macro">;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 83d4ce3ca278c..662fe16d965b6 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1792,8 +1792,10 @@ def ext_bit_int : Extension<
 } // end of Parse Issue category.
 
 let CategoryName = "Modules Issue" in {
-def err_unexpected_module_or_import_decl : Error<
-  "%select{module|import}0 declaration can only appear at the top level">;
+def err_unexpected_module_decl : Error<
+  "module declaration can only appear at the top level">;
+def err_module_expected_ident : Error<
+  "expected a module name after '%select{module|import}0'">;
 def err_attribute_not_module_attr : Error<
   "%0 attribute cannot be applied to a module">;
 def err_keyword_not_module_attr : Error<
@@ -1804,10 +1806,6 @@ def err_keyword_not_import_attr : Error<
   "%0 cannot be applied to a module import">;
 def err_module_expected_semi : Error<
   "expected ';' after module name">;
-def err_expected_semi_after_module_or_import
-  : Error<"%0 directive must end with a ';'">;
-def note_module_declared_here : Note<
-  "%select{module|import}0 directive defined here">;
 def err_global_module_introducer_not_at_start : Error<
   "'module;' introducing a global module fragment can appear only "
   "at the start of the translation unit">;
diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h
index 1131727ed23ee..043c184323876 100644
--- a/clang/include/clang/Basic/IdentifierTable.h
+++ b/clang/include/clang/Basic/IdentifierTable.h
@@ -231,10 +231,6 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
   LLVM_PREFERRED_TYPE(bool)
   unsigned IsModulesImport : 1;
 
-  // True if this is the 'module' contextual keyword.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsModulesDecl : 1;
-
   // True if this is a mangled OpenMP variant name.
   LLVM_PREFERRED_TYPE(bool)
   unsigned IsMangledOpenMPVariantName : 1;
@@ -271,9 +267,8 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
         IsCPPOperatorKeyword(false), NeedsHandleIdentifier(false),
         IsFromAST(false), ChangedAfterLoad(false), FEChangedAfterLoad(false),
         RevertedTokenID(false), OutOfDate(false), IsModulesImport(false),
-        IsModulesDecl(false), IsMangledOpenMPVariantName(false),
-        IsDeprecatedMacro(false), IsRestrictExpansion(false), IsFinal(false),
-        IsKeywordInCpp(false) {}
+        IsMangledOpenMPVariantName(false), IsDeprecatedMacro(false),
+        IsRestrictExpansion(false), IsFinal(false), IsKeywordInCpp(false) {}
 
 public:
   IdentifierInfo(const IdentifierInfo &) = delete;
@@ -574,24 +569,12 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
   }
 
   /// Determine whether this is the contextual keyword \c import.
-  bool isImportKeyword() const { return IsModulesImport; }
+  bool isModulesImport() const { return IsModulesImport; }
 
   /// Set whether this identifier is the contextual keyword \c import.
-  void setKeywordImport(bool Val) {
-    IsModulesImport = Val;
-    if (Val)
-      NeedsHandleIdentifier = true;
-    else
-      RecomputeNeedsHandleIdentifier();
-  }
-
-  /// Determine whether this is the contextual keyword \c module.
-  bool isModuleKeyword() const { return IsModulesDecl; }
-
-  /// Set whether this identifier is the contextual keyword \c module.
-  void setModuleKeyword(bool Val) {
-    IsModulesDecl = Val;
-    if (Val)
+  void setModulesImport(bool I) {
+    IsModulesImport = I;
+    if (I)
       NeedsHandleIdentifier = true;
     else
       RecomputeNeedsHandleIdentifier();
@@ -646,7 +629,7 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
   void RecomputeNeedsHandleIdentifier() {
     NeedsHandleIdentifier = isPoisoned() || hasMacroDefinition() ||
                             isExtensionToken() || isFutureCompatKeyword() ||
-                            isOutOfDate() || isImportKeyword();
+                            isOutOfDate() || isModulesImport();
   }
 };
 
@@ -814,11 +797,10 @@ class IdentifierTable {
     // contents.
     II->Entry = &Entry;
 
-    // If this is the 'import' or 'module' contextual keyword, mark it as such.
+    // If this is the 'import' contextual keyword, mark it as such.
     if (Name == "import")
-      II->setKeywordImport(true);
-    else if (Name == "module")
-      II->setModuleKeyword(true);
+      II->setModulesImport(true);
+
     return *II;
   }
 
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index a3d286fdb81a7..3d955095b07a8 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -133,11 +133,6 @@ PPKEYWORD(pragma)
 // C23 & C++26 #embed
 PPKEYWORD(embed)
 
-// C++20 Module Directive
-PPKEYWORD(module)
-PPKEYWORD(__preprocessed_module)
-PPKEYWORD(__preprocessed_import)
-
 // GNU Extensions.
 PPKEYWORD(import)
 PPKEYWORD(include_next)
@@ -1035,9 +1030,6 @@ ANNOTATION(module_include)
 ANNOTATION(module_begin)
 ANNOTATION(module_end)
 
-// Annotations for C++, Clang and Objective-C named modules.
-ANNOTATION(module_name)
-
 // Annotation for a header_name token that has been looked up and transformed
 // into the name of a header unit.
 ANNOTATION(header_unit)
diff --git a/clang/include/clang/Basic/TokenKinds.h b/clang/include/clang/Basic/TokenKinds.h
index c0316257d9d97..a801113c57715 100644
--- a/clang/include/clang/Basic/TokenKinds.h
+++ b/clang/include/clang/Basic/TokenKinds.h
@@ -76,10 +76,6 @@ const char *getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE;
 /// tokens like 'int' and 'dynamic_cast'. Returns NULL for other token kinds.
 const char *getKeywordSpelling(TokenKind Kind) LLVM_READNONE;
 
-/// Determines the spelling of simple Objective-C keyword tokens like '@import'.
-/// Returns NULL for other token kinds.
-const char *getObjCKeywordSpelling(ObjCKeywordKind Kind) LLVM_READNONE;
-
 /// Returns the spelling of preprocessor keywords, such as "else".
 const char *getPPKeywordSpelling(PPKeywordKind Kind) LLVM_READNONE;
 
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 6db1be7f0ed58..ded5f55d180aa 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -905,7 +905,7 @@ class CompilerInstance : public ModuleLoader {
   /// load it.
   ModuleLoadResult findOrCompileModuleAndReadAST(StringRef ModuleName,
                                                  SourceLocation ImportLoc,
-                                                 SourceRange ModuleNameRange,
+                                                 SourceLocation ModuleNameLoc,
                                                  bool IsInclusionDirective);
 
   /// Creates a \c CompilerInstance for compiling a module.
diff --git a/clang/include/clang/Lex/CodeCompletionHandler.h b/clang/include/clang/Lex/CodeCompletionHandler.h
index 2ef29743415ae..bd3e05a36bb33 100644
--- a/clang/include/clang/Lex/CodeCompletionHandler.h
+++ b/clang/include/clang/Lex/CodeCompletionHandler.h
@@ -13,15 +13,12 @@
 #ifndef LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
 #define LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
 
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/StringRef.h"
 
 namespace clang {
 
 class IdentifierInfo;
 class MacroInfo;
-using ModuleIdPath = ArrayRef<IdentifierLoc>;
 
 /// Callback handler that receives notifications when performing code
 /// completion within the preprocessor.
@@ -73,11 +70,6 @@ class CodeCompletionHandler {
   /// file where we expect natural language, e.g., a comment, string, or
   /// \#error directive.
   virtual void CodeCompleteNaturalLanguage() { }
-
-  /// Callback invoked when performing code completion inside the module name
-  /// part of an import directive.
-  virtual void CodeCompleteModuleImport(SourceLocation ImportLoc,
-                                        ModuleIdPath Path) {}
 };
 
 }
diff --git a/clang/include/clang/Lex/DependencyDirectivesScanner.h b/clang/include/clang/Lex/DependencyDirectivesScanner.h
index b21da166a96e5..f9fec3998ca53 100644
--- a/clang/include/clang/Lex/DependencyDirectivesScanner.h
+++ b/clang/include/clang/Lex/DependencyDirectivesScanner.h
@@ -135,22 +135,6 @@ void printDependencyDirectivesAsSource(
     ArrayRef<dependency_directives_scan::Directive> Directives,
     llvm::raw_ostream &OS);
 
-/// Scan an input source buffer for C++20 named module usage.
-///
-/// \param Source The input source buffer.
-///
-/// \returns true if any C++20 named modules related directive was found.
-bool scanInputForCXX20ModulesUsage(StringRef Source);
-
-/// Scan an input source buffer, and check whether the input source is a
-/// preprocessed output.
-///
-/// \param Source The input source buffer.
-///
-/// \returns true if any '__preprocessed_module' or '__preprocessed_import'
-/// directive was found.
-bool isPreprocessedModuleFile(StringRef Source);
-
 /// Functor that returns the dependency directives for a given file.
 class DependencyDirectivesGetter {
 public:
diff --git a/clang/include/clang/Lex/ModuleLoader.h b/clang/include/clang/Lex/ModuleLoader.h
index 042a5ab1f4a57..a58407200c41c 100644
--- a/clang/include/clang/Lex/ModuleLoader.h
+++ b/clang/include/clang/Lex/ModuleLoader.h
@@ -159,7 +159,6 @@ class ModuleLoader {
   /// \returns Returns true if any modules with that symbol found.
   virtual bool lookupMissingImports(StringRef Name,
                                     SourceLocation TriggerLoc) = 0;
-  static std::string getFlatNameFromPath(ModuleIdPath Path);
 
   bool HadFatalFailure = false;
 };
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index c8356b1dd45e4..b1c648e647f41 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -48,7 +48,6 @@
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Registry.h"
-#include "llvm/Support/TrailingObjects.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -137,64 +136,6 @@ struct CXXStandardLibraryVersionInfo {
   std::uint64_t Version;
 };
 
-/// Record the previous 'export' keyword info.
-///
-/// Since P1857R3, the standard introduced several rules to determine whether
-/// the 'module', 'export module', 'import', 'export import' is a valid
-/// directive introducer. This class is used to record the previous 'export'
-/// keyword token, and then handle 'export module' and 'export import'.
-class ExportContextualKeywordInfo {
-  Token ExportTok;
-  bool AtPhysicalStartOfLine = false;
-
-public:
-  ExportContextualKeywordInfo() = default;
-  ExportContextualKeywordInfo(const Token &Tok, bool AtPhysicalStartOfLine)
-      : ExportTok(Tok), AtPhysicalStartOfLine(AtPhysicalStartOfLine) {}
-
-  bool isValid() const { return ExportTok.is(tok::kw_export); }
-  bool isAtPhysicalStartOfLine() const { return AtPhysicalStartOfLine; }
-  Token getExportTok() const { return ExportTok; }
-  void reset() {
-    ExportTok.startToken();
-    AtPhysicalStartOfLine = false;
-  }
-};
-
-class ModuleNameLoc final
-    : llvm::TrailingObjects<ModuleNameLoc, IdentifierLoc> {
-  friend TrailingObjects;
-  unsigned NumIdentifierLocs;
-  unsigned numTrailingObjects(OverloadToken<IdentifierLoc>) const {
-    return getNumIdentifierLocs();
-  }
-
-  ModuleNameLoc(ModuleIdPath Path) : NumIdentifierLocs(Path.size()) {
-    (void)llvm::copy(Path, getTrailingObjectsNonStrict<IdentifierLoc>());
-  }
-
-public:
-  static ModuleNameLoc *Create(Preprocessor &PP, ModuleIdPath Path);
-  unsigned getNumIdentifierLocs() const { return NumIdentifierLocs; }
-  ModuleIdPath getModuleIdPath() const {
-    return {getTrailingObjectsNonStrict<IdentifierLoc>(),
-            getNumIdentifierLocs()};
-  }
-
-  SourceLocation getBeginLoc() const {
-    return getModuleIdPath().front().getLoc();
-  }
-  SourceLocation getEndLoc() const {
-    auto &Last = getModuleIdPath().back();
-    return Last.getLoc().getLocWithOffset(
-        Last.getIdentifierInfo()->getLength());
-  }
-  SourceRange getRange() const { return {getBeginLoc(), getEndLoc()}; }
-  std::string str() const {
-    return ModuleLoader::getFlatNameFromPath(getModuleIdPath());
-  }
-};
-
 /// Engages in a tight little dance with the lexer to efficiently
 /// preprocess tokens.
 ///
@@ -398,9 +339,8 @@ class Preprocessor {
   /// lexed, if any.
   SourceLocation ModuleImportLoc;
 
-  /// The source location of the \c module contextual keyword we just
-  /// lexed, if any.
-  SourceLocation ModuleDeclLoc;
+  /// The import path for named module that we're currently processing.
+  SmallVector<IdentifierLoc, 2> NamedModuleImportPath;
 
   llvm::DenseMap<FileID, SmallVector<const char *>> CheckPoints;
   unsigned CheckPointCounter = 0;
@@ -411,12 +351,6 @@ class Preprocessor {
   /// Whether the last token we lexed was an '@'.
   bool LastTokenWasAt = false;
 
-  /// Whether we're importing a standard C++20 named Modules.
-  bool ImportingCXXNamedModules = false;
-
-  /// Whether the last token we lexed was an 'export' keyword.
-  ExportContextualKeywordInfo LastTokenWasExportKeyword;
-
   /// First pp-token source location in current translation unit.
   SourceLocation FirstPPTokenLoc;
 
@@ -628,9 +562,9 @@ class Preprocessor {
         reset();
     }
 
-    void handleModuleName(ModuleNameLoc *NameLoc) {
-      if (isModuleCandidate() && NameLoc)
-        Name += NameLoc->str();
+    void handleIdentifier(IdentifierInfo *Identifier) {
+      if (isModuleCandidate() && Identifier)
+        Name += Identifier->getName().str();
       else if (!isNamedModule())
         reset();
     }
@@ -642,6 +576,13 @@ class Preprocessor {
         reset();
     }
 
+    void handlePeriod() {
+      if (isModuleCandidate())
+        Name += ".";
+      else if (!isNamedModule())
+        reset();
+    }
+
     void handleSemi() {
       if (!Name.empty() && isModuleCandidate()) {
         if (State == InterfaceCandidate)
@@ -698,6 +639,10 @@ class Preprocessor {
 
   ModuleDeclSeq ModuleDeclState;
 
+  /// Whether the module import expects an identifier next. Otherwise,
+  /// it expects a '.' or ';'.
+  bool ModuleImportExpectsIdentifier = false;
+
   /// The identifier and source location of the currently-active
   /// \#pragma clang arc_cf_code_audited begin.
   IdentifierLoc PragmaARCCFCodeAuditedInfo;
@@ -1180,9 +1125,6 @@ class Preprocessor {
   /// Whether tokens are being skipped until the through header is seen.
   bool SkippingUntilPCHThroughHeader = false;
 
-  /// Whether the main file is preprocessed module file.
-  bool MainFileIsPreprocessedModuleFile = false;
-
   /// \{
   /// Cache of macro expanders to reduce malloc traffic.
   enum { TokenLexerCacheSize = 8 };
@@ -1836,36 +1778,6 @@ class Preprocessor {
   std::optional<LexEmbedParametersResult> LexEmbedParameters(Token &Current,
                                                              bool ForHasEmbed);
 
-  /// Whether the main file is preprocessed module file.
-  bool isPreprocessedModuleFile() const {
-    return MainFileIsPreprocessedModuleFile;
-  }
-
-  /// Mark the main file as a preprocessed module file, then the 'module' and
-  /// 'import' directive recognition will be suppressed. Only
-  /// '__preprocessed_moduke' and '__preprocessed_import' are allowed.
-  void markMainFileAsPreprocessedModuleFile() {
-    MainFileIsPreprocessedModuleFile = true;
-  }
-
-  bool LexModuleNameContinue(Token &Tok, SourceLocation UseLoc,
-                             SmallVectorImpl<Token> &Suffix,
-                             SmallVectorImpl<IdentifierLoc> &Path,
-                             bool AllowMacroExpansion = true,
-                             bool IsPartition = false);
-  void EnterModuleSuffixTokenStream(ArrayRef<Token> Toks);
-  void HandleCXXImportDirective(Token Import);
-  void HandleCXXModuleDirective(Token Module);
-
-  /// Callback invoked when the lexer sees one of export, import or module token
-  /// at the start of a line.
-  ///
-  /// This consumes the...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Dec 25, 2025

@llvm/pr-subscribers-clang-modules

Author: None (yronglin)

Changes

This reverts commit 0d1c396.


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

44 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (-1)
  • (modified) clang/docs/StandardCPlusPlusModules.rst (+27)
  • (modified) clang/include/clang/Basic/DiagnosticLexKinds.td (+2-17)
  • (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+4-6)
  • (modified) clang/include/clang/Basic/IdentifierTable.h (+10-28)
  • (modified) clang/include/clang/Basic/TokenKinds.def (-8)
  • (modified) clang/include/clang/Basic/TokenKinds.h (-4)
  • (modified) clang/include/clang/Frontend/CompilerInstance.h (+1-1)
  • (modified) clang/include/clang/Lex/CodeCompletionHandler.h (-8)
  • (modified) clang/include/clang/Lex/DependencyDirectivesScanner.h (-16)
  • (modified) clang/include/clang/Lex/ModuleLoader.h (-1)
  • (modified) clang/include/clang/Lex/Preprocessor.h (+61-135)
  • (modified) clang/include/clang/Lex/Token.h (-4)
  • (modified) clang/include/clang/Lex/TokenLexer.h (-12)
  • (modified) clang/include/clang/Parse/Parser.h (+4-5)
  • (modified) clang/lib/Basic/IdentifierTable.cpp (+2-14)
  • (modified) clang/lib/Basic/TokenKinds.cpp (-12)
  • (modified) clang/lib/DependencyScanning/ModuleDepCollector.cpp (+1-2)
  • (modified) clang/lib/Frontend/CompilerInstance.cpp (+4-8)
  • (modified) clang/lib/Frontend/InitPreprocessor.cpp (-7)
  • (modified) clang/lib/Frontend/PrintPreprocessedOutput.cpp (+1-32)
  • (modified) clang/lib/Lex/DependencyDirectivesScanner.cpp (+15-149)
  • (modified) clang/lib/Lex/Lexer.cpp (+10-46)
  • (modified) clang/lib/Lex/PPDirectives.cpp (+31-441)
  • (modified) clang/lib/Lex/Preprocessor.cpp (+209-277)
  • (modified) clang/lib/Lex/TokenConcatenation.cpp (+3-5)
  • (modified) clang/lib/Lex/TokenLexer.cpp (+1-29)
  • (modified) clang/lib/Parse/Parser.cpp (+77-47)
  • (modified) clang/lib/Sema/SemaModule.cpp (+24-7)
  • (modified) clang/test/CXX/basic/basic.link/p3.cpp (+8-7)
  • (modified) clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp (+1-1)
  • (removed) clang/test/CXX/drs/cwg2947.cpp (-81)
  • (modified) clang/test/CXX/lex/lex.pptoken/p3-2a.cpp (+14-19)
  • (modified) clang/test/CXX/module/basic/basic.link/module-declaration.cpp (+2-2)
  • (removed) clang/test/CXX/module/cpp.pre/p1.cpp (-207)
  • (modified) clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm (+4-4)
  • (removed) clang/test/Lexer/cxx20-module-directive.cpp (-11)
  • (modified) clang/test/Modules/pr121066.cpp (+1-3)
  • (modified) clang/test/Modules/preprocess-named-modules.cppm (+1-1)
  • (modified) clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp (+1-2)
  • (modified) clang/unittests/Lex/DependencyDirectivesScannerTest.cpp (+5-43)
  • (modified) clang/unittests/Lex/ModuleDeclStateTest.cpp (+1-1)
  • (modified) clang/www/cxx_dr_status.html (+1-1)
  • (modified) clang/www/cxx_status.html (+9-2)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7bf003f700448..2319ff13f7864 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -209,7 +209,6 @@ C++20 Feature Support
 - Clang now normalizes constraints before checking whether they are satisfied, as mandated by the standard.
   As a result, Clang no longer incorrectly diagnoses substitution failures in template arguments only
   used in concept-ids, and produces better diagnostics for satisfaction failure. (#GH61811) (#GH135190)
-- Clang now supports `P1857R3 <https://wg21.link/p1857r3>`_ Modules Dependency Discovery. (#GH54047)
 
 C++17 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/docs/StandardCPlusPlusModules.rst b/clang/docs/StandardCPlusPlusModules.rst
index f6ab17ede46fa..71988d0fced98 100644
--- a/clang/docs/StandardCPlusPlusModules.rst
+++ b/clang/docs/StandardCPlusPlusModules.rst
@@ -1384,6 +1384,33 @@ declarations which use it. Thus, the preferred name will not be displayed in
 the debugger as expected. This is tracked by
 `#56490 <https://github.com/llvm/llvm-project/issues/56490>`_.
 
+Don't emit macros about module declaration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is covered by `P1857R3 <https://wg21.link/P1857R3>`_. It is mentioned here
+because we want users to be aware that we don't yet implement it.
+
+A direct approach to write code that can be compiled by both modules and
+non-module builds may look like:
+
+.. code-block:: c++
+
+  MODULE
+  IMPORT header_name
+  EXPORT_MODULE MODULE_NAME;
+  IMPORT header_name
+  EXPORT ...
+
+The intent of this is that this file can be compiled like a module unit or a
+non-module unit depending on the definition of some macros. However, this usage
+is forbidden by P1857R3 which is not yet implemented in Clang. This means that
+is possible to write invalid modules which will no longer be accepted once
+P1857R3 is implemented. This is tracked by
+`#54047 <https://github.com/llvm/llvm-project/issues/54047>`_.
+
+Until then, it is recommended not to mix macros with module declarations.
+
+
 Inconsistent filename suffix requirement for importable module units
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 77feea9f869e9..a72d3f37b1b72 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -503,8 +503,8 @@ def warn_cxx98_compat_variadic_macro : Warning<
   InGroup<CXX98CompatPedantic>, DefaultIgnore;
 def ext_named_variadic_macro : Extension<
   "named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
-def err_embedded_directive : Error<"embedding a %select{#|C++ }0%1 directive "
-                                   "within macro arguments is not supported">;
+def err_embedded_directive : Error<
+  "embedding a #%0 directive within macro arguments is not supported">;
 def ext_embedded_directive : Extension<
   "embedding a directive within macro arguments has undefined behavior">,
   InGroup<DiagGroup<"embedded-directive">>;
@@ -998,21 +998,6 @@ def warn_module_conflict : Warning<
   InGroup<ModuleConflict>;
 
 // C++20 modules
-def err_pp_module_name_is_macro : Error<
-  "%select{module|partition}0 name component %1 cannot be a object-like macro">;
-def err_pp_module_expected_ident : Error<
-  "expected %select{identifier after '.' in |}0module name">;
-def err_pp_unexpected_tok_after_module_name : Error<
-  "unexpected preprocessing token '%0' after module name, "
-  "only ';' and '[' (start of attribute specifier sequence) are allowed">;
-def warn_pp_extra_tokens_at_module_directive_eol
-    : Warning<"extra tokens after semicolon in '%0' directive">,
-      InGroup<ExtraTokens>;
-def err_pp_module_decl_in_header
-    : Error<"module declaration must not come from an #include directive">;
-def err_pp_cond_span_module_decl
-    : Error<"module directive lines are not allowed on lines controlled "
-    "by preprocessor conditionals">;
 def err_header_import_semi_in_macro : Error<
   "semicolon terminating header import declaration cannot be produced "
   "by a macro">;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 83d4ce3ca278c..662fe16d965b6 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1792,8 +1792,10 @@ def ext_bit_int : Extension<
 } // end of Parse Issue category.
 
 let CategoryName = "Modules Issue" in {
-def err_unexpected_module_or_import_decl : Error<
-  "%select{module|import}0 declaration can only appear at the top level">;
+def err_unexpected_module_decl : Error<
+  "module declaration can only appear at the top level">;
+def err_module_expected_ident : Error<
+  "expected a module name after '%select{module|import}0'">;
 def err_attribute_not_module_attr : Error<
   "%0 attribute cannot be applied to a module">;
 def err_keyword_not_module_attr : Error<
@@ -1804,10 +1806,6 @@ def err_keyword_not_import_attr : Error<
   "%0 cannot be applied to a module import">;
 def err_module_expected_semi : Error<
   "expected ';' after module name">;
-def err_expected_semi_after_module_or_import
-  : Error<"%0 directive must end with a ';'">;
-def note_module_declared_here : Note<
-  "%select{module|import}0 directive defined here">;
 def err_global_module_introducer_not_at_start : Error<
   "'module;' introducing a global module fragment can appear only "
   "at the start of the translation unit">;
diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h
index 1131727ed23ee..043c184323876 100644
--- a/clang/include/clang/Basic/IdentifierTable.h
+++ b/clang/include/clang/Basic/IdentifierTable.h
@@ -231,10 +231,6 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
   LLVM_PREFERRED_TYPE(bool)
   unsigned IsModulesImport : 1;
 
-  // True if this is the 'module' contextual keyword.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsModulesDecl : 1;
-
   // True if this is a mangled OpenMP variant name.
   LLVM_PREFERRED_TYPE(bool)
   unsigned IsMangledOpenMPVariantName : 1;
@@ -271,9 +267,8 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
         IsCPPOperatorKeyword(false), NeedsHandleIdentifier(false),
         IsFromAST(false), ChangedAfterLoad(false), FEChangedAfterLoad(false),
         RevertedTokenID(false), OutOfDate(false), IsModulesImport(false),
-        IsModulesDecl(false), IsMangledOpenMPVariantName(false),
-        IsDeprecatedMacro(false), IsRestrictExpansion(false), IsFinal(false),
-        IsKeywordInCpp(false) {}
+        IsMangledOpenMPVariantName(false), IsDeprecatedMacro(false),
+        IsRestrictExpansion(false), IsFinal(false), IsKeywordInCpp(false) {}
 
 public:
   IdentifierInfo(const IdentifierInfo &) = delete;
@@ -574,24 +569,12 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
   }
 
   /// Determine whether this is the contextual keyword \c import.
-  bool isImportKeyword() const { return IsModulesImport; }
+  bool isModulesImport() const { return IsModulesImport; }
 
   /// Set whether this identifier is the contextual keyword \c import.
-  void setKeywordImport(bool Val) {
-    IsModulesImport = Val;
-    if (Val)
-      NeedsHandleIdentifier = true;
-    else
-      RecomputeNeedsHandleIdentifier();
-  }
-
-  /// Determine whether this is the contextual keyword \c module.
-  bool isModuleKeyword() const { return IsModulesDecl; }
-
-  /// Set whether this identifier is the contextual keyword \c module.
-  void setModuleKeyword(bool Val) {
-    IsModulesDecl = Val;
-    if (Val)
+  void setModulesImport(bool I) {
+    IsModulesImport = I;
+    if (I)
       NeedsHandleIdentifier = true;
     else
       RecomputeNeedsHandleIdentifier();
@@ -646,7 +629,7 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
   void RecomputeNeedsHandleIdentifier() {
     NeedsHandleIdentifier = isPoisoned() || hasMacroDefinition() ||
                             isExtensionToken() || isFutureCompatKeyword() ||
-                            isOutOfDate() || isImportKeyword();
+                            isOutOfDate() || isModulesImport();
   }
 };
 
@@ -814,11 +797,10 @@ class IdentifierTable {
     // contents.
     II->Entry = &Entry;
 
-    // If this is the 'import' or 'module' contextual keyword, mark it as such.
+    // If this is the 'import' contextual keyword, mark it as such.
     if (Name == "import")
-      II->setKeywordImport(true);
-    else if (Name == "module")
-      II->setModuleKeyword(true);
+      II->setModulesImport(true);
+
     return *II;
   }
 
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index a3d286fdb81a7..3d955095b07a8 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -133,11 +133,6 @@ PPKEYWORD(pragma)
 // C23 & C++26 #embed
 PPKEYWORD(embed)
 
-// C++20 Module Directive
-PPKEYWORD(module)
-PPKEYWORD(__preprocessed_module)
-PPKEYWORD(__preprocessed_import)
-
 // GNU Extensions.
 PPKEYWORD(import)
 PPKEYWORD(include_next)
@@ -1035,9 +1030,6 @@ ANNOTATION(module_include)
 ANNOTATION(module_begin)
 ANNOTATION(module_end)
 
-// Annotations for C++, Clang and Objective-C named modules.
-ANNOTATION(module_name)
-
 // Annotation for a header_name token that has been looked up and transformed
 // into the name of a header unit.
 ANNOTATION(header_unit)
diff --git a/clang/include/clang/Basic/TokenKinds.h b/clang/include/clang/Basic/TokenKinds.h
index c0316257d9d97..a801113c57715 100644
--- a/clang/include/clang/Basic/TokenKinds.h
+++ b/clang/include/clang/Basic/TokenKinds.h
@@ -76,10 +76,6 @@ const char *getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE;
 /// tokens like 'int' and 'dynamic_cast'. Returns NULL for other token kinds.
 const char *getKeywordSpelling(TokenKind Kind) LLVM_READNONE;
 
-/// Determines the spelling of simple Objective-C keyword tokens like '@import'.
-/// Returns NULL for other token kinds.
-const char *getObjCKeywordSpelling(ObjCKeywordKind Kind) LLVM_READNONE;
-
 /// Returns the spelling of preprocessor keywords, such as "else".
 const char *getPPKeywordSpelling(PPKeywordKind Kind) LLVM_READNONE;
 
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 6db1be7f0ed58..ded5f55d180aa 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -905,7 +905,7 @@ class CompilerInstance : public ModuleLoader {
   /// load it.
   ModuleLoadResult findOrCompileModuleAndReadAST(StringRef ModuleName,
                                                  SourceLocation ImportLoc,
-                                                 SourceRange ModuleNameRange,
+                                                 SourceLocation ModuleNameLoc,
                                                  bool IsInclusionDirective);
 
   /// Creates a \c CompilerInstance for compiling a module.
diff --git a/clang/include/clang/Lex/CodeCompletionHandler.h b/clang/include/clang/Lex/CodeCompletionHandler.h
index 2ef29743415ae..bd3e05a36bb33 100644
--- a/clang/include/clang/Lex/CodeCompletionHandler.h
+++ b/clang/include/clang/Lex/CodeCompletionHandler.h
@@ -13,15 +13,12 @@
 #ifndef LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
 #define LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
 
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/StringRef.h"
 
 namespace clang {
 
 class IdentifierInfo;
 class MacroInfo;
-using ModuleIdPath = ArrayRef<IdentifierLoc>;
 
 /// Callback handler that receives notifications when performing code
 /// completion within the preprocessor.
@@ -73,11 +70,6 @@ class CodeCompletionHandler {
   /// file where we expect natural language, e.g., a comment, string, or
   /// \#error directive.
   virtual void CodeCompleteNaturalLanguage() { }
-
-  /// Callback invoked when performing code completion inside the module name
-  /// part of an import directive.
-  virtual void CodeCompleteModuleImport(SourceLocation ImportLoc,
-                                        ModuleIdPath Path) {}
 };
 
 }
diff --git a/clang/include/clang/Lex/DependencyDirectivesScanner.h b/clang/include/clang/Lex/DependencyDirectivesScanner.h
index b21da166a96e5..f9fec3998ca53 100644
--- a/clang/include/clang/Lex/DependencyDirectivesScanner.h
+++ b/clang/include/clang/Lex/DependencyDirectivesScanner.h
@@ -135,22 +135,6 @@ void printDependencyDirectivesAsSource(
     ArrayRef<dependency_directives_scan::Directive> Directives,
     llvm::raw_ostream &OS);
 
-/// Scan an input source buffer for C++20 named module usage.
-///
-/// \param Source The input source buffer.
-///
-/// \returns true if any C++20 named modules related directive was found.
-bool scanInputForCXX20ModulesUsage(StringRef Source);
-
-/// Scan an input source buffer, and check whether the input source is a
-/// preprocessed output.
-///
-/// \param Source The input source buffer.
-///
-/// \returns true if any '__preprocessed_module' or '__preprocessed_import'
-/// directive was found.
-bool isPreprocessedModuleFile(StringRef Source);
-
 /// Functor that returns the dependency directives for a given file.
 class DependencyDirectivesGetter {
 public:
diff --git a/clang/include/clang/Lex/ModuleLoader.h b/clang/include/clang/Lex/ModuleLoader.h
index 042a5ab1f4a57..a58407200c41c 100644
--- a/clang/include/clang/Lex/ModuleLoader.h
+++ b/clang/include/clang/Lex/ModuleLoader.h
@@ -159,7 +159,6 @@ class ModuleLoader {
   /// \returns Returns true if any modules with that symbol found.
   virtual bool lookupMissingImports(StringRef Name,
                                     SourceLocation TriggerLoc) = 0;
-  static std::string getFlatNameFromPath(ModuleIdPath Path);
 
   bool HadFatalFailure = false;
 };
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index c8356b1dd45e4..b1c648e647f41 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -48,7 +48,6 @@
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Registry.h"
-#include "llvm/Support/TrailingObjects.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -137,64 +136,6 @@ struct CXXStandardLibraryVersionInfo {
   std::uint64_t Version;
 };
 
-/// Record the previous 'export' keyword info.
-///
-/// Since P1857R3, the standard introduced several rules to determine whether
-/// the 'module', 'export module', 'import', 'export import' is a valid
-/// directive introducer. This class is used to record the previous 'export'
-/// keyword token, and then handle 'export module' and 'export import'.
-class ExportContextualKeywordInfo {
-  Token ExportTok;
-  bool AtPhysicalStartOfLine = false;
-
-public:
-  ExportContextualKeywordInfo() = default;
-  ExportContextualKeywordInfo(const Token &Tok, bool AtPhysicalStartOfLine)
-      : ExportTok(Tok), AtPhysicalStartOfLine(AtPhysicalStartOfLine) {}
-
-  bool isValid() const { return ExportTok.is(tok::kw_export); }
-  bool isAtPhysicalStartOfLine() const { return AtPhysicalStartOfLine; }
-  Token getExportTok() const { return ExportTok; }
-  void reset() {
-    ExportTok.startToken();
-    AtPhysicalStartOfLine = false;
-  }
-};
-
-class ModuleNameLoc final
-    : llvm::TrailingObjects<ModuleNameLoc, IdentifierLoc> {
-  friend TrailingObjects;
-  unsigned NumIdentifierLocs;
-  unsigned numTrailingObjects(OverloadToken<IdentifierLoc>) const {
-    return getNumIdentifierLocs();
-  }
-
-  ModuleNameLoc(ModuleIdPath Path) : NumIdentifierLocs(Path.size()) {
-    (void)llvm::copy(Path, getTrailingObjectsNonStrict<IdentifierLoc>());
-  }
-
-public:
-  static ModuleNameLoc *Create(Preprocessor &PP, ModuleIdPath Path);
-  unsigned getNumIdentifierLocs() const { return NumIdentifierLocs; }
-  ModuleIdPath getModuleIdPath() const {
-    return {getTrailingObjectsNonStrict<IdentifierLoc>(),
-            getNumIdentifierLocs()};
-  }
-
-  SourceLocation getBeginLoc() const {
-    return getModuleIdPath().front().getLoc();
-  }
-  SourceLocation getEndLoc() const {
-    auto &Last = getModuleIdPath().back();
-    return Last.getLoc().getLocWithOffset(
-        Last.getIdentifierInfo()->getLength());
-  }
-  SourceRange getRange() const { return {getBeginLoc(), getEndLoc()}; }
-  std::string str() const {
-    return ModuleLoader::getFlatNameFromPath(getModuleIdPath());
-  }
-};
-
 /// Engages in a tight little dance with the lexer to efficiently
 /// preprocess tokens.
 ///
@@ -398,9 +339,8 @@ class Preprocessor {
   /// lexed, if any.
   SourceLocation ModuleImportLoc;
 
-  /// The source location of the \c module contextual keyword we just
-  /// lexed, if any.
-  SourceLocation ModuleDeclLoc;
+  /// The import path for named module that we're currently processing.
+  SmallVector<IdentifierLoc, 2> NamedModuleImportPath;
 
   llvm::DenseMap<FileID, SmallVector<const char *>> CheckPoints;
   unsigned CheckPointCounter = 0;
@@ -411,12 +351,6 @@ class Preprocessor {
   /// Whether the last token we lexed was an '@'.
   bool LastTokenWasAt = false;
 
-  /// Whether we're importing a standard C++20 named Modules.
-  bool ImportingCXXNamedModules = false;
-
-  /// Whether the last token we lexed was an 'export' keyword.
-  ExportContextualKeywordInfo LastTokenWasExportKeyword;
-
   /// First pp-token source location in current translation unit.
   SourceLocation FirstPPTokenLoc;
 
@@ -628,9 +562,9 @@ class Preprocessor {
         reset();
     }
 
-    void handleModuleName(ModuleNameLoc *NameLoc) {
-      if (isModuleCandidate() && NameLoc)
-        Name += NameLoc->str();
+    void handleIdentifier(IdentifierInfo *Identifier) {
+      if (isModuleCandidate() && Identifier)
+        Name += Identifier->getName().str();
       else if (!isNamedModule())
         reset();
     }
@@ -642,6 +576,13 @@ class Preprocessor {
         reset();
     }
 
+    void handlePeriod() {
+      if (isModuleCandidate())
+        Name += ".";
+      else if (!isNamedModule())
+        reset();
+    }
+
     void handleSemi() {
       if (!Name.empty() && isModuleCandidate()) {
         if (State == InterfaceCandidate)
@@ -698,6 +639,10 @@ class Preprocessor {
 
   ModuleDeclSeq ModuleDeclState;
 
+  /// Whether the module import expects an identifier next. Otherwise,
+  /// it expects a '.' or ';'.
+  bool ModuleImportExpectsIdentifier = false;
+
   /// The identifier and source location of the currently-active
   /// \#pragma clang arc_cf_code_audited begin.
   IdentifierLoc PragmaARCCFCodeAuditedInfo;
@@ -1180,9 +1125,6 @@ class Preprocessor {
   /// Whether tokens are being skipped until the through header is seen.
   bool SkippingUntilPCHThroughHeader = false;
 
-  /// Whether the main file is preprocessed module file.
-  bool MainFileIsPreprocessedModuleFile = false;
-
   /// \{
   /// Cache of macro expanders to reduce malloc traffic.
   enum { TokenLexerCacheSize = 8 };
@@ -1836,36 +1778,6 @@ class Preprocessor {
   std::optional<LexEmbedParametersResult> LexEmbedParameters(Token &Current,
                                                              bool ForHasEmbed);
 
-  /// Whether the main file is preprocessed module file.
-  bool isPreprocessedModuleFile() const {
-    return MainFileIsPreprocessedModuleFile;
-  }
-
-  /// Mark the main file as a preprocessed module file, then the 'module' and
-  /// 'import' directive recognition will be suppressed. Only
-  /// '__preprocessed_moduke' and '__preprocessed_import' are allowed.
-  void markMainFileAsPreprocessedModuleFile() {
-    MainFileIsPreprocessedModuleFile = true;
-  }
-
-  bool LexModuleNameContinue(Token &Tok, SourceLocation UseLoc,
-                             SmallVectorImpl<Token> &Suffix,
-                             SmallVectorImpl<IdentifierLoc> &Path,
-                             bool AllowMacroExpansion = true,
-                             bool IsPartition = false);
-  void EnterModuleSuffixTokenStream(ArrayRef<Token> Toks);
-  void HandleCXXImportDirective(Token Import);
-  void HandleCXXModuleDirective(Token Module);
-
-  /// Callback invoked when the lexer sees one of export, import or module token
-  /// at the start of a line.
-  ///
-  /// This consumes the...
[truncated]

@yronglin yronglin merged commit 71bba12 into llvm:main Dec 25, 2025
11 of 15 checks passed
@github-actions
Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions cppm,h,cpp -- clang/include/clang/Basic/IdentifierTable.h clang/include/clang/Basic/TokenKinds.h clang/include/clang/Frontend/CompilerInstance.h clang/include/clang/Lex/CodeCompletionHandler.h clang/include/clang/Lex/DependencyDirectivesScanner.h clang/include/clang/Lex/ModuleLoader.h clang/include/clang/Lex/Preprocessor.h clang/include/clang/Lex/Token.h clang/include/clang/Lex/TokenLexer.h clang/include/clang/Parse/Parser.h clang/lib/Basic/IdentifierTable.cpp clang/lib/Basic/TokenKinds.cpp clang/lib/DependencyScanning/ModuleDepCollector.cpp clang/lib/Frontend/CompilerInstance.cpp clang/lib/Frontend/InitPreprocessor.cpp clang/lib/Frontend/PrintPreprocessedOutput.cpp clang/lib/Lex/DependencyDirectivesScanner.cpp clang/lib/Lex/Lexer.cpp clang/lib/Lex/PPDirectives.cpp clang/lib/Lex/Preprocessor.cpp clang/lib/Lex/TokenConcatenation.cpp clang/lib/Lex/TokenLexer.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/SemaModule.cpp clang/test/CXX/basic/basic.link/p3.cpp clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp clang/test/CXX/lex/lex.pptoken/p3-2a.cpp clang/test/CXX/module/basic/basic.link/module-declaration.cpp clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm clang/test/Modules/pr121066.cpp clang/test/Modules/preprocess-named-modules.cppm clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp clang/unittests/Lex/DependencyDirectivesScannerTest.cpp clang/unittests/Lex/ModuleDeclStateTest.cpp --diff_from_common_commit

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/clang/include/clang/Lex/CodeCompletionHandler.h b/clang/include/clang/Lex/CodeCompletionHandler.h
index bd3e05a36..bd4fa2bd5 100644
--- a/clang/include/clang/Lex/CodeCompletionHandler.h
+++ b/clang/include/clang/Lex/CodeCompletionHandler.h
@@ -69,7 +69,7 @@ public:
   /// Callback invoked when performing code completion in a part of the
   /// file where we expect natural language, e.g., a comment, string, or
   /// \#error directive.
-  virtual void CodeCompleteNaturalLanguage() { }
+  virtual void CodeCompleteNaturalLanguage() {}
 };
 
 }
diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp
index 9b4019834..43d193906 100644
--- a/clang/lib/Basic/IdentifierTable.cpp
+++ b/clang/lib/Basic/IdentifierTable.cpp
@@ -430,7 +430,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
   CASE( 6, 'a', 's', assert);
   CASE( 6, 'd', 'f', define);
   CASE( 6, 'i', 'n', ifndef);
-  CASE( 6, 'i', 'p', import);
+  CASE(6, 'i', 'p', import);
   CASE( 6, 'p', 'a', pragma);
 
   CASE( 7, 'd', 'f', defined);
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 0a25dc195..db3dce2f6 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -1130,11 +1130,15 @@ void Preprocessor::CollectPpImportSuffix(SmallVectorImpl<Token> &Toks) {
     Lex(Toks.back());
 
     switch (Toks.back().getKind()) {
-    case tok::l_paren: case tok::l_square: case tok::l_brace:
+    case tok::l_paren:
+    case tok::l_square:
+    case tok::l_brace:
       ++BracketDepth;
       break;
 
-    case tok::r_paren: case tok::r_square: case tok::r_brace:
+    case tok::r_paren:
+    case tok::r_square:
+    case tok::r_brace:
       if (BracketDepth == 0)
         return;
       --BracketDepth;
@@ -1143,7 +1147,7 @@ void Preprocessor::CollectPpImportSuffix(SmallVectorImpl<Token> &Toks) {
     case tok::semi:
       if (BracketDepth == 0)
         return;
-    break;
+      break;
 
     case tok::eof:
       return;
@@ -1154,7 +1158,6 @@ void Preprocessor::CollectPpImportSuffix(SmallVectorImpl<Token> &Toks) {
   }
 }
 
-
 /// Lex a token following the 'import' contextual keyword.
 ///
 ///     pp-import: [C++20]
@@ -1346,8 +1349,7 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) {
   // We don't/shouldn't load the standard c++20 modules when preprocessing.
   if (getLangOpts().Modules && !isInImportingCXXNamedModules()) {
     Imported = TheModuleLoader.loadModule(ModuleImportLoc,
-                                          NamedModuleImportPath,
-                                          Module::Hidden,
+                                          NamedModuleImportPath, Module::Hidden,
                                           /*IsInclusionDirective=*/false);
     if (Imported)
       makeModuleVisible(Imported, SemiLoc);
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index cbe37cd47..a8bfef390 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -305,7 +305,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
     // We were asked to compile a module interface unit but this is a module
     // implementation unit.
     Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)
-      << FixItHint::CreateInsertion(ModuleLoc, "export ");
+        << FixItHint::CreateInsertion(ModuleLoc, "export ");
     MDK = ModuleDeclKind::Interface;
     break;
 
@@ -388,7 +388,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
         << getLangOpts().CurrentModule;
     return nullptr;
   }
-  const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName;
+  const_cast<LangOptions &>(getLangOpts()).CurrentModule = ModuleName;
 
   auto &Map = PP.getHeaderSearchInfo().getModuleMap();
   Module *Mod;                 // The module we are creating.
@@ -433,7 +433,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
     Interface = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
                                              Module::AllVisible,
                                              /*IsInclusionDirective=*/false);
-    const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName;
+    const_cast<LangOptions &>(getLangOpts()).CurrentModule = ModuleName;
 
     if (!Interface) {
       Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;

mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Jan 6, 2026
…y Discovery" (llvm#173130)" (llvm#173549)

This reverts commit 0d1c396.

Co-authored-by: Yihan Wang <yihwang@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants