]> granicus.if.org Git - clang/commitdiff
add support for reading macros. This does all the reading (with a bunch of
authorChris Lattner <sabre@nondot.org>
Fri, 10 Apr 2009 21:41:48 +0000 (21:41 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 10 Apr 2009 21:41:48 +0000 (21:41 +0000)
fixme's, e.g. for tokens with identifiers) but does not actually install
them.  Some details with the predefines buffer needs to be sorted out first.

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

include/clang/Frontend/PCHReader.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp

index 498d5fffeb2d8d73280ff6c4f408e1d360267f60..0c14df070e086d0415bc370992fe5f98d584a7dc 100644 (file)
@@ -107,6 +107,7 @@ class PCHReader : public ExternalASTSource {
 
   PCHReadResult ReadPCHBlock();
   bool ReadSourceManagerBlock();
+  bool ReadPreprocessorBlock();
 
   bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record);
   QualType ReadTypeRecord(uint64_t Offset);
index 9eb881ce0f44bf5d8750afe229cd960d0e225150..d5923086c7a0fc2dc25f46934eb4ded713c883d2 100644 (file)
@@ -15,6 +15,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Type.h"
+#include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/FileManager.h"
@@ -193,6 +194,115 @@ bool PCHReader::ReadSourceManagerBlock() {
   }
 }
 
+bool PCHReader::ReadPreprocessorBlock() {
+  if (Stream.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID))
+    return Error("Malformed preprocessor block record");
+  
+  std::string CurName; // FIXME: HACK.
+  RecordData Record;
+  llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
+  MacroInfo *LastMacro = 0;
+  
+  while (true) {
+    unsigned Code = Stream.ReadCode();
+    switch (Code) {
+    case llvm::bitc::END_BLOCK:
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of preprocessor block");
+      return false;
+    
+    case llvm::bitc::ENTER_SUBBLOCK:
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    
+    case llvm::bitc::DEFINE_ABBREV:
+      Stream.ReadAbbrevRecord();
+      continue;
+    default: break;
+    }
+    
+    // Read a record.
+    Record.clear();
+    pch::PreprocessorRecordTypes RecType =
+      (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
+    switch (RecType) {
+    default:  // Default behavior: ignore unknown records.
+      break;
+        
+    case pch::PP_MACRO_NAME:
+      // Set CurName.  FIXME: This is a hack and should be removed when we have
+      // identifier id's.
+      CurName.clear();
+      for (unsigned i = 0, e = Record.size(); i != e; ++i)
+        CurName += (char)Record[i];
+      break;
+        
+    case pch::PP_MACRO_OBJECT_LIKE:
+    case pch::PP_MACRO_FUNCTION_LIKE: {
+      unsigned IdentInfo = Record[0];
+      IdentInfo = IdentInfo; // FIXME: Decode into identifier info*.
+      assert(!CurName.empty());
+      IdentifierInfo *II = PP.getIdentifierInfo(CurName.c_str());
+      
+      SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
+      bool isUsed = Record[2];
+      
+      MacroInfo *MI = PP.AllocateMacroInfo(Loc);
+      MI->setIsUsed(isUsed);
+      
+      if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
+        // Decode function-like macro info.
+        bool isC99VarArgs = Record[3];
+        bool isGNUVarArgs = Record[4];
+        MacroArgs.clear();
+        unsigned NumArgs = Record[5];
+        for (unsigned i = 0; i != NumArgs; ++i)
+          ; // FIXME: Decode macro arg names: MacroArgs.push_back(Record[6+i]);
+
+        // Install function-like macro info.
+        MI->setIsFunctionLike();
+        if (isC99VarArgs) MI->setIsC99Varargs();
+        if (isGNUVarArgs) MI->setIsGNUVarargs();
+        MI->setArgumentList(&MacroArgs[0], MacroArgs.size(),
+                            PP.getPreprocessorAllocator());
+      }
+
+      // Finally, install the macro.
+      II = II;
+#if 0
+      // FIXME: Do this when predefines buffer is worked out.
+      PP.setMacroInfo(II, MI);
+#endif
+
+      // Remember that we saw this macro last so that we add the tokens that
+      // form its body to it.
+      LastMacro = MI;
+      break;
+    }
+        
+    case pch::PP_TOKEN: {
+      // If we see a TOKEN before a PP_MACRO_*, then the file is eroneous, just
+      // pretend we didn't see this.
+      if (LastMacro == 0) break;
+      
+      Token Tok;
+      Tok.startToken();
+      Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
+      Tok.setLength(Record[1]);
+      unsigned IdentInfo = Record[2];
+      IdentInfo = IdentInfo; // FIXME: Handle this right.
+      Tok.setKind((tok::TokenKind)Record[3]);
+      Tok.setFlag((Token::TokenFlags)Record[4]);
+      LastMacro->AddTokenToBody(Tok);
+      break;
+    }
+    }
+  }
+}
+
 PCHReader::PCHReadResult PCHReader::ReadPCHBlock() {
   if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
     Error("Malformed block record");
@@ -228,6 +338,13 @@ PCHReader::PCHReadResult PCHReader::ReadPCHBlock() {
           return Failure;
         }
         break;
+          
+      case pch::PREPROCESSOR_BLOCK_ID:
+        if (ReadPreprocessorBlock()) {
+          Error("Malformed preprocessor block");
+          return Failure;
+        }
+        break;
       }
       continue;
     }
index a31c0c79855af3ec9d79374f7653fabadda1ec6a..09080d640b5ea9361866057950cc5d1347249a15 100644 (file)
@@ -573,6 +573,8 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
   // macros.
   for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
        I != E; ++I) {
+    // FIXME: This emits macros in hash table order, we should do it in a stable
+    // order so that output is reproducible.
     MacroInfo *MI = I->second;
 
     // Don't emit builtin macros like __LINE__ to the PCH file unless they have