]> granicus.if.org Git - clang/commitdiff
Push the rewriter forward a bit more. Now it rewrites
authorChris Lattner <sabre@nondot.org>
Tue, 16 Oct 2007 21:07:07 +0000 (21:07 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 16 Oct 2007 21:07:07 +0000 (21:07 +0000)
#import to #include's as a test.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43041 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/RewriteTest.cpp
Rewrite/Rewriter.cpp
clang.xcodeproj/project.pbxproj
include/clang/Basic/SourceLocation.h
include/clang/Rewrite/Rewriter.h

index 103610248ad07cf08c9ace3014fba782ed312d6b..5b27f55190f6076075128c38ed08b002b6eaea05 100644 (file)
@@ -21,17 +21,22 @@ using namespace clang;
 
 namespace {
   class RewriteTest : public ASTConsumer {
+    Rewriter Rewrite;
     SourceManager *SM;
     unsigned MainFileID;
+    SourceLocation LastIncLoc;
   public:
     void Initialize(ASTContext &Context, unsigned mainFileID) {
       SM = &Context.SourceMgr;
       MainFileID = mainFileID;
+      Rewrite.setSourceMgr(Context.SourceMgr);
     }
     
     virtual void HandleTopLevelDecl(Decl *D);
 
-    
+    void HandleDeclInMainFile(Decl *D);
+    void RewriteInclude(SourceLocation Loc);
+
     ~RewriteTest();
   };
 }
@@ -39,19 +44,53 @@ namespace {
 ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
 
 void RewriteTest::HandleTopLevelDecl(Decl *D) {
-  // Nothing to do here yet.
-#if 0
-  if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
-    if (ND->getName())
-      printf("%s\n", ND->getName());
-#endif
+  // Two cases: either the decl could be in the main file, or it could be in a
+  // #included file.  If the former, rewrite it now.  If the later, check to see
+  // if we rewrote the #include/#import.
+  SourceLocation Loc = D->getLocation();
+  Loc = SM->getLogicalLoc(Loc);
+  
+  // 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() {
-  Rewriter Rewrite(*SM);
-  
   // Get the top-level buffer that this corresponds to.
   std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
   const char *MainBufStart = MainBuf.first;
index 5f935c328113d417327f318f7029066383f646b7..3c618de585b30c3cc6fbe4e7a72e51642f3d3c0f 100644 (file)
@@ -143,7 +143,7 @@ void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
 
 unsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc,
                                               unsigned &FileID) const {
-  std::pair<unsigned,unsigned> V = SourceMgr.getDecomposedFileLoc(Loc);
+  std::pair<unsigned,unsigned> V = SourceMgr->getDecomposedFileLoc(Loc);
   FileID = V.first;
   return V.second;
 }
@@ -158,7 +158,7 @@ RewriteBuffer &Rewriter::getEditBuffer(unsigned FileID) {
     return I->second;
   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);
   
   return I->second;
index 75d938806b0068e9faf478a9935977559b88f772..33627a1f29daae1f318dd95b4da2b914de67e111 100644 (file)
                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>"; };
                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>"; };
                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>"; };
index 420d5012f0c7d6b7ca112a2d3304e131e947287a..1ebb0ff3f8592f219f69ce1fef0e5bf151e7a4e1 100644 (file)
@@ -30,7 +30,9 @@ public:
     
     MacroIDBits       = 20,
     MacroPhysOffsBits = 9,
-    MacroLogOffBits   = 2
+    MacroLogOffBits   = 2,
+    
+    ChunkSize = (1 << FilePosBits)
   };
 
   SourceLocation() : ID(0) {}  // 0 is an invalid FileID.
@@ -42,9 +44,9 @@ public:
     SourceLocation L;
     // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
     // enough consequtive FileIDs that we have one for each chunk.
-    if (FilePos >= (1 << FilePosBits)) {
+    if (FilePos >= ChunkSize) {
       FileID += FilePos >> FilePosBits;
-      FilePos &= (1 << FilePosBits)-1;
+      FilePos &= ChunkSize-1;
     }
     
     // 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.
   unsigned getRawFilePos() const { 
     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 {
@@ -122,7 +124,14 @@ public:
   /// getFileLocWithOffset - Return a source location with the specified offset
   /// from this file SourceLocation.
   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
index 24c7f1c8f3dbb605cc71b7782fbba066bcccb17d..6e8c2084c64f32bd60beb5fbc3846d51ce2893d2 100644 (file)
@@ -107,11 +107,14 @@ private:  // Methods only usable by Rewriter.
 /// job is to dispatch high-level requests to the low-level RewriteBuffers that
 /// are involved.
 class Rewriter {
-  SourceManager &SourceMgr;
+  SourceManager *SourceMgr;
   
   std::map<unsigned, RewriteBuffer> RewriteBuffers;
 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
   /// is rewritable.  Locations from macros, etc are not rewritable.