================
@@ -4095,3 +4185,323 @@ void Preprocessor::HandleEmbedDirective(SourceLocation 
HashLoc, Token &EmbedTok,
       StringRef(static_cast<char *>(Mem), OriginalFilename.size());
   HandleEmbedDirectiveImpl(HashLoc, *Params, BinaryContents, FilenameToGo);
 }
+
+/// HandleCXXImportDirective - Handle the C++ modules import directives
+///
+/// pp-import:
+///       export[opt] import header-name pp-tokens[opt] ; new-line
+///       export[opt] import header-name-tokens pp-tokens[opt] ; new-line
+///       export[opt] import pp-tokens ; new-line
+///
+/// The header importing are replaced by annot_header_unit token, and the
+/// lexed module name are replaced by annot_module_name token.
+void Preprocessor::HandleCXXImportDirective(Token ImportTok) {
+  assert(getLangOpts().CPlusPlusModules && ImportTok.is(tok::kw_import));
+  llvm::SaveAndRestore<bool> SaveImportingCXXModules(
+      this->ImportingCXXNamedModules, true);
+
+  if (LastTokenWasExportKeyword.isValid())
+    LastTokenWasExportKeyword.reset();
+
+  Token Tok;
+  if (LexHeaderName(Tok)) {
+    if (Tok.isNot(tok::eod))
+      CheckEndOfDirective(ImportTok.getIdentifierInfo()->getName());
+    return;
+  }
+
+  SourceLocation UseLoc = ImportTok.getLocation();
+  SmallVector<Token, 4> DirToks{ImportTok};
+  SmallVector<IdentifierLoc, 2> Path;
+  bool ImportingHeader = false;
+  bool IsPartition = false;
+  std::string FlatName;
+  switch (Tok.getKind()) {
+  case tok::header_name:
+    ImportingHeader = true;
+    DirToks.push_back(Tok);
+    Lex(DirToks.emplace_back());
+    break;
+  case tok::colon:
+    IsPartition = true;
+    DirToks.push_back(Tok);
+    UseLoc = Tok.getLocation();
+    Lex(Tok);
+    [[fallthrough]];
+  case tok::identifier: {
+    bool LeadingSpace = Tok.hasLeadingSpace();
+    unsigned NumToksInDirective = DirToks.size();
+    if (LexModuleNameContinue(Tok, UseLoc, DirToks, Path)) {
+      if (Tok.isNot(tok::eod))
+        CheckEndOfDirective(ImportTok.getIdentifierInfo()->getName(),
+                            /*EnableMacros=*/false, &DirToks);
+      EnterModuleSuffixTokenStream(DirToks);
+      return;
+    }
+
+    // Clean the module-name tokens and replace these tokens with
+    // annot_module_name.
+    DirToks.resize(NumToksInDirective);
+    ModuleNameLoc *NameLoc = ModuleNameLoc::Create(*this, Path);
+    DirToks.emplace_back();
+    DirToks.back().setKind(tok::annot_module_name);
+    DirToks.back().setAnnotationRange(NameLoc->getRange());
+    DirToks.back().setAnnotationValue(static_cast<void *>(NameLoc));
+    DirToks.back().setFlagValue(Token::LeadingSpace, LeadingSpace);
+    DirToks.push_back(Tok);
+
+    bool IsValid =
+        (IsPartition && ModuleDeclState.isNamedModule()) || !IsPartition;
+    if (Callbacks && IsValid) {
+      if (IsPartition && ModuleDeclState.isNamedModule()) {
+        FlatName += ModuleDeclState.getPrimaryName();
+        FlatName += ":";
+      }
+
+      FlatName += ModuleLoader::getFlatNameFromPath(Path);
+      SourceLocation StartLoc = IsPartition ? UseLoc : Path[0].getLoc();
+      IdentifierLoc FlatNameLoc(StartLoc, getIdentifierInfo(FlatName));
+
+      // We don't/shouldn't load the standard c++20 modules when preprocessing.
+      // so the imported module is nullptr.
+      Callbacks->moduleImport(ImportTok.getLocation(),
+                              ModuleIdPath(FlatNameLoc),
+                              /*Imported=*/nullptr);
+    }
+    break;
+  }
+  default:
+    DirToks.push_back(Tok);
+    break;
+  }
+
+  // Consume the pp-import-suffix and expand any macros in it now, if we're not
+  // at the semicolon already.
+  if (!DirToks.back().isOneOf(tok::semi, tok::eod))
+    CollectPPImportSuffix(DirToks);
+
+  if (DirToks.back().isNot(tok::eod))
+    CheckEndOfDirective(ImportTok.getIdentifierInfo()->getName());
+  else
+    DirToks.pop_back();
+
+  // This is not a pp-import after all.
+  if (DirToks.back().isNot(tok::semi)) {
+    EnterModuleSuffixTokenStream(DirToks);
+    return;
+  }
+
+  if (ImportingHeader) {
+    // C++2a [cpp.module]p1:
+    //   The ';' preprocessing-token terminating a pp-import shall not have
+    //   been produced by macro replacement.
+    SourceLocation SemiLoc = DirToks.back().getLocation();
+    if (SemiLoc.isMacroID())
+      Diag(SemiLoc, diag::err_header_import_semi_in_macro);
+
+    auto Action = HandleHeaderIncludeOrImport(
+        /*HashLoc*/ SourceLocation(), ImportTok, Tok, SemiLoc);
+    switch (Action.Kind) {
+    case ImportAction::None:
+      break;
+
+    case ImportAction::ModuleBegin:
+      // Let the parser know we're textually entering the module.
+      DirToks.emplace_back();
+      DirToks.back().startToken();
+      DirToks.back().setKind(tok::annot_module_begin);
+      DirToks.back().setLocation(SemiLoc);
+      DirToks.back().setAnnotationEndLoc(SemiLoc);
+      DirToks.back().setAnnotationValue(Action.ModuleForHeader);
+      [[fallthrough]];
+
+    case ImportAction::ModuleImport:
+    case ImportAction::HeaderUnitImport:
+    case ImportAction::SkippedModuleImport:
+      // We chose to import (or textually enter) the file. Convert the
+      // header-name token into a header unit annotation token.
+      DirToks[1].setKind(tok::annot_header_unit);
+      DirToks[1].setAnnotationEndLoc(DirToks[0].getLocation());
+      DirToks[1].setAnnotationValue(Action.ModuleForHeader);
+      // FIXME: Call the moduleImport callback?
+      break;
+    case ImportAction::Failure:
+      assert(TheModuleLoader.HadFatalFailure &&
+             "This should be an early exit only to a fatal error");
+      CurLexer->cutOffLexing();
+      return;
+    }
+  }
+
+  EnterModuleSuffixTokenStream(DirToks);
+}
+
+/// HandleCXXModuleDirective - Handle C++ module declaration directives.
+///
+/// pp-module:
+///       export[opt] module pp-tokens[opt] ; new-line
+///
+/// pp-module-name:
+///       pp-module-name-qualifier[opt] identifier
+/// pp-module-partition:
+///       : pp-module-name-qualifier[opt] identifier
+/// pp-module-name-qualifier:
+///       identifier .
+///       pp-module-name-qualifier identifier .
+///
+/// global-module-fragment:
+///       module-keyword ; declaration-seq[opt]
+///
+/// private-module-fragment:
+///       module-keyword : private ; declaration-seq[opt]
+///
+/// The lexed module name are replaced by annot_module_name token.
+void Preprocessor::HandleCXXModuleDirective(Token ModuleTok) {
+  assert(getLangOpts().CPlusPlusModules && ModuleTok.is(tok::kw_module));
+  Token Introducer = ModuleTok;
+  if (LastTokenWasExportKeyword.isValid()) {
+    Introducer = LastTokenWasExportKeyword.getExportTok();
+    LastTokenWasExportKeyword.reset();
+  }
+
+  SourceLocation StartLoc = Introducer.getLocation();
+
+  Token Tok;
+  SourceLocation UseLoc = ModuleTok.getLocation();
+  SmallVector<Token, 4> DirToks{ModuleTok};
+  SmallVector<IdentifierLoc, 2> Path, Partition;
+  LexUnexpandedToken(Tok);
+
+  switch (Tok.getKind()) {
+  // Global Module Fragment.
+  case tok::semi:
+    DirToks.push_back(Tok);
+    break;
+  case tok::colon:
+    DirToks.push_back(Tok);
+    LexUnexpandedToken(Tok);
+    if (Tok.isNot(tok::kw_private)) {
+      if (Tok.isNot(tok::eod))
+        CheckEndOfDirective(ModuleTok.getIdentifierInfo()->getName(),
+                            /*EnableMacros=*/false, &DirToks);
+      EnterModuleSuffixTokenStream(DirToks);
+      return;
+    }
+    DirToks.push_back(Tok);
+    break;
+  case tok::identifier: {
+    bool LeadingSpace = Tok.hasLeadingSpace();
+    unsigned NumToksInDirective = DirToks.size();
+
+    // C++ [cpp.module]p3: Any preprocessing tokens after the module
+    // preprocessing token in the module directive are processed just as in
+    // normal text.
+    //
+    // P3034R1 Module Declarations Shouldn’t be Macros.
+    if (LexModuleNameContinue(Tok, UseLoc, DirToks, Path,
+                              /*AllowMacroExpansion=*/false)) {
+      if (Tok.isNot(tok::eod))
+        CheckEndOfDirective(ModuleTok.getIdentifierInfo()->getName(),
+                            /*EnableMacros=*/false, &DirToks);
+      EnterModuleSuffixTokenStream(DirToks);
+      return;
+    }
+
+    ModuleNameLoc *NameLoc = ModuleNameLoc::Create(*this, Path);
+    DirToks.resize(NumToksInDirective);
+    DirToks.emplace_back();
+    DirToks.back().setKind(tok::annot_module_name);
+    DirToks.back().setAnnotationRange(NameLoc->getRange());
+    DirToks.back().setAnnotationValue(static_cast<void *>(NameLoc));
+    DirToks.back().setFlagValue(Token::LeadingSpace, LeadingSpace);
+    DirToks.push_back(Tok);
+
+    // C++20 [cpp.module]p
+    //   The pp-tokens, if any, of a pp-module shall be of the form:
+    //     pp-module-name pp-module-partition[opt] pp-tokens[opt]
+    if (Tok.is(tok::colon)) {
+      NumToksInDirective = DirToks.size();
+      LexUnexpandedToken(Tok);
+      LeadingSpace = Tok.hasLeadingSpace();
+      if (LexModuleNameContinue(Tok, UseLoc, DirToks, Partition,
+                                /*AllowMacroExpansion=*/false,
+                                /*IsPartition=*/true)) {
+        if (Tok.isNot(tok::eod))
+          CheckEndOfDirective(ModuleTok.getIdentifierInfo()->getName(),
+                              /*EnableMacros=*/false, &DirToks);
+        EnterModuleSuffixTokenStream(DirToks);
+        return;
+      }
+
+      ModuleNameLoc *PartitionLoc = ModuleNameLoc::Create(*this, Partition);
+      DirToks.resize(NumToksInDirective);
+      DirToks.emplace_back();
+      DirToks.back().setKind(tok::annot_module_name);
+      DirToks.back().setAnnotationRange(NameLoc->getRange());
+      DirToks.back().setAnnotationValue(static_cast<void *>(PartitionLoc));
+      DirToks.back().setFlagValue(Token::LeadingSpace, LeadingSpace);
+      DirToks.push_back(Tok);
+    }
+
+    // If the current token is a macro definition, put it back to token stream
+    // and expand any macros in it later.
+    //
+    // export module M ATTR(some_attr);  // -D'ATTR(x)=[[x]]'
+    //
+    // Current token is `ATTR`.
+    if (Tok.is(tok::identifier) &&
+        getMacroDefinition(Tok.getIdentifierInfo())) {
+      std::unique_ptr<Token[]> TokCopy = std::make_unique<Token[]>(1);
+      TokCopy[0] = Tok;
+      EnterTokenStream(std::move(TokCopy), /*NumToks=*/1,
+                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
+      Lex(Tok);
+      DirToks.back() = Tok;
+    }
+    break;
+  }
+  default:
+    DirToks.push_back(Tok);
+    break;
+  }
+
+  // Consume the pp-import-suffix and expand any macros in it now, if we're not
+  // at the semicolon already.
+  SourceLocation End = DirToks.back().getLocation();
+  std::optional<Token> NextPPTok = DirToks.back();
+  if (DirToks.back().is(tok::eod)) {
+    NextPPTok = peekNextPPToken();
+    if (NextPPTok && NextPPTok->is(tok::raw_identifier))
+      LookUpIdentifierInfo(*NextPPTok);
+  }
+
+  // Only ';' and '[' are allowed after module name.
+  // We also check 'private' because the previous is not a module name.
+  if (!NextPPTok->isOneOf(tok::semi, tok::eod, tok::l_square, tok::kw_private))
+    Diag(*NextPPTok, diag::err_pp_unexpected_tok_after_module_name)
+        << getSpelling(*NextPPTok);
+
+  if (!DirToks.back().isOneOf(tok::semi, tok::eod)) {
+    // Consume the pp-import-suffix and expand any macros in it now. We'll add
+    // it back into the token stream later.
+    CollectPPImportSuffix(DirToks);
+    End = DirToks.back().getLocation();
----------------
shafik wrote:

This is effectively dead code, following this block the next if/else statement 
sets `End` in both branches.

As far as I can tell the first assignment to `End` is also dead.

We should move the declaration of `End` down below here and set it using an 
IIFE to avoid having to declare it and then set it.


https://github.com/llvm/llvm-project/pull/173789
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to