================
@@ -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