diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-02 18:30:45 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-02 18:30:45 +0000 |
commit | 570918821a8492048e6ab54955c9864bd6c3e952 (patch) | |
tree | f9d0d3f3478c298aaf51987483bbbbefe8e6631b /lib/Lex/Pragma.cpp | |
parent | f0c55418e2b09eaab37c820d3756cc1b4584d084 (diff) |
Diffstat (limited to 'lib/Lex/Pragma.cpp')
-rw-r--r-- | lib/Lex/Pragma.cpp | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 87e105d1d03d4..576151a98b2c0 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -508,7 +508,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { const DirectoryLookup *CurDir; const FileEntry *File = LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr, - nullptr, CurDir, nullptr, nullptr, nullptr); + nullptr, CurDir, nullptr, nullptr, nullptr, nullptr); if (!File) { if (!SuppressIncludeNotFoundError) Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; @@ -534,6 +534,47 @@ 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) { @@ -1301,6 +1342,19 @@ public: } }; +/// Handle the clang \#pragma module import extension. The syntax is: +/// \code +/// #pragma clang module import some.module.name +/// \endcode +struct PragmaModuleImportHandler : public PragmaHandler { + PragmaModuleImportHandler() : PragmaHandler("import") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &ImportTok) override { + PP.HandlePragmaModuleImport(ImportTok); + } +}; + /// PragmaPushMacroHandler - "\#pragma push_macro" saves the value of the /// macro on the top of the stack. struct PragmaPushMacroHandler : public PragmaHandler { @@ -1524,6 +1578,11 @@ void Preprocessor::RegisterBuiltinPragmas() { AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler()); AddPragmaHandler("clang", new PragmaAssumeNonNullHandler()); + // #pragma clang module ... + auto *ModuleHandler = new PragmaNamespace("module"); + AddPragmaHandler("clang", ModuleHandler); + ModuleHandler->AddPragma(new PragmaModuleImportHandler()); + AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler()); |