summaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Frontend
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend')
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp227
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp30
6 files changed, 235 insertions, 84 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index d3ebf48315e2..96854b8fbc1a 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -766,6 +766,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.SanitizeCoverageTracePC = Args.hasArg(OPT_fsanitize_coverage_trace_pc);
Opts.SanitizeCoverageTracePCGuard =
Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard);
+ Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune);
Opts.SanitizeMemoryTrackOrigins =
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
Opts.SanitizeMemoryUseAfterDtor =
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
index d26b6937b851..1fbb2b054bad 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
@@ -136,6 +136,12 @@ void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput,
CurrentASTUnit = std::move(AST);
}
+Module *FrontendAction::getCurrentModule() const {
+ CompilerInstance &CI = getCompilerInstance();
+ return CI.getPreprocessor().getHeaderSearchInfo().lookupModule(
+ CI.getLangOpts().CurrentModule, /*AllowSearch*/false);
+}
+
std::unique_ptr<ASTConsumer>
FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
StringRef InFile) {
@@ -188,16 +194,25 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
-// For preprocessed files, if the first line is the linemarker and specifies
-// the original source file name, use that name as the input file name.
-static bool ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile)
-{
- bool Invalid = false;
+/// For preprocessed files, if the first line is the linemarker and specifies
+/// the original source file name, use that name as the input file name.
+/// Returns the location of the first token after the line marker directive.
+///
+/// \param CI The compiler instance.
+/// \param InputFile Populated with the filename from the line marker.
+/// \param AddLineNote If \c true, add a line note corresponding to this line
+/// directive. Only use this if the directive will not actually be
+/// visited by the preprocessor.
+static SourceLocation ReadOriginalFileName(CompilerInstance &CI,
+ std::string &InputFile,
+ bool AddLineNote = false) {
auto &SourceMgr = CI.getSourceManager();
auto MainFileID = SourceMgr.getMainFileID();
+
+ bool Invalid = false;
const auto *MainFileBuf = SourceMgr.getBuffer(MainFileID, &Invalid);
if (Invalid)
- return false;
+ return SourceLocation();
std::unique_ptr<Lexer> RawLexer(
new Lexer(MainFileID, MainFileBuf, SourceMgr, CI.getLangOpts()));
@@ -209,19 +224,37 @@ static bool ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile)
// we use FILENAME as the input file name.
Token T;
if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash)
- return false;
+ return SourceLocation();
if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() ||
T.getKind() != tok::numeric_constant)
- return false;
+ return SourceLocation();
+
+ unsigned LineNo;
+ SourceLocation LineNoLoc = T.getLocation();
+ if (AddLineNote) {
+ llvm::SmallString<16> Buffer;
+ if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts())
+ .getAsInteger(10, LineNo))
+ return SourceLocation();
+ }
+
RawLexer->LexFromRawLexer(T);
if (T.isAtStartOfLine() || T.getKind() != tok::string_literal)
- return false;
+ return SourceLocation();
StringLiteralParser Literal(T, CI.getPreprocessor());
if (Literal.hadError)
- return false;
+ return SourceLocation();
+ RawLexer->LexFromRawLexer(T);
+ if (T.isNot(tok::eof) && !T.isAtStartOfLine())
+ return SourceLocation();
InputFile = Literal.GetString().str();
- return true;
+
+ if (AddLineNote)
+ CI.getSourceManager().AddLineNote(
+ LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile));
+
+ return T.getLocation();
}
static SmallVectorImpl<char> &
@@ -339,42 +372,44 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
return std::error_code();
}
-/// Parse a module map and compute the corresponding real input buffer that
-/// should be used to build the module described by that module map and the
-/// current module name.
-static std::unique_ptr<llvm::MemoryBuffer>
-getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename,
- bool IsSystem) {
- // Find the module map file.
- const FileEntry *ModuleMap =
- CI.getFileManager().getFile(Filename, /*openFile*/true);
- if (!ModuleMap) {
- CI.getDiagnostics().Report(diag::err_module_map_not_found)
- << Filename;
- return nullptr;
- }
+static bool
+loadModuleMapForModuleBuild(CompilerInstance &CI, StringRef Filename,
+ bool IsSystem, bool IsPreprocessed,
+ unsigned &Offset) {
+ auto &SrcMgr = CI.getSourceManager();
+ HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
- // Find the module map file from which it was generated, if different.
- const FileEntry *OriginalModuleMap = ModuleMap;
- StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap;
- if (!OriginalModuleMapName.empty()) {
- OriginalModuleMap = CI.getFileManager().getFile(OriginalModuleMapName,
- /*openFile*/ true);
- if (!OriginalModuleMap) {
- CI.getDiagnostics().Report(diag::err_module_map_not_found)
- << OriginalModuleMapName;
- return nullptr;
- }
+ // Map the current input to a file.
+ FileID ModuleMapID = SrcMgr.getMainFileID();
+ const FileEntry *ModuleMap = SrcMgr.getFileEntryForID(ModuleMapID);
+
+ // If the module map is preprocessed, handle the initial line marker;
+ // line directives are not part of the module map syntax in general.
+ Offset = 0;
+ if (IsPreprocessed) {
+ std::string PresumedModuleMapFile;
+ SourceLocation EndOfLineMarker =
+ ReadOriginalFileName(CI, PresumedModuleMapFile, /*AddLineNote*/true);
+ if (EndOfLineMarker.isValid())
+ Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second;
+ // FIXME: Use PresumedModuleMapFile as the MODULE_MAP_FILE in the PCM.
}
-
- // Parse the module map file.
- HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
- if (HS.loadModuleMapFile(ModuleMap, IsSystem))
- return nullptr;
-
+
+ // Load the module map file.
+ if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset))
+ return true;
+
+ if (SrcMgr.getBuffer(ModuleMapID)->getBufferSize() == Offset)
+ Offset = 0;
+
+ return false;
+}
+
+static Module *prepareToBuildModule(CompilerInstance &CI,
+ StringRef ModuleMapFilename) {
if (CI.getLangOpts().CurrentModule.empty()) {
CI.getDiagnostics().Report(diag::err_missing_module_name);
-
+
// FIXME: Eventually, we could consider asking whether there was just
// a single module described in the module map, and use that as a
// default. Then it would be fairly trivial to just "compile" a module
@@ -382,21 +417,14 @@ getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename,
return nullptr;
}
- // If we're being run from the command-line, the module build stack will not
- // have been filled in yet, so complete it now in order to allow us to detect
- // module cycles.
- SourceManager &SourceMgr = CI.getSourceManager();
- if (SourceMgr.getModuleBuildStack().empty())
- SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule,
- FullSourceLoc(SourceLocation(), SourceMgr));
-
// Dig out the module definition.
+ HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule,
/*AllowSearch=*/false);
if (!M) {
CI.getDiagnostics().Report(diag::err_missing_module)
- << CI.getLangOpts().CurrentModule << Filename;
-
+ << CI.getLangOpts().CurrentModule << ModuleMapFilename;
+
return nullptr;
}
@@ -417,11 +445,45 @@ getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename,
return nullptr;
}
- if (OriginalModuleMap != ModuleMap) {
- M->IsInferred = true;
- HS.getModuleMap().setInferredModuleAllowedBy(M, OriginalModuleMap);
+ // Inform the preprocessor that includes from within the input buffer should
+ // be resolved relative to the build directory of the module map file.
+ CI.getPreprocessor().setMainFileDir(M->Directory);
+
+ // If the module was inferred from a different module map (via an expanded
+ // umbrella module definition), track that fact.
+ // FIXME: It would be preferable to fill this in as part of processing
+ // the module map, rather than adding it after the fact.
+ StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap;
+ if (!OriginalModuleMapName.empty()) {
+ auto *OriginalModuleMap =
+ CI.getFileManager().getFile(OriginalModuleMapName,
+ /*openFile*/ true);
+ if (!OriginalModuleMap) {
+ CI.getDiagnostics().Report(diag::err_module_map_not_found)
+ << OriginalModuleMapName;
+ return nullptr;
+ }
+ if (OriginalModuleMap != CI.getSourceManager().getFileEntryForID(
+ CI.getSourceManager().getMainFileID())) {
+ M->IsInferred = true;
+ CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()
+ .setInferredModuleAllowedBy(M, OriginalModuleMap);
+ }
}
+ // If we're being run from the command-line, the module build stack will not
+ // have been filled in yet, so complete it now in order to allow us to detect
+ // module cycles.
+ SourceManager &SourceMgr = CI.getSourceManager();
+ if (SourceMgr.getModuleBuildStack().empty())
+ SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule,
+ FullSourceLoc(SourceLocation(), SourceMgr));
+ return M;
+}
+
+/// Compute the input buffer that should be used to build the specified module.
+static std::unique_ptr<llvm::MemoryBuffer>
+getInputBufferForModule(CompilerInstance &CI, Module *M) {
FileManager &FileMgr = CI.getFileManager();
// Collect the set of #includes we need to build the module.
@@ -441,10 +503,6 @@ getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename,
return nullptr;
}
- // Inform the preprocessor that includes from within the input buffer should
- // be resolved relative to the build directory of the module map file.
- CI.getPreprocessor().setMainFileDir(M->Directory);
-
return llvm::MemoryBuffer::getMemBufferCopy(
HeaderContents, Module::getModuleInputBufferName());
}
@@ -457,7 +515,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
setCompilerInstance(&CI);
StringRef InputFile = Input.getFile();
- FrontendInputFile FileToProcess = Input;
bool HasBegunSourceFile = false;
if (!BeginInvocation(CI))
goto failure;
@@ -597,36 +654,45 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
&CI.getPreprocessor());
HasBegunSourceFile = true;
+ // Initialize the main file entry.
+ if (!CI.InitializeSourceManager(Input))
+ goto failure;
+
// For module map files, we first parse the module map and synthesize a
// "<module-includes>" buffer before more conventional processing.
if (Input.getKind().getFormat() == InputKind::ModuleMap) {
CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap);
- auto Buffer = getInputBufferForModuleMap(CI, InputFile, Input.isSystem());
- if (!Buffer)
+ unsigned OffsetToContents;
+ if (loadModuleMapForModuleBuild(CI, Input.getFile(), Input.isSystem(),
+ Input.isPreprocessed(), OffsetToContents))
goto failure;
- Module *CurrentModule =
- CI.getPreprocessor().getHeaderSearchInfo().lookupModule(
- CI.getLangOpts().CurrentModule,
- /*AllowSearch=*/false);
- assert(CurrentModule && "no module info for current module");
+ auto *CurrentModule = prepareToBuildModule(CI, Input.getFile());
+ if (!CurrentModule)
+ goto failure;
+
+ if (OffsetToContents)
+ // If the module contents are in the same file, skip to them.
+ CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true);
+ else {
+ // Otherwise, convert the module description to a suitable input buffer.
+ auto Buffer = getInputBufferForModule(CI, CurrentModule);
+ if (!Buffer)
+ goto failure;
- // The input that we end up processing is the generated buffer, not the
- // module map file itself.
- FileToProcess = FrontendInputFile(
- Buffer.release(), Input.getKind().withFormat(InputKind::Source),
- CurrentModule->IsSystem);
+ // Reinitialize the main file entry to refer to the new input.
+ if (!CI.InitializeSourceManager(FrontendInputFile(
+ Buffer.release(), Input.getKind().withFormat(InputKind::Source),
+ CurrentModule->IsSystem)))
+ goto failure;
+ }
}
// Initialize the action.
if (!BeginSourceFileAction(CI, InputFile))
goto failure;
- // Initialize the main file entry.
- if (!CI.InitializeSourceManager(FileToProcess))
- goto failure;
-
// Create the AST context and consumer unless this is a preprocessor only
// action.
if (!usesPreprocessorOnly()) {
@@ -636,13 +702,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// For preprocessed files, check if the first line specifies the original
// source file name with a linemarker.
- std::string OrigFile;
+ std::string PresumedInputFile = InputFile;
if (Input.isPreprocessed())
- if (ReadOriginalFileName(CI, OrigFile))
- InputFile = OrigFile;
+ ReadOriginalFileName(CI, PresumedInputFile);
std::unique_ptr<ASTConsumer> Consumer =
- CreateWrappedASTConsumer(CI, InputFile);
+ CreateWrappedASTConsumer(CI, PresumedInputFile);
if (!Consumer)
goto failure;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
index dd7c12f60f0e..baaf93b167bc 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
@@ -542,6 +542,18 @@ void PrintPreprocessedAction::ExecuteAction() {
CI.createDefaultOutputFile(BinaryMode, getCurrentFile());
if (!OS) return;
+ // If we're preprocessing a module map, start by dumping the contents of the
+ // module itself before switching to the input buffer.
+ auto &Input = getCurrentInput();
+ if (Input.getKind().getFormat() == InputKind::ModuleMap) {
+ if (Input.isFile())
+ (*OS) << "# 1 \"" << Input.getFile() << "\"\n";
+ // FIXME: Include additional information here so that we don't need the
+ // original source files to exist on disk.
+ getCurrentModule()->print(*OS);
+ (*OS) << "#pragma clang module contents\n";
+ }
+
DoPrintPreprocessedInput(CI.getPreprocessor(), OS.get(),
CI.getPreprocessorOutputOpts());
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
index ffedf3cac847..832eaf2926f0 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -174,6 +174,9 @@ public:
void MacroUndefined(const Token &MacroNameTok,
const MacroDefinition &MD,
const MacroDirective *Undef) override;
+
+ void BeginModule(const Module *M);
+ void EndModule(const Module *M);
};
} // end anonymous namespace
@@ -372,6 +375,20 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
}
}
+/// Handle entering the scope of a module during a module compilation.
+void PrintPPOutputPPCallbacks::BeginModule(const Module *M) {
+ startNewLineIfNeeded();
+ OS << "#pragma clang module begin " << M->getFullModuleName();
+ setEmittedDirectiveOnThisLine();
+}
+
+/// Handle leaving the scope of a module during a module compilation.
+void PrintPPOutputPPCallbacks::EndModule(const Module *M) {
+ startNewLineIfNeeded();
+ OS << "#pragma clang module end /*" << M->getFullModuleName() << "*/";
+ setEmittedDirectiveOnThisLine();
+}
+
/// Ident - Handle #ident directives when read by the preprocessor.
///
void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) {
@@ -685,13 +702,27 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
// -traditional-cpp the lexer keeps /all/ whitespace, including comments.
SourceLocation StartLoc = Tok.getLocation();
Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength()));
- } else if (Tok.is(tok::annot_module_include) ||
- Tok.is(tok::annot_module_begin) ||
- Tok.is(tok::annot_module_end)) {
+ } else if (Tok.is(tok::annot_module_include)) {
// PrintPPOutputPPCallbacks::InclusionDirective handles producing
// appropriate output here. Ignore this token entirely.
PP.Lex(Tok);
continue;
+ } else if (Tok.is(tok::annot_module_begin)) {
+ // FIXME: We retrieve this token after the FileChanged callback, and
+ // retrieve the module_end token before the FileChanged callback, so
+ // we render this within the file and render the module end outside the
+ // file, but this is backwards from the token locations: the module_begin
+ // token is at the include location (outside the file) and the module_end
+ // token is at the EOF location (within the file).
+ Callbacks->BeginModule(
+ reinterpret_cast<Module *>(Tok.getAnnotationValue()));
+ PP.Lex(Tok);
+ continue;
+ } else if (Tok.is(tok::annot_module_end)) {
+ Callbacks->EndModule(
+ reinterpret_cast<Module *>(Tok.getAnnotationValue()));
+ PP.Lex(Tok);
+ continue;
} else if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
OS << II->getName();
} else if (Tok.isLiteral() && !Tok.needsCleaning() &&
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
index 2e76e2e3151e..8c5eb161b5ab 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -196,6 +196,18 @@ void RewriteIncludesAction::ExecuteAction() {
CI.createDefaultOutputFile(true, getCurrentFile());
if (!OS) return;
+ // If we're preprocessing a module map, start by dumping the contents of the
+ // module itself before switching to the input buffer.
+ auto &Input = getCurrentInput();
+ if (Input.getKind().getFormat() == InputKind::ModuleMap) {
+ if (Input.isFile())
+ (*OS) << "# 1 \"" << Input.getFile() << "\"\n";
+ // FIXME: Include additional information here so that we don't need the
+ // original source files to exist on disk.
+ getCurrentModule()->print(*OS);
+ (*OS) << "#pragma clang module contents\n";
+ }
+
RewriteIncludesInInput(CI.getPreprocessor(), OS.get(),
CI.getPreprocessorOutputOpts());
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
index ee61f76d029d..d45cbc01df8c 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -46,6 +46,8 @@ class InclusionRewriter : public PPCallbacks {
std::map<unsigned, IncludedFile> FileIncludes;
/// Tracks where inclusions that import modules are found.
std::map<unsigned, const Module *> ModuleIncludes;
+ /// Tracks where inclusions that enter modules (in a module build) are found.
+ std::map<unsigned, const Module *> ModuleEntryIncludes;
/// Used transitively for building up the FileIncludes mapping over the
/// various \c PPCallbacks callbacks.
SourceLocation LastInclusionLocation;
@@ -57,6 +59,11 @@ public:
PredefinesBuffer = Buf;
}
void detectMainFileEOL();
+ void handleModuleBegin(Token &Tok) {
+ assert(Tok.getKind() == tok::annot_module_begin);
+ ModuleEntryIncludes.insert({Tok.getLocation().getRawEncoding(),
+ (Module *)Tok.getAnnotationValue()});
+ }
private:
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
@@ -84,6 +91,7 @@ private:
bool &FileExists);
const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const;
const Module *FindModuleAtLocation(SourceLocation Loc) const;
+ const Module *FindEnteredModule(SourceLocation Loc) const;
StringRef NextIdentifierName(Lexer &RawLex, Token &RawToken);
};
@@ -211,6 +219,16 @@ InclusionRewriter::FindModuleAtLocation(SourceLocation Loc) const {
return nullptr;
}
+/// Simple lookup for a SourceLocation (specifically one denoting the hash in
+/// an inclusion directive) in the map of module entry information.
+const Module *
+InclusionRewriter::FindEnteredModule(SourceLocation Loc) const {
+ const auto I = ModuleEntryIncludes.find(Loc.getRawEncoding());
+ if (I != ModuleEntryIncludes.end())
+ return I->second;
+ return nullptr;
+}
+
/// Detect the likely line ending style of \p FromFile by examining the first
/// newline found within it.
static StringRef DetectEOL(const MemoryBuffer &FromFile) {
@@ -452,8 +470,18 @@ void InclusionRewriter::Process(FileID FileId,
if (const Module *Mod = FindModuleAtLocation(Loc))
WriteImplicitModuleImport(Mod);
else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) {
+ const Module *Mod = FindEnteredModule(Loc);
+ if (Mod)
+ OS << "#pragma clang module begin " << Mod->getFullModuleName()
+ << "\n";
+
// Include and recursively process the file.
Process(Inc->Id, Inc->FileType);
+
+ if (Mod)
+ OS << "#pragma clang module end /*" << Mod->getFullModuleName()
+ << "*/\n";
+
// Add line marker to indicate we're returning from an included
// file.
LineInfoExtra = " 2";
@@ -590,6 +618,8 @@ void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
PP.SetMacroExpansionOnlyInDirectives();
do {
PP.Lex(Tok);
+ if (Tok.is(tok::annot_module_begin))
+ Rewrite->handleModuleBegin(Tok);
} while (Tok.isNot(tok::eof));
Rewrite->setPredefinesBuffer(SM.getBuffer(PP.getPredefinesFileID()));
Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User);