================ @@ -1121,6 +1153,149 @@ void Preprocessor::CollectPpImportSuffix(SmallVectorImpl<Token> &Toks) { } } +std::string ModuleNameInfo::getFlatName() const { + std::string FlatModuleName; + for (auto &Tok : getTokens()) { + switch (Tok.getKind()) { + case tok::identifier: + FlatModuleName += Tok.getIdentifierInfo()->getName(); + break; + case tok::period: + FlatModuleName += '.'; + break; + case tok::colon: + FlatModuleName += ':'; + break; + default: + llvm_unreachable("Unexpected token in module name"); + } + } + return FlatModuleName; +} + +void ModuleNameInfo::getModuleIdPath( + SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> &Path) const { + return getModuleIdPath(getTokens(), Path); +} + +void ModuleNameInfo::getModuleIdPath( + ArrayRef<Token> ModuleName, + SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> &Path) { + for (const auto &Tok : ModuleName) { + if (Tok.is(tok::identifier)) + Path.push_back( + std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation())); + } +} + +/// Lex a module name or a partition name. +/// +/// module-name: +/// module-name-qualifier[opt] identifier +/// +/// partition-name: [C++20] +/// : module-name-qualifier[opt] identifier +/// +/// module-name-qualifier +/// module-name-qualifier[opt] identifier . +bool Preprocessor::LexModuleName(Token &Result, bool IsImport) { + bool ExpectsIdentifier = true, IsLexingPartition = false; + SmallVector<Token, 8> ModuleName; + std::optional<unsigned> ColonTokIndex; + auto LexNextToken = [&](Token &Tok) { + if (IsImport) + Lex(Tok); + else + LexUnexpandedToken(Tok); + }; + + while (true) { + LexNextToken(Result); + if (ExpectsIdentifier && Result.is(tok::identifier)) { + auto *MI = getMacroInfo(Result.getIdentifierInfo()); + if (getLangOpts().CPlusPlusModules && !IsImport && MI && + MI->isObjectLike()) { + Diag(Result, diag::err_module_decl_cannot_be_macros) + << Result.getLocation() << IsLexingPartition + << Result.getIdentifierInfo(); + } + ModuleName.push_back(Result); + ExpectsIdentifier = false; + continue; + } + + if (!ExpectsIdentifier && Result.is(tok::period)) { + ModuleName.push_back(Result); + ExpectsIdentifier = true; + continue; + } + + // Module partition only allowed in C++20 Modules. + if (getLangOpts().CPlusPlusModules && Result.is(tok::colon)) { + // Handle the form like: import :P; + // If the token after ':' is not an identifier, this is a invalid module + // name. + if (ModuleName.empty()) { + Token Tmp; + LexNextToken(Tmp); + EnterToken(Tmp, /*IsReiject=*/false); + // A private-module-fragment, module :private; + if (!IsImport && Tmp.is(tok::kw_private)) + return true; + // import :N; + if (IsImport && Tmp.isNot(tok::identifier)) + return false; + } else if (!ExpectsIdentifier) { + ExpectsIdentifier = true; + } + IsLexingPartition = true; + ColonTokIndex = ModuleName.size(); + ModuleName.push_back(Result); + continue; + } + + // [cpp.module]/p2: where the pp-tokens (if any) shall not begin with a ( + // preprocessing token [...] + // + // We only emit diagnostic in the preprocessor, and in the parser we skip + // invalid tokens and recover from errors. + if (getLangOpts().CPlusPlusModules && !ExpectsIdentifier && + Result.is(tok::l_paren)) + Diag(Result, diag::err_unxepected_paren_in_module_decl) + << IsLexingPartition; + break; + } + + // Put the last token back to stream, it's not a valid part of module name. + // We lexed it unexpanded but it might be a valid macro expansion + Result.clearFlag(Token::DisableExpand); + auto ToksCopy = std::make_unique<Token[]>(1); + *ToksCopy.get() = Result; + EnterTokenStream(std::move(ToksCopy), 1, + /*DisableMacroExpansion=*/false, + /*IsReinject=*/false); + + if (ModuleName.empty()) + return false; + Result.startToken(); + Result.setKind(tok::annot_module_name); + Result.setLocation(ModuleName.front().getLocation()); + Result.setAnnotationEndLoc(ModuleName.back().getLocation()); + auto AnnotToks = ArrayRef(ModuleName).copy(getPreprocessorAllocator()); + ArrayRef<Token> ModuleNameToks, PartitionNameToks; + if (ColonTokIndex.has_value()) { + ModuleNameToks = + ArrayRef(AnnotToks.begin(), AnnotToks.begin() + *ColonTokIndex); + PartitionNameToks = + ArrayRef(AnnotToks.begin() + *ColonTokIndex, AnnotToks.end()); + } else { + ModuleNameToks = AnnotToks; + } ---------------- cor3ntin wrote:
I think you can simplify that by first setting `ColonTokIndex` to `AnnotToks.size()` when it does not have a value. Maybe we want to move the logic of creating the two slices to the constructor of `ModuleNameInfo` ie have a `ModuleNameInfo(Tok, OptionalColonIndex)` constructor https://github.com/llvm/llvm-project/pull/90574 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits