Push the rewriter forward a bit more. Now it rewrites
#import to #include's as a test. llvm-svn: 43041
This commit is contained in:
parent
9a36bb84ea
commit
0bd1c97293
|
@ -21,17 +21,22 @@ using namespace clang;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class RewriteTest : public ASTConsumer {
|
class RewriteTest : public ASTConsumer {
|
||||||
|
Rewriter Rewrite;
|
||||||
SourceManager *SM;
|
SourceManager *SM;
|
||||||
unsigned MainFileID;
|
unsigned MainFileID;
|
||||||
|
SourceLocation LastIncLoc;
|
||||||
public:
|
public:
|
||||||
void Initialize(ASTContext &Context, unsigned mainFileID) {
|
void Initialize(ASTContext &Context, unsigned mainFileID) {
|
||||||
SM = &Context.SourceMgr;
|
SM = &Context.SourceMgr;
|
||||||
MainFileID = mainFileID;
|
MainFileID = mainFileID;
|
||||||
|
Rewrite.setSourceMgr(Context.SourceMgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void HandleTopLevelDecl(Decl *D);
|
virtual void HandleTopLevelDecl(Decl *D);
|
||||||
|
|
||||||
|
void HandleDeclInMainFile(Decl *D);
|
||||||
|
void RewriteInclude(SourceLocation Loc);
|
||||||
|
|
||||||
~RewriteTest();
|
~RewriteTest();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -39,19 +44,53 @@ namespace {
|
||||||
ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
|
ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
|
||||||
|
|
||||||
void RewriteTest::HandleTopLevelDecl(Decl *D) {
|
void RewriteTest::HandleTopLevelDecl(Decl *D) {
|
||||||
// Nothing to do here yet.
|
// Two cases: either the decl could be in the main file, or it could be in a
|
||||||
#if 0
|
// #included file. If the former, rewrite it now. If the later, check to see
|
||||||
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
|
// if we rewrote the #include/#import.
|
||||||
if (ND->getName())
|
SourceLocation Loc = D->getLocation();
|
||||||
printf("%s\n", ND->getName());
|
Loc = SM->getLogicalLoc(Loc);
|
||||||
#endif
|
|
||||||
|
// If this is for a builtin, ignore it.
|
||||||
|
if (Loc.isInvalid()) return;
|
||||||
|
|
||||||
|
if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
|
||||||
|
return HandleDeclInMainFile(D);
|
||||||
|
|
||||||
|
RewriteInclude(Loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RewriteTest::RewriteInclude(SourceLocation Loc) {
|
||||||
|
// Rip up the #include stack to the main file.
|
||||||
|
SourceLocation IncLoc = Loc, NextLoc = Loc;
|
||||||
|
do {
|
||||||
|
IncLoc = Loc;
|
||||||
|
Loc = SM->getLogicalLoc(NextLoc);
|
||||||
|
NextLoc = SM->getIncludeLoc(Loc);
|
||||||
|
} while (!NextLoc.isInvalid());
|
||||||
|
|
||||||
|
// Loc is now the location of the #include filename "foo" or <foo/bar.h>.
|
||||||
|
// IncLoc indicates the header that was included if it is useful.
|
||||||
|
IncLoc = SM->getLogicalLoc(IncLoc);
|
||||||
|
if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
|
||||||
|
Loc == LastIncLoc)
|
||||||
|
return;
|
||||||
|
LastIncLoc = Loc;
|
||||||
|
|
||||||
|
unsigned IncCol = SM->getColumnNumber(Loc);
|
||||||
|
SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
|
||||||
|
|
||||||
|
// Replace the #import with #include.
|
||||||
|
Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// HandleDeclInMainFile - This is called for each top-level decl defined in the
|
||||||
|
/// main file of the input.
|
||||||
|
void RewriteTest::HandleDeclInMainFile(Decl *D) {
|
||||||
|
// Nothing yet.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RewriteTest::~RewriteTest() {
|
RewriteTest::~RewriteTest() {
|
||||||
Rewriter Rewrite(*SM);
|
|
||||||
|
|
||||||
// Get the top-level buffer that this corresponds to.
|
// Get the top-level buffer that this corresponds to.
|
||||||
std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
|
std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
|
||||||
const char *MainBufStart = MainBuf.first;
|
const char *MainBufStart = MainBuf.first;
|
||||||
|
|
|
@ -143,7 +143,7 @@ void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
|
||||||
|
|
||||||
unsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc,
|
unsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc,
|
||||||
unsigned &FileID) const {
|
unsigned &FileID) const {
|
||||||
std::pair<unsigned,unsigned> V = SourceMgr.getDecomposedFileLoc(Loc);
|
std::pair<unsigned,unsigned> V = SourceMgr->getDecomposedFileLoc(Loc);
|
||||||
FileID = V.first;
|
FileID = V.first;
|
||||||
return V.second;
|
return V.second;
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ RewriteBuffer &Rewriter::getEditBuffer(unsigned FileID) {
|
||||||
return I->second;
|
return I->second;
|
||||||
I = RewriteBuffers.insert(I, std::make_pair(FileID, RewriteBuffer()));
|
I = RewriteBuffers.insert(I, std::make_pair(FileID, RewriteBuffer()));
|
||||||
|
|
||||||
std::pair<const char*, const char*> MB = SourceMgr.getBufferData(FileID);
|
std::pair<const char*, const char*> MB = SourceMgr->getBufferData(FileID);
|
||||||
I->second.Initialize(MB.first, MB.second);
|
I->second.Initialize(MB.first, MB.second);
|
||||||
|
|
||||||
return I->second;
|
return I->second;
|
||||||
|
|
|
@ -238,7 +238,7 @@
|
||||||
84AF36A00CB17A3B00C820A5 /* DeclObjC.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DeclObjC.h; path = clang/AST/DeclObjC.h; sourceTree = "<group>"; };
|
84AF36A00CB17A3B00C820A5 /* DeclObjC.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DeclObjC.h; path = clang/AST/DeclObjC.h; sourceTree = "<group>"; };
|
||||||
84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; };
|
84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; };
|
||||||
84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; };
|
84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; };
|
||||||
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
|
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
|
DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
|
||||||
DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; };
|
DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; };
|
||||||
DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
|
DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
|
||||||
|
|
|
@ -30,7 +30,9 @@ public:
|
||||||
|
|
||||||
MacroIDBits = 20,
|
MacroIDBits = 20,
|
||||||
MacroPhysOffsBits = 9,
|
MacroPhysOffsBits = 9,
|
||||||
MacroLogOffBits = 2
|
MacroLogOffBits = 2,
|
||||||
|
|
||||||
|
ChunkSize = (1 << FilePosBits)
|
||||||
};
|
};
|
||||||
|
|
||||||
SourceLocation() : ID(0) {} // 0 is an invalid FileID.
|
SourceLocation() : ID(0) {} // 0 is an invalid FileID.
|
||||||
|
@ -42,9 +44,9 @@ public:
|
||||||
SourceLocation L;
|
SourceLocation L;
|
||||||
// If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
|
// If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
|
||||||
// enough consequtive FileIDs that we have one for each chunk.
|
// enough consequtive FileIDs that we have one for each chunk.
|
||||||
if (FilePos >= (1 << FilePosBits)) {
|
if (FilePos >= ChunkSize) {
|
||||||
FileID += FilePos >> FilePosBits;
|
FileID += FilePos >> FilePosBits;
|
||||||
FilePos &= (1 << FilePosBits)-1;
|
FilePos &= ChunkSize-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Find a way to handle out of FileID bits! Maybe MaxFileID is an
|
// FIXME: Find a way to handle out of FileID bits! Maybe MaxFileID is an
|
||||||
|
@ -98,7 +100,7 @@ public:
|
||||||
/// SourceManager::getFilePos. This method will be incorrect for large files.
|
/// SourceManager::getFilePos. This method will be incorrect for large files.
|
||||||
unsigned getRawFilePos() const {
|
unsigned getRawFilePos() const {
|
||||||
assert(isFileID() && "can't get the file id of a non-file sloc!");
|
assert(isFileID() && "can't get the file id of a non-file sloc!");
|
||||||
return ID & ((1 << FilePosBits)-1);
|
return ID & (ChunkSize-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getMacroID() const {
|
unsigned getMacroID() const {
|
||||||
|
@ -122,7 +124,14 @@ public:
|
||||||
/// getFileLocWithOffset - Return a source location with the specified offset
|
/// getFileLocWithOffset - Return a source location with the specified offset
|
||||||
/// from this file SourceLocation.
|
/// from this file SourceLocation.
|
||||||
SourceLocation getFileLocWithOffset(int Offset) const {
|
SourceLocation getFileLocWithOffset(int Offset) const {
|
||||||
return getFileLoc(getFileID(), getRawFilePos()+Offset);
|
unsigned FileID = getFileID();
|
||||||
|
Offset += getRawFilePos();
|
||||||
|
// Handle negative offsets correctly.
|
||||||
|
while (Offset < 0) {
|
||||||
|
--FileID;
|
||||||
|
Offset += ChunkSize;
|
||||||
|
}
|
||||||
|
return getFileLoc(FileID, Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getRawEncoding - When a SourceLocation itself cannot be used, this returns
|
/// getRawEncoding - When a SourceLocation itself cannot be used, this returns
|
||||||
|
|
|
@ -107,11 +107,14 @@ private: // Methods only usable by Rewriter.
|
||||||
/// job is to dispatch high-level requests to the low-level RewriteBuffers that
|
/// job is to dispatch high-level requests to the low-level RewriteBuffers that
|
||||||
/// are involved.
|
/// are involved.
|
||||||
class Rewriter {
|
class Rewriter {
|
||||||
SourceManager &SourceMgr;
|
SourceManager *SourceMgr;
|
||||||
|
|
||||||
std::map<unsigned, RewriteBuffer> RewriteBuffers;
|
std::map<unsigned, RewriteBuffer> RewriteBuffers;
|
||||||
public:
|
public:
|
||||||
explicit Rewriter(SourceManager &SM) : SourceMgr(SM) {}
|
explicit Rewriter(SourceManager &SM) : SourceMgr(&SM) {}
|
||||||
|
explicit Rewriter() : SourceMgr(0) {}
|
||||||
|
|
||||||
|
void setSourceMgr(SourceManager &SM) { SourceMgr = &SM; }
|
||||||
|
|
||||||
/// isRewritable - Return true if this location is a raw file location, which
|
/// isRewritable - Return true if this location is a raw file location, which
|
||||||
/// is rewritable. Locations from macros, etc are not rewritable.
|
/// is rewritable. Locations from macros, etc are not rewritable.
|
||||||
|
|
Loading…
Reference in New Issue