summaryrefslogtreecommitdiffstats
path: root/lib/Rewrite/Frontend
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
committerdim <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
commitea266cad53e3d49771fa38103913d3ec7a166694 (patch)
tree8f7776b7310bebaf415ac5b69e46e9f928c37144 /lib/Rewrite/Frontend
parentc72c57c9e9b69944e3e009cd5e209634839581d3 (diff)
downloadFreeBSD-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.cpp5
-rw-r--r--lib/Rewrite/Frontend/InclusionRewriter.cpp160
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;
}
OpenPOWER on IntegriCloud