diff options
author | dim <dim@FreeBSD.org> | 2013-06-10 20:45:12 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-06-10 20:45:12 +0000 |
commit | ea266cad53e3d49771fa38103913d3ec7a166694 (patch) | |
tree | 8f7776b7310bebaf415ac5b69e46e9f928c37144 /lib/Rewrite/Frontend | |
parent | c72c57c9e9b69944e3e009cd5e209634839581d3 (diff) | |
download | FreeBSD-src-ea266cad53e3d49771fa38103913d3ec7a166694.zip FreeBSD-src-ea266cad53e3d49771fa38103913d3ec7a166694.tar.gz |
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3
release):
http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_33/final@183502
Diffstat (limited to 'lib/Rewrite/Frontend')
-rw-r--r-- | lib/Rewrite/Frontend/FixItRewriter.cpp | 5 | ||||
-rw-r--r-- | lib/Rewrite/Frontend/InclusionRewriter.cpp | 160 |
2 files changed, 146 insertions, 19 deletions
diff --git a/lib/Rewrite/Frontend/FixItRewriter.cpp b/lib/Rewrite/Frontend/FixItRewriter.cpp index a3bbdcf..166c607 100644 --- a/lib/Rewrite/Frontend/FixItRewriter.cpp +++ b/lib/Rewrite/Frontend/FixItRewriter.cpp @@ -197,9 +197,4 @@ void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) { Diags.setClient(this); } -DiagnosticConsumer *FixItRewriter::clone(DiagnosticsEngine &Diags) const { - return new FixItRewriter(Diags, Diags.getSourceManager(), - Rewrite.getLangOpts(), FixItOpts); -} - FixItOptions::~FixItOptions() {} diff --git a/lib/Rewrite/Frontend/InclusionRewriter.cpp b/lib/Rewrite/Frontend/InclusionRewriter.cpp index d95fb07..878be84 100644 --- a/lib/Rewrite/Frontend/InclusionRewriter.cpp +++ b/lib/Rewrite/Frontend/InclusionRewriter.cpp @@ -15,7 +15,9 @@ #include "clang/Rewrite/Frontend/Rewriters.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/PreprocessorOutputOptions.h" +#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -27,10 +29,11 @@ class InclusionRewriter : public PPCallbacks { /// Information about which #includes were actually performed, /// created by preprocessor callbacks. struct FileChange { + const Module *Mod; SourceLocation From; FileID Id; 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. @@ -65,6 +68,7 @@ private: void WriteLineInfo(const char *Filename, int Line, SrcMgr::CharacteristicKind FileType, StringRef EOL, StringRef Extra = StringRef()); + void WriteImplicitModuleImport(const Module *Mod, StringRef EOL); void OutputContentUpTo(const MemoryBuffer &FromFile, unsigned &WriteFrom, unsigned WriteTo, StringRef EOL, int &lines, @@ -72,6 +76,9 @@ private: void CommentOutDirective(Lexer &DirectivesLex, const Token &StartToken, const MemoryBuffer &FromFile, StringRef EOL, unsigned &NextToWrite, int &Lines); + bool HandleHasInclude(FileID FileId, Lexer &RawLex, + const DirectoryLookup *Lookup, Token &Tok, + bool &FileExists); const FileChange *FindFileChangeLocation(SourceLocation Loc) const; StringRef NextIdentifierName(Lexer &RawLex, Token &RawToken); }; @@ -117,6 +124,12 @@ void InclusionRewriter::WriteLineInfo(const char *Filename, int Line, 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 /// it invokes this handler. void InclusionRewriter::FileChanged(SourceLocation Loc, @@ -157,13 +170,14 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, const FileEntry * /*File*/, StringRef /*SearchPath*/, StringRef /*RelativePath*/, - const Module * /*Imported*/) { + const Module *Imported) { assert(LastInsertedFileChange == FileChanges.end() && "Another inclusion " "directive was found before the previous one was processed"); 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"); - LastInsertedFileChange = p.first; + if (!Imported) + LastInsertedFileChange = p.first; } /// Simple lookup for a SourceLocation (specifically one denoting the hash in @@ -245,6 +259,75 @@ StringRef InclusionRewriter::NextIdentifierName(Lexer &RawLex, return StringRef(); } +// Expand __has_include and __has_include_next if possible. If there's no +// definitive answer return false. +bool InclusionRewriter::HandleHasInclude( + FileID FileId, Lexer &RawLex, const DirectoryLookup *Lookup, Token &Tok, + bool &FileExists) { + // Lex the opening paren. + RawLex.LexFromRawLexer(Tok); + if (Tok.isNot(tok::l_paren)) + return false; + + RawLex.LexFromRawLexer(Tok); + + SmallString<128> FilenameBuffer; + StringRef Filename; + // Since the raw lexer doesn't give us angle_literals we have to parse them + // ourselves. + // FIXME: What to do if the file name is a macro? + if (Tok.is(tok::less)) { + RawLex.LexFromRawLexer(Tok); + + FilenameBuffer += '<'; + do { + if (Tok.is(tok::eod)) // Sanity check. + return false; + + if (Tok.is(tok::raw_identifier)) + PP.LookUpIdentifierInfo(Tok); + + // Get the string piece. + SmallVector<char, 128> TmpBuffer; + bool Invalid = false; + StringRef TmpName = PP.getSpelling(Tok, TmpBuffer, &Invalid); + if (Invalid) + return false; + + FilenameBuffer += TmpName; + + RawLex.LexFromRawLexer(Tok); + } while (Tok.isNot(tok::greater)); + + FilenameBuffer += '>'; + Filename = FilenameBuffer; + } else { + if (Tok.isNot(tok::string_literal)) + return false; + + bool Invalid = false; + Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid); + if (Invalid) + return false; + } + + // Lex the closing paren. + RawLex.LexFromRawLexer(Tok); + if (Tok.isNot(tok::r_paren)) + return false; + + // Now ask HeaderInfo if it knows about the header. + // FIXME: Subframeworks aren't handled here. Do we care? + bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename); + const DirectoryLookup *CurDir; + const FileEntry *File = PP.getHeaderSearchInfo().LookupFile( + Filename, isAngled, 0, CurDir, + PP.getSourceManager().getFileEntryForID(FileId), 0, 0, 0, false); + + FileExists = File != 0; + return true; +} + /// Use a raw lexer to analyze \p FileId, inccrementally copying parts of it /// and including content of included files recursively. bool InclusionRewriter::Process(FileID FileId, @@ -253,7 +336,7 @@ bool InclusionRewriter::Process(FileID FileId, bool Invalid; const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid); if (Invalid) // invalid inclusion - return true; + return false; const char *FileName = FromFile.getBufferIdentifier(); Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts()); RawLex.SetCommentRetentionState(false); @@ -264,7 +347,7 @@ bool InclusionRewriter::Process(FileID FileId, WriteLineInfo(FileName, 1, FileType, EOL, " 1"); if (SM.getFileIDSize(FileId) == 0) - return true; + return false; // The next byte to be copied from the source file unsigned NextToWrite = 0; @@ -282,26 +365,31 @@ bool InclusionRewriter::Process(FileID FileId, RawLex.LexFromRawLexer(RawToken); if (RawToken.is(tok::raw_identifier)) PP.LookUpIdentifierInfo(RawToken); - if (RawToken.is(tok::identifier)) { + if (RawToken.is(tok::identifier) || RawToken.is(tok::kw_if)) { switch (RawToken.getIdentifierInfo()->getPPKeywordID()) { case tok::pp_include: case tok::pp_include_next: case tok::pp_import: { CommentOutDirective(RawLex, HashToken, FromFile, EOL, NextToWrite, Line); + StringRef LineInfoExtra; if (const FileChange *Change = FindFileChangeLocation( HashToken.getLocation())) { - // now include and recursively process the file - if (Process(Change->Id, Change->FileType)) + if (Change->Mod) { + 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 // actually included // `2' indicates returning to a file (after having included // another file. - WriteLineInfo(FileName, Line, FileType, EOL, " 2"); - } else - // fix up lineinfo (since commented out directive changed line - // numbers) for inclusions that were skipped due to header guards - WriteLineInfo(FileName, Line, FileType, EOL); + LineInfoExtra = " 2"; + } + } + // fix up lineinfo (since commented out directive changed line + // numbers) for inclusions that were skipped due to header guards + WriteLineInfo(FileName, Line, FileType, EOL, LineInfoExtra); break; } case tok::pp_pragma: { @@ -323,6 +411,50 @@ bool InclusionRewriter::Process(FileID FileId, } break; } + case tok::pp_if: + case tok::pp_elif: + // Rewrite special builtin macros to avoid pulling in host details. + do { + // Walk over the directive. + RawLex.LexFromRawLexer(RawToken); + if (RawToken.is(tok::raw_identifier)) + PP.LookUpIdentifierInfo(RawToken); + + if (RawToken.is(tok::identifier)) { + bool HasFile; + SourceLocation Loc = RawToken.getLocation(); + + // Rewrite __has_include(x) + if (RawToken.getIdentifierInfo()->isStr("__has_include")) { + if (!HandleHasInclude(FileId, RawLex, 0, RawToken, HasFile)) + continue; + // Rewrite __has_include_next(x) + } else if (RawToken.getIdentifierInfo()->isStr( + "__has_include_next")) { + const DirectoryLookup *Lookup = PP.GetCurDirLookup(); + if (Lookup) + ++Lookup; + + if (!HandleHasInclude(FileId, RawLex, Lookup, RawToken, + HasFile)) + continue; + } else { + continue; + } + // Replace the macro with (0) or (1), followed by the commented + // out macro for reference. + OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(Loc), + EOL, Line); + OS << '(' << (int) HasFile << ")/*"; + OutputContentUpTo(FromFile, NextToWrite, + SM.getFileOffset(RawToken.getLocation()) + + RawToken.getLength(), + EOL, Line); + OS << "*/"; + } + } while (RawToken.isNot(tok::eod)); + + break; default: break; } |