diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-08 17:13:11 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-08 17:13:11 +0000 |
commit | 0a5fb09b599c1bdea3cd11168bb8f4ff4040316e (patch) | |
tree | 5e94367d1a8032322c6871cfe16714c0982fd61a /lib/Lex | |
parent | f0c0337bbfb63d1f9edf145aab535bdf82c20454 (diff) | |
download | src-0a5fb09b599c1bdea3cd11168bb8f4ff4040316e.tar.gz src-0a5fb09b599c1bdea3cd11168bb8f4ff4040316e.zip |
Vendor import of clang trunk r302418:vendor/clang/clang-trunk-r302418
Notes
Notes:
svn path=/vendor/clang/dist/; revision=317951
svn path=/vendor/clang/clang-trunk-r302418/; revision=317952; tag=vendor/clang/clang-trunk-r302418
Diffstat (limited to 'lib/Lex')
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 10 | ||||
-rw-r--r-- | lib/Lex/Lexer.cpp | 66 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 58 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 8 | ||||
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 57 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/Pragma.cpp | 167 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 8 | ||||
-rw-r--r-- | lib/Lex/TokenLexer.cpp | 30 |
9 files changed, 298 insertions, 108 deletions
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index bd425a07c33a..f5b7c59e446f 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -1325,7 +1325,8 @@ static const FileEntry *getPrivateModuleMap(const FileEntry *File, return FileMgr.getFile(PrivateFilename); } -bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { +bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, + FileID ID, unsigned *Offset) { // Find the directory for the module. For frameworks, that may require going // up from the 'Modules' directory. const DirectoryEntry *Dir = nullptr; @@ -1344,7 +1345,7 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { } } - switch (loadModuleMapFileImpl(File, IsSystem, Dir)) { + switch (loadModuleMapFileImpl(File, IsSystem, Dir, ID, Offset)) { case LMM_AlreadyLoaded: case LMM_NewlyLoaded: return false; @@ -1357,7 +1358,8 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir) { + const DirectoryEntry *Dir, FileID ID, + unsigned *Offset) { assert(File && "expected FileEntry"); // Check whether we've already loaded this module map, and mark it as being @@ -1366,7 +1368,7 @@ HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, if (!AddResult.second) return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; - if (ModMap.parseModuleMapFile(File, IsSystem, Dir)) { + if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID, Offset)) { LoadedModuleMaps[File] = false; return LMM_InvalidModuleMap; } diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 003c9b5eed1b..3d6fe91115a9 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -452,6 +452,29 @@ bool Lexer::getRawToken(SourceLocation Loc, Token &Result, return false; } +/// Returns the pointer that points to the beginning of line that contains +/// the given offset, or null if the offset if invalid. +static const char *findBeginningOfLine(StringRef Buffer, unsigned Offset) { + const char *BufStart = Buffer.data(); + if (Offset >= Buffer.size()) + return nullptr; + const char *StrData = BufStart + Offset; + + if (StrData[0] == '\n' || StrData[0] == '\r') + return StrData; + + const char *LexStart = StrData; + while (LexStart != BufStart) { + if (LexStart[0] == '\n' || LexStart[0] == '\r') { + ++LexStart; + break; + } + + --LexStart; + } + return LexStart; +} + static SourceLocation getBeginningOfFileToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) { @@ -467,27 +490,15 @@ static SourceLocation getBeginningOfFileToken(SourceLocation Loc, // Back up from the current location until we hit the beginning of a line // (or the buffer). We'll relex from that point. - const char *BufStart = Buffer.data(); - if (LocInfo.second >= Buffer.size()) - return Loc; - - const char *StrData = BufStart+LocInfo.second; - if (StrData[0] == '\n' || StrData[0] == '\r') + const char *StrData = Buffer.data() + LocInfo.second; + const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second); + if (!LexStart || LexStart == StrData) return Loc; - - const char *LexStart = StrData; - while (LexStart != BufStart) { - if (LexStart[0] == '\n' || LexStart[0] == '\r') { - ++LexStart; - break; - } - - --LexStart; - } // Create a lexer starting at the beginning of this token. SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second); - Lexer TheLexer(LexerStartLoc, LangOpts, BufStart, LexStart, Buffer.end()); + Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart, + Buffer.end()); TheLexer.SetCommentRetentionState(true); // Lex tokens until we find the token that contains the source location. @@ -1038,6 +1049,27 @@ bool Lexer::isIdentifierBodyChar(char c, const LangOptions &LangOpts) { return isIdentifierBody(c, LangOpts.DollarIdents); } +StringRef Lexer::getIndentationForLine(SourceLocation Loc, + const SourceManager &SM) { + if (Loc.isInvalid() || Loc.isMacroID()) + return ""; + std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); + if (LocInfo.first.isInvalid()) + return ""; + bool Invalid = false; + StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); + if (Invalid) + return ""; + const char *Line = findBeginningOfLine(Buffer, LocInfo.second); + if (!Line) + return ""; + StringRef Rest = Buffer.substr(Line - Buffer.data()); + size_t NumWhitespaceChars = Rest.find_first_not_of(" \t"); + return NumWhitespaceChars == StringRef::npos + ? "" + : Rest.take_front(NumWhitespaceChars); +} + //===----------------------------------------------------------------------===// // Diagnostics forwarding code. //===----------------------------------------------------------------------===// diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 512d7dc5de68..70d37d3d7082 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -1132,14 +1132,17 @@ namespace clang { } bool parseModuleMapFile(); + + bool terminatedByDirective() { return false; } + SourceLocation getLocation() { return Tok.getLocation(); } }; } SourceLocation ModuleMapParser::consumeToken() { -retry: SourceLocation Result = Tok.getLocation(); + +retry: Tok.clear(); - Token LToken; L.LexFromRawLexer(LToken); Tok.Location = LToken.getLocation().getRawEncoding(); @@ -1232,9 +1235,28 @@ retry: 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; + } + } + LLVM_FALLTHROUGH; + default: - Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); + Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); HadError = true; goto retry; } @@ -1682,7 +1704,8 @@ void ModuleMapParser::parseExternModuleDecl() { File, /*IsSystem=*/false, Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd ? Directory - : File->getDir(), ExternLoc); + : File->getDir(), + FileID(), nullptr, ExternLoc); } /// Whether to add the requirement \p Feature to the module \p M. @@ -2522,28 +2545,45 @@ bool ModuleMapParser::parseModuleMapFile() { } bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir, + const DirectoryEntry *Dir, FileID ID, + unsigned *Offset, SourceLocation ExternModuleLoc) { + assert(Target && "Missing target information"); llvm::DenseMap<const FileEntry *, bool>::iterator Known = ParsedModuleMap.find(File); if (Known != ParsedModuleMap.end()) return Known->second; + // If the module map file wasn't already entered, do so now. + if (ID.isInvalid()) { + auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User; + ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); + } + assert(Target && "Missing target information"); - auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User; - FileID ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); if (!Buffer) return ParsedModuleMap[File] = true; + assert((!Offset || *Offset <= Buffer->getBufferSize()) && + "invalid buffer offset"); // Parse this module map file. - Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts); + Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, + Buffer->getBufferStart(), + Buffer->getBufferStart() + (Offset ? *Offset : 0), + Buffer->getBufferEnd()); SourceLocation Start = L.getSourceLocation(); ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, BuiltinIncludeDir, IsSystem); bool Result = Parser.parseModuleMapFile(); ParsedModuleMap[File] = Result; + if (Offset) { + auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); + assert(Loc.first == ID && "stopped in a different file?"); + *Offset = Loc.second; + } + // Notify callbacks that we parsed it. for (const auto &Cb : Callbacks) Cb->moduleMapFileRead(Start, *File, IsSystem); diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 4826e399afda..06fee8e5b0a8 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -2049,12 +2049,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, M->getTopLevelModuleName() == getLangOpts().CurrentModule) return; - assert(!CurSubmodule && "should not have marked this as a module yet"); - CurSubmodule = M; + assert(!CurLexerSubmodule && "should not have marked this as a module yet"); + CurLexerSubmodule = M; // Let the macro handling code know that any future macros are within // the new submodule. - EnterSubmodule(M, HashLoc); + EnterSubmodule(M, HashLoc, /*ForPragma*/false); // Let the parser know that any future declarations are within the new // submodule. @@ -2082,7 +2082,7 @@ void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc, } else if (isInPrimaryFile()) { Lookup = nullptr; Diag(IncludeNextTok, diag::pp_include_next_in_primary); - } else if (CurSubmodule) { + } else if (CurLexerSubmodule) { // Start looking up in the directory *after* the one in which the current // file would be found, if any. assert(CurPPLexer && "#include_next directive in macro?"); diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index fcc49b387034..1938328c904d 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -117,7 +117,7 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, CurLexer.reset(TheLexer); CurPPLexer = TheLexer; CurDirLookup = CurDir; - CurSubmodule = nullptr; + CurLexerSubmodule = nullptr; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_Lexer; @@ -142,7 +142,7 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL, CurDirLookup = CurDir; CurPTHLexer.reset(PL); CurPPLexer = CurPTHLexer.get(); - CurSubmodule = nullptr; + CurLexerSubmodule = nullptr; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_PTHLexer; @@ -337,6 +337,26 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { assert(!CurTokenLexer && "Ending a file when currently in a macro!"); + // If we have an unclosed module region from a pragma at the end of a + // module, complain and close it now. + // FIXME: This is not correct if we are building a module from PTH. + const bool LeavingSubmodule = CurLexer && CurLexerSubmodule; + if ((LeavingSubmodule || IncludeMacroStack.empty()) && + !BuildingSubmoduleStack.empty() && + BuildingSubmoduleStack.back().IsPragma) { + Diag(BuildingSubmoduleStack.back().ImportLoc, + diag::err_pp_module_begin_without_module_end); + Module *M = LeaveSubmodule(/*ForPragma*/true); + + Result.startToken(); + const char *EndPos = getCurLexerEndPos(); + CurLexer->BufferPtr = EndPos; + CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end); + Result.setAnnotationEndLoc(Result.getLocation()); + Result.setAnnotationValue(M); + return true; + } + // See if this file had a controlling macro. if (CurPPLexer) { // Not ending a macro, ignore it. if (const IdentifierInfo *ControllingMacro = @@ -442,18 +462,17 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { if (Callbacks && !isEndOfMacro && CurPPLexer) ExitedFID = CurPPLexer->getFileID(); - bool LeavingSubmodule = CurSubmodule && CurLexer; if (LeavingSubmodule) { + // We're done with this submodule. + Module *M = LeaveSubmodule(/*ForPragma*/false); + // Notify the parser that we've left the module. const char *EndPos = getCurLexerEndPos(); Result.startToken(); CurLexer->BufferPtr = EndPos; CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end); Result.setAnnotationEndLoc(Result.getLocation()); - Result.setAnnotationValue(CurSubmodule); - - // We're done with this submodule. - LeaveSubmodule(); + Result.setAnnotationValue(M); } // We're done with the #included file. @@ -628,11 +647,13 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { assert(!FoundLexer && "Lexer should return EOD before EOF in PP mode"); } -void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { +void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc, + bool ForPragma) { if (!getLangOpts().ModulesLocalVisibility) { // Just track that we entered this submodule. - BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( - M, ImportLoc, CurSubmoduleState, PendingModuleMacroNames.size())); + BuildingSubmoduleStack.push_back( + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); return; } @@ -673,8 +694,9 @@ void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { } // Track that we entered this module. - BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( - M, ImportLoc, CurSubmoduleState, PendingModuleMacroNames.size())); + BuildingSubmoduleStack.push_back( + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); // Switch to this submodule as the current submodule. CurSubmoduleState = &State; @@ -697,7 +719,13 @@ bool Preprocessor::needModuleMacros() const { return getLangOpts().isCompilingModule(); } -void Preprocessor::LeaveSubmodule() { +Module *Preprocessor::LeaveSubmodule(bool ForPragma) { + if (BuildingSubmoduleStack.empty() || + BuildingSubmoduleStack.back().IsPragma != ForPragma) { + assert(ForPragma && "non-pragma module enter/leave mismatch"); + return nullptr; + } + auto &Info = BuildingSubmoduleStack.back(); Module *LeavingMod = Info.M; @@ -711,7 +739,7 @@ void Preprocessor::LeaveSubmodule() { // of pending names for the surrounding submodule. BuildingSubmoduleStack.pop_back(); makeModuleVisible(LeavingMod, ImportLoc); - return; + return LeavingMod; } // Create ModuleMacros for any macros defined in this submodule. @@ -800,4 +828,5 @@ void Preprocessor::LeaveSubmodule() { // A nested #include makes the included submodule visible. makeModuleVisible(LeavingMod, ImportLoc); + return LeavingMod; } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 196223981d74..6c7663994a49 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -1453,7 +1453,7 @@ static bool EvaluateHasIncludeNext(Token &Tok, } else if (PP.isInPrimaryFile()) { Lookup = nullptr; PP.Diag(Tok, diag::pp_include_next_in_primary); - } else if (PP.getCurrentSubmodule()) { + } else if (PP.getCurrentLexerSubmodule()) { // Start looking up in the directory *after* the one in which the current // file would be found, if any. assert(PP.getCurrentLexer() && "#include_next directive in macro?"); diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 576151a98b2c..99d56182c1bb 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -534,47 +534,6 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { } } -void Preprocessor::HandlePragmaModuleImport(Token &ImportTok) { - SourceLocation ImportLoc = ImportTok.getLocation(); - - Token Tok; - - llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> ModuleName; - while (true) { - LexUnexpandedToken(Tok); - if (Tok.isNot(tok::identifier)) { - Diag(Tok.getLocation(), - diag::err_pragma_module_import_expected_module_name) << 0; - return; - } - - ModuleName.emplace_back(Tok.getIdentifierInfo(), Tok.getLocation()); - - LexUnexpandedToken(Tok); - assert(Tok.isNot(tok::eof)); - if (Tok.is(tok::eod)) - break; - if (Tok.isNot(tok::period)) { - Diag(Tok.getLocation(), - diag::err_pragma_module_import_expected_module_name) << 1; - return; - } - } - - // If we have a non-empty module path, load the named module. - Module *Imported = - TheModuleLoader.loadModule(ImportLoc, ModuleName, Module::Hidden, - /*IsIncludeDirective=*/false); - if (!Imported) - return; - - makeModuleVisible(Imported, ImportLoc); - EnterAnnotationToken(SourceRange(ImportLoc, Tok.getLocation()), - tok::annot_module_include, Imported); - if (Callbacks) - Callbacks->moduleImport(ImportLoc, ModuleName, Imported); -} - /// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro. /// Return the IdentifierInfo* associated with the macro to push or pop. IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { @@ -1342,6 +1301,26 @@ public: } }; +static bool LexModuleName( + Preprocessor &PP, Token &Tok, + llvm::SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> + &ModuleName) { + while (true) { + PP.LexUnexpandedToken(Tok); + if (Tok.isAnnotation() || !Tok.getIdentifierInfo()) { + PP.Diag(Tok.getLocation(), diag::err_pp_expected_module_name) + << ModuleName.empty(); + return true; + } + + ModuleName.emplace_back(Tok.getIdentifierInfo(), Tok.getLocation()); + + PP.LexUnexpandedToken(Tok); + if (Tok.isNot(tok::period)) + return false; + } +} + /// Handle the clang \#pragma module import extension. The syntax is: /// \code /// #pragma clang module import some.module.name @@ -1350,8 +1329,108 @@ struct PragmaModuleImportHandler : public PragmaHandler { PragmaModuleImportHandler() : PragmaHandler("import") {} void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &ImportTok) override { - PP.HandlePragmaModuleImport(ImportTok); + Token &Tok) override { + SourceLocation ImportLoc = Tok.getLocation(); + + // Read the module name. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> + ModuleName; + if (LexModuleName(PP, Tok, ModuleName)) + return; + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + // If we have a non-empty module path, load the named module. + Module *Imported = + PP.getModuleLoader().loadModule(ImportLoc, ModuleName, Module::Hidden, + /*IsIncludeDirective=*/false); + if (!Imported) + return; + + PP.makeModuleVisible(Imported, ImportLoc); + PP.EnterAnnotationToken(SourceRange(ImportLoc, ModuleName.back().second), + tok::annot_module_include, Imported); + if (auto *CB = PP.getPPCallbacks()) + CB->moduleImport(ImportLoc, ModuleName, Imported); + } +}; + +/// Handle the clang \#pragma module begin extension. The syntax is: +/// \code +/// #pragma clang module begin some.module.name +/// ... +/// #pragma clang module end +/// \endcode +struct PragmaModuleBeginHandler : public PragmaHandler { + PragmaModuleBeginHandler() : PragmaHandler("begin") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + SourceLocation BeginLoc = Tok.getLocation(); + + // Read the module name. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> + ModuleName; + if (LexModuleName(PP, Tok, ModuleName)) + return; + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + // We can only enter submodules of the current module. + StringRef Current = PP.getLangOpts().CurrentModule; + if (ModuleName.front().first->getName() != Current) { + PP.Diag(ModuleName.front().second, diag::err_pp_module_begin_wrong_module) + << ModuleName.front().first << (ModuleName.size() > 1) + << Current.empty() << Current; + return; + } + + // Find the module we're entering. We require that a module map for it + // be loaded or implicitly loadable. + // FIXME: We could create the submodule here. We'd need to know whether + // it's supposed to be explicit, but not much else. + Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(Current); + if (!M) { + PP.Diag(ModuleName.front().second, + diag::err_pp_module_begin_no_module_map) << Current; + return; + } + for (unsigned I = 1; I != ModuleName.size(); ++I) { + auto *NewM = M->findSubmodule(ModuleName[I].first->getName()); + if (!NewM) { + PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule) + << M->getFullModuleName() << ModuleName[I].first; + return; + } + M = NewM; + } + + // Enter the scope of the submodule. + PP.EnterSubmodule(M, BeginLoc, /*ForPragma*/true); + PP.EnterAnnotationToken(SourceRange(BeginLoc, ModuleName.back().second), + tok::annot_module_begin, M); + } +}; + +/// Handle the clang \#pragma module end extension. +struct PragmaModuleEndHandler : public PragmaHandler { + PragmaModuleEndHandler() : PragmaHandler("end") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + SourceLocation Loc = Tok.getLocation(); + + PP.LexUnexpandedToken(Tok); + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + Module *M = PP.LeaveSubmodule(/*ForPragma*/true); + if (M) + PP.EnterAnnotationToken(SourceRange(Loc), tok::annot_module_end, M); + else + PP.Diag(Loc, diag::err_pp_module_end_without_module_begin); } }; @@ -1582,6 +1661,8 @@ void Preprocessor::RegisterBuiltinPragmas() { auto *ModuleHandler = new PragmaNamespace("module"); AddPragmaHandler("clang", ModuleHandler); ModuleHandler->AddPragma(new PragmaModuleImportHandler()); + ModuleHandler->AddPragma(new PragmaModuleBeginHandler()); + ModuleHandler->AddPragma(new PragmaModuleEndHandler()); AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index babef5dcc7ca..e409ab036535 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -85,10 +85,10 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, LastTokenWasAt(false), ModuleImportExpectsIdentifier(false), CodeCompletionReached(false), CodeCompletionII(nullptr), MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr), - CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), - Callbacks(nullptr), CurSubmoduleState(&NullSubmoduleState), - MacroArgCache(nullptr), Record(nullptr), MIChainHead(nullptr), - DeserialMIChainHead(nullptr) { + CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), + CurLexerSubmodule(nullptr), Callbacks(nullptr), + CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr), + Record(nullptr), MIChainHead(nullptr), DeserialMIChainHead(nullptr) { OwnsHeaderSearch = OwnsHeaders; CounterValue = 0; // __COUNTER__ starts at 0. diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index a53c8014ebaf..049e046cece1 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -183,6 +183,12 @@ void TokenLexer::ExpandFunctionArguments() { // preprocessor already verified that the following token is a macro name // when the #define was parsed. const Token &CurTok = Tokens[i]; + // We don't want a space for the next token after a paste + // operator. In valid code, the token will get smooshed onto the + // preceding one anyway. In assembler-with-cpp mode, invalid + // pastes are allowed through: in this case, we do not want the + // extra whitespace to be added. For example, we want ". ## foo" + // -> ".foo" not ". foo". if (i != 0 && !Tokens[i-1].is(tok::hashhash) && CurTok.hasLeadingSpace()) NextTokGetsSpace = true; @@ -317,6 +323,7 @@ void TokenLexer::ExpandFunctionArguments() { const Token *ArgToks = ActualArgs->getUnexpArgument(ArgNo); unsigned NumToks = MacroArgs::getArgLength(ArgToks); if (NumToks) { // Not an empty argument? + bool VaArgsPseudoPaste = false; // If this is the GNU ", ## __VA_ARGS__" extension, and we just learned // that __VA_ARGS__ expands to multiple tokens, avoid a pasting error when // the expander trys to paste ',' with the first token of the __VA_ARGS__ @@ -325,6 +332,7 @@ void TokenLexer::ExpandFunctionArguments() { ResultToks[ResultToks.size()-2].is(tok::comma) && (unsigned)ArgNo == Macro->getNumArgs()-1 && Macro->isVariadic()) { + VaArgsPseudoPaste = true; // Remove the paste operator, report use of the extension. PP.Diag(ResultToks.pop_back_val().getLocation(), diag::ext_paste_comma); } @@ -344,18 +352,16 @@ void TokenLexer::ExpandFunctionArguments() { ResultToks.end()-NumToks, ResultToks.end()); } - // If this token (the macro argument) was supposed to get leading - // whitespace, transfer this information onto the first token of the - // expansion. - // - // Do not do this if the paste operator occurs before the macro argument, - // as in "A ## MACROARG". In valid code, the first token will get - // smooshed onto the preceding one anyway (forming AMACROARG). In - // assembler-with-cpp mode, invalid pastes are allowed through: in this - // case, we do not want the extra whitespace to be added. For example, - // we want ". ## foo" -> ".foo" not ". foo". - if (NextTokGetsSpace) - ResultToks[ResultToks.size()-NumToks].setFlag(Token::LeadingSpace); + // Transfer the leading whitespace information from the token + // (the macro argument) onto the first token of the + // expansion. Note that we don't do this for the GNU + // pseudo-paste extension ", ## __VA_ARGS__". + if (!VaArgsPseudoPaste) { + ResultToks[ResultToks.size() - NumToks].setFlagValue(Token::StartOfLine, + false); + ResultToks[ResultToks.size() - NumToks].setFlagValue( + Token::LeadingSpace, NextTokGetsSpace); + } NextTokGetsSpace = false; continue; |