[frontend] -frewrite-includes: turn implicit module imports into @imports.

rdar://13610250

llvm-svn: 179145
This commit is contained in:
Argyrios Kyrtzidis 2013-04-10 01:53:50 +00:00
parent a6444b1ce1
commit cf22d1f3ab
2 changed files with 44 additions and 15 deletions

View File

@ -27,10 +27,11 @@ class InclusionRewriter : public PPCallbacks {
/// Information about which #includes were actually performed, /// Information about which #includes were actually performed,
/// created by preprocessor callbacks. /// created by preprocessor callbacks.
struct FileChange { struct FileChange {
const Module *Mod;
SourceLocation From; SourceLocation From;
FileID Id; FileID Id;
SrcMgr::CharacteristicKind FileType; SrcMgr::CharacteristicKind FileType;
FileChange(SourceLocation From) : From(From) { FileChange(SourceLocation From, const Module *Mod) : Mod(Mod), From(From) {
} }
}; };
Preprocessor &PP; ///< Used to find inclusion directives. Preprocessor &PP; ///< Used to find inclusion directives.
@ -65,6 +66,7 @@ private:
void WriteLineInfo(const char *Filename, int Line, void WriteLineInfo(const char *Filename, int Line,
SrcMgr::CharacteristicKind FileType, SrcMgr::CharacteristicKind FileType,
StringRef EOL, StringRef Extra = StringRef()); StringRef EOL, StringRef Extra = StringRef());
void WriteImplicitModuleImport(const Module *Mod, StringRef EOL);
void OutputContentUpTo(const MemoryBuffer &FromFile, void OutputContentUpTo(const MemoryBuffer &FromFile,
unsigned &WriteFrom, unsigned WriteTo, unsigned &WriteFrom, unsigned WriteTo,
StringRef EOL, int &lines, StringRef EOL, int &lines,
@ -117,6 +119,12 @@ void InclusionRewriter::WriteLineInfo(const char *Filename, int Line,
OS << EOL; OS << EOL;
} }
void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod,
StringRef EOL) {
OS << "@import " << Mod->getFullModuleName() << ";"
<< " /* clang -frewrite-includes: implicit import */" << EOL;
}
/// FileChanged - Whenever the preprocessor enters or exits a #include file /// FileChanged - Whenever the preprocessor enters or exits a #include file
/// it invokes this handler. /// it invokes this handler.
void InclusionRewriter::FileChanged(SourceLocation Loc, void InclusionRewriter::FileChanged(SourceLocation Loc,
@ -157,12 +165,13 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc,
const FileEntry * /*File*/, const FileEntry * /*File*/,
StringRef /*SearchPath*/, StringRef /*SearchPath*/,
StringRef /*RelativePath*/, StringRef /*RelativePath*/,
const Module * /*Imported*/) { const Module *Imported) {
assert(LastInsertedFileChange == FileChanges.end() && "Another inclusion " assert(LastInsertedFileChange == FileChanges.end() && "Another inclusion "
"directive was found before the previous one was processed"); "directive was found before the previous one was processed");
std::pair<FileChangeMap::iterator, bool> p = FileChanges.insert( std::pair<FileChangeMap::iterator, bool> p = FileChanges.insert(
std::make_pair(HashLoc.getRawEncoding(), FileChange(HashLoc))); std::make_pair(HashLoc.getRawEncoding(), FileChange(HashLoc, Imported)));
assert(p.second && "Unexpected revisitation of the same include directive"); assert(p.second && "Unexpected revisitation of the same include directive");
if (!Imported)
LastInsertedFileChange = p.first; LastInsertedFileChange = p.first;
} }
@ -289,24 +298,24 @@ bool InclusionRewriter::Process(FileID FileId,
case tok::pp_import: { case tok::pp_import: {
CommentOutDirective(RawLex, HashToken, FromFile, EOL, NextToWrite, CommentOutDirective(RawLex, HashToken, FromFile, EOL, NextToWrite,
Line); Line);
StringRef LineInfoExtra;
if (const FileChange *Change = FindFileChangeLocation( if (const FileChange *Change = FindFileChangeLocation(
HashToken.getLocation())) { HashToken.getLocation())) {
// now include and recursively process the file if (Change->Mod) {
if (Process(Change->Id, Change->FileType)) { WriteImplicitModuleImport(Change->Mod, EOL);
// else now include and recursively process the file
} else if (Process(Change->Id, Change->FileType)) {
// and set lineinfo back to this file, if the nested one was // and set lineinfo back to this file, if the nested one was
// actually included // actually included
// `2' indicates returning to a file (after having included // `2' indicates returning to a file (after having included
// another file. // another file.
WriteLineInfo(FileName, Line, FileType, EOL, " 2"); LineInfoExtra = " 2";
} else { }
// fix up lineinfo (since commented out directive changed line
// numbers).
WriteLineInfo(FileName, Line, FileType, EOL);
} }
} else
// fix up lineinfo (since commented out directive changed line // fix up lineinfo (since commented out directive changed line
// numbers) for inclusions that were skipped due to header guards // numbers) for inclusions that were skipped due to header guards
WriteLineInfo(FileName, Line, FileType, EOL); WriteLineInfo(FileName, Line, FileType, EOL, LineInfoExtra);
break; break;
} }
case tok::pp_pragma: { case tok::pp_pragma: {

View File

@ -0,0 +1,20 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -x objective-c %s -F %S/../Modules/Inputs -E -frewrite-includes -o - | FileCheck %s
int bar();
#include <Module/Module.h>
int foo();
#include <Module/Module.h>
// CHECK: int bar();{{$}}
// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}}
// CHECK-NEXT: #include <Module/Module.h>{{$}}
// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}}
// CHECK-NEXT: @import Module; /* clang -frewrite-includes: implicit import */{{$}}
// CHECK-NEXT: # 6 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}
// CHECK-NEXT: int foo();{{$}}
// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}}
// CHECK-NEXT: #include <Module/Module.h>{{$}}
// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}}
// CHECK-NEXT: @import Module; /* clang -frewrite-includes: implicit import */{{$}}
// CHECK-NEXT: # 8 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}