[cfe-commits] r68758 - in /cfe/trunk: include/clang/Basic/SourceManager.h include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h include/clang/Frontend/PCHWriter.h include/clang/Lex/Preprocessor.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp lib/Lex/Preprocessor.cpp test/PCH/variables.c test/PCH/variables.h tools/clang-cc/clang-cc.cpp

Douglas Gregor dgregor at apple.com
Thu Apr 9 20:52:48 PDT 2009


Author: dgregor
Date: Thu Apr  9 22:52:48 2009
New Revision: 68758

URL: http://llvm.org/viewvc/llvm-project?rev=68758&view=rev
Log:
PCH serialization/deserialization of the source manager. With this
improvement, source locations read from the PCH file will properly
resolve to the source files that were used to build the PCH file
itself.

Once we have the preprocessor state stored in the PCH file, source
locations that refer to macro instantiations that occur in the PCH
file should have the appropriate instantiation information.


Modified:
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/include/clang/Frontend/PCHWriter.h
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Lex/Preprocessor.cpp
    cfe/trunk/test/PCH/variables.c
    cfe/trunk/test/PCH/variables.h
    cfe/trunk/tools/clang-cc/clang-cc.cpp

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Thu Apr  9 22:52:48 2009
@@ -183,7 +183,7 @@
     unsigned SpellingLoc;
     
     /// InstantiationLocStart/InstantiationLocEnd - In a macro expansion, these
-    /// indicate the start and end of the instantiation.  In object-line macros,
+    /// indicate the start and end of the instantiation.  In object-like macros,
     /// these will be the same.  In a function-like macro instantiation, the
     /// start will be the identifier and the end will be the ')'.
     unsigned InstantiationLocStart, InstantiationLocEnd;
@@ -610,7 +610,20 @@
   /// Read - Reconstitute a SourceManager from Bitcode.
   static SourceManager* CreateAndRegister(llvm::Deserializer& S,
                                           FileManager &FMgr);
-  
+
+  // Iteration over the source location entry table.  
+  typedef std::vector<SrcMgr::SLocEntry>::const_iterator sloc_entry_iterator;
+
+  sloc_entry_iterator sloc_entry_begin() const { 
+    return SLocEntryTable.begin(); 
+  }
+
+  sloc_entry_iterator sloc_entry_end() const { 
+    return SLocEntryTable.end(); 
+  }
+
+  unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
+
 private:
   friend class SrcMgr::ContentCache; // Used for deserialization.
   

Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Thu Apr  9 22:52:48 2009
@@ -31,7 +31,19 @@
       /// \brief The PCH block, which acts as a container around the
       /// full PCH block.
       PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
-      
+
+      /// \brief The block containing information about the language
+      /// options used to build this precompiled header.
+      LANGUAGE_OPTIONS_BLOCK_ID,
+
+      /// \brief The block containing information about the source
+      /// manager.
+      SOURCE_MANAGER_BLOCK_ID,
+
+      /// \brief The block containing information about the
+      /// preprocessor.
+      PREPROCESSOR_BLOCK_ID,
+
       /// \brief The block containing the definitions of all of the
       /// types used within the PCH file.
       TYPES_BLOCK_ID,
@@ -55,6 +67,30 @@
       DECL_OFFSETS_BLOCK_ID
     };
 
+    /// \brief Record types used within a source manager block.
+    enum SourceManagerRecordTypes {
+      /// \brief Describes a source location entry (SLocEntry) for a
+      /// file.
+      SM_SLOC_FILE_ENTRY = 1,
+      /// \brief Describes a source location entry (SLocEntry) for a
+      /// buffer.
+      SM_SLOC_BUFFER_ENTRY = 2,
+      /// \brief Describes a blob that contains the data for a buffer
+      /// entry. This kind of record always directly follows a
+      /// SM_SLOC_BUFFER_ENTRY record.
+      SM_SLOC_BUFFER_BLOB = 3,
+      /// \brief Describes a source location entry (SLocEntry) for a
+      /// macro instantiation.
+      SM_SLOC_INSTANTIATION_ENTRY = 4
+    };
+
+    /// \defgroup PCHAST Precompiled header AST constants
+    ///
+    /// The constants in this group describe various components of the
+    /// abstract syntax tree within a precompiled header.
+    ///
+    /// @{
+
     /// \brief Predefined type IDs.
     ///
     /// These type IDs correspond to predefined types in the AST
@@ -233,6 +269,8 @@
     enum DeclOffsetCode {
       DECL_OFFSET = 1
     };
+
+    /// @}
   }
 } // end namespace clang
 

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Thu Apr  9 22:52:48 2009
@@ -34,6 +34,7 @@
 class ASTContext;
 class Decl;
 class DeclContext;
+class Preprocessor;
 
 /// \brief Reads a precompiled head containing the contents of a
 /// translation unit.
@@ -48,6 +49,9 @@
 /// required when traversing the AST. Only those AST nodes that are
 /// actually required will be de-serialized.
 class PCHReader : public ExternalASTSource {
+  /// \brief The preprocessor that will be loading the source file.
+  Preprocessor &PP;
+
   /// \brief The AST context into which we'll read the PCH file.
   ASTContext &Context;
 
@@ -95,6 +99,7 @@
   DeclContextOffsetsMap DeclContextOffsets;
 
   bool ReadPCHBlock();
+  bool ReadSourceManagerBlock();
   bool ReadTypeOffsets();
   bool ReadDeclOffsets();
 
@@ -108,7 +113,9 @@
 public:
   typedef llvm::SmallVector<uint64_t, 64> RecordData;
 
-  PCHReader(ASTContext &Context) : Context(Context), Buffer() { }
+  PCHReader(Preprocessor &PP, ASTContext &Context) 
+    : PP(PP), Context(Context), Buffer() { }
+
   ~PCHReader();
 
   bool ReadPCH(const std::string &FileName);

Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Thu Apr  9 22:52:48 2009
@@ -30,6 +30,7 @@
 namespace clang {
 
 class ASTContext;
+class SourceManager;
 
 /// \brief Writes a precompiled header containing the contents of a
 /// translation unit.
@@ -74,6 +75,7 @@
   /// \brief The type ID that will be assigned to the next new type.
   unsigned NextTypeID;
 
+  void WriteSourceManagerBlock(SourceManager &SourceMgr);
   void WriteType(const Type *T);
   void WriteTypesBlock(ASTContext &Context);
   uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Thu Apr  9 22:52:48 2009
@@ -782,6 +782,7 @@
 public:
   virtual ~PreprocessorFactory();
   virtual Preprocessor* CreatePreprocessor() = 0;  
+  virtual bool FinishInitialization(Preprocessor *PP);
 };
   
 }  // end namespace clang

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Thu Apr  9 22:52:48 2009
@@ -15,6 +15,9 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Type.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
 #include "llvm/Bitcode/BitstreamReader.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -111,6 +114,84 @@
   return true;
 }
 
+/// \brief Read the source manager block
+bool PCHReader::ReadSourceManagerBlock() {
+  using namespace SrcMgr;
+  if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID))
+    return Error("Malformed source manager block record");
+
+  SourceManager &SourceMgr = Context.getSourceManager();
+  RecordData Record;
+  while (true) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of Source Manager block");
+      return false;
+    }
+    
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    }
+    
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+    
+    // Read a record.
+    const char *BlobStart;
+    unsigned BlobLen;
+    Record.clear();
+    switch (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+    default:  // Default behavior: ignore.
+      break;
+
+    case pch::SM_SLOC_FILE_ENTRY: {
+      // FIXME: We would really like to delay the creation of this
+      // FileEntry until it is actually required, e.g., when producing
+      // a diagnostic with a source location in this file.
+      const FileEntry *File 
+        = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
+      // FIXME: Error recovery if file cannot be found.
+      SourceMgr.createFileID(File,
+                             SourceLocation::getFromRawEncoding(Record[1]),
+                             (CharacteristicKind)Record[2]);
+      break;
+    }
+
+    case pch::SM_SLOC_BUFFER_ENTRY: {
+      const char *Name = BlobStart;
+      unsigned Code = Stream.ReadCode();
+      Record.clear();
+      unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+      assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
+      SourceMgr.createFileIDForMemBuffer(
+          llvm::MemoryBuffer::getMemBuffer(BlobStart, BlobStart + BlobLen - 1,
+                                           Name));
+      break;
+    }
+
+    case pch::SM_SLOC_INSTANTIATION_ENTRY: {
+      SourceLocation SpellingLoc 
+        = SourceLocation::getFromRawEncoding(Record[1]);
+      SourceMgr.createInstantiationLoc(
+                              SpellingLoc,
+                              SourceLocation::getFromRawEncoding(Record[2]),
+                              SourceLocation::getFromRawEncoding(Record[3]),
+                              Lexer::MeasureTokenLength(SpellingLoc, 
+                                                        SourceMgr));
+      break;
+    }
+
+    }
+  }
+}
+
 /// \brief Read the type-offsets block.
 bool PCHReader::ReadTypeOffsets() {
   if (Stream.EnterSubBlock(pch::TYPE_OFFSETS_BLOCK_ID))
@@ -217,6 +298,10 @@
           return Error("Malformed block record");
         break;
 
+      case pch::SOURCE_MANAGER_BLOCK_ID:
+        if (ReadSourceManagerBlock())
+          return Error("Malformed source manager block");
+        break;
 
       case pch::TYPE_OFFSETS_BLOCK_ID:
         if (ReadTypeOffsets())

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Thu Apr  9 22:52:48 2009
@@ -17,8 +17,11 @@
 #include "clang/AST/DeclContextInternals.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/AST/Type.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
 #include "llvm/Bitcode/BitstreamWriter.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemoryBuffer.h"
 
 using namespace clang;
 
@@ -323,6 +326,154 @@
 // PCHWriter Implementation
 //===----------------------------------------------------------------------===//
 
+//===----------------------------------------------------------------------===//
+// Source Manager Serialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// file.
+static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &S) {
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
+  // FIXME: Need an actual encoding for the line directives; maybe
+  // this should be an array?
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
+  return S.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// buffer.
+static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &S) {
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
+  return S.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// buffer's blob.
+static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &S) {
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
+  return S.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to an
+/// buffer.
+static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &S) {
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
+  return S.EmitAbbrev(Abbrev);
+}
+
+/// \brief Writes the block containing the serialized form of the
+/// source manager.
+///
+/// TODO: We should probably use an on-disk hash table (stored in a
+/// blob), indexed based on the file name, so that we only create
+/// entries for files that we actually need. In the common case (no
+/// errors), we probably won't have to create file entries for any of
+/// the files in the AST.
+void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) {
+  // Enter the types block
+  S.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3);
+
+  // Abbreviations for the various kinds of source-location entries.
+  int SLocFileAbbrv = -1;
+  int SLocBufferAbbrv = -1;
+  int SLocBufferBlobAbbrv = -1;
+  int SLocInstantiationAbbrv = -1;
+
+  // Write out the source location entry table. We skip the first
+  // entry, which is always the same dummy entry.
+  RecordData Record;
+  for (SourceManager::sloc_entry_iterator 
+         SLoc = SourceMgr.sloc_entry_begin() + 1,
+         SLocEnd = SourceMgr.sloc_entry_end();
+       SLoc != SLocEnd; ++SLoc) {
+    // Figure out which record code to use.
+    unsigned Code;
+    if (SLoc->isFile()) {
+      if (SLoc->getFile().getContentCache()->Entry)
+        Code = pch::SM_SLOC_FILE_ENTRY;
+      else
+        Code = pch::SM_SLOC_BUFFER_ENTRY;
+    } else
+      Code = pch::SM_SLOC_INSTANTIATION_ENTRY;
+    Record.push_back(Code);
+
+    Record.push_back(SLoc->getOffset());
+    if (SLoc->isFile()) {
+      const SrcMgr::FileInfo &File = SLoc->getFile();
+      Record.push_back(File.getIncludeLoc().getRawEncoding());
+      Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
+      Record.push_back(File.hasLineDirectives()); // FIXME: encode the
+                                                  // line directives?
+
+      const SrcMgr::ContentCache *Content = File.getContentCache();
+      if (Content->Entry) {
+        // The source location entry is a file. The blob associated
+        // with this entry is the file name.
+        if (SLocFileAbbrv == -1)
+          SLocFileAbbrv = CreateSLocFileAbbrev(S);
+        S.EmitRecordWithBlob(SLocFileAbbrv, Record,
+                             Content->Entry->getName(),
+                             strlen(Content->Entry->getName()));
+      } else {
+        // The source location entry is a buffer. The blob associated
+        // with this entry contains the contents of the buffer.
+        if (SLocBufferAbbrv == -1) {
+          SLocBufferAbbrv = CreateSLocBufferAbbrev(S);
+          SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(S);
+        }
+
+        // We add one to the size so that we capture the trailing NULL
+        // that is required by llvm::MemoryBuffer::getMemBuffer (on
+        // the reader side).
+        const llvm::MemoryBuffer *Buffer = Content->getBuffer();
+        const char *Name = Buffer->getBufferIdentifier();
+        S.EmitRecordWithBlob(SLocBufferAbbrv, Record, Name, strlen(Name) + 1);
+        Record.clear();
+        Record.push_back(pch::SM_SLOC_BUFFER_BLOB);
+        S.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
+                             Buffer->getBufferStart(),
+                             Buffer->getBufferSize() + 1);
+      }
+    } else {
+      // The source location entry is an instantiation.
+      const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation();
+      Record.push_back(Inst.getSpellingLoc().getRawEncoding());
+      Record.push_back(Inst.getInstantiationLocStart().getRawEncoding());
+      Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
+
+      if (SLocInstantiationAbbrv == -1)
+        SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(S);
+      S.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
+    }
+
+    Record.clear();
+  }
+
+  S.ExitBlock();
+}
+
 /// \brief Write the representation of a type to the PCH stream.
 void PCHWriter::WriteType(const Type *T) {
   pch::ID &ID = TypeIDs[T];
@@ -521,6 +672,7 @@
 
   // Write the remaining PCH contents.
   S.EnterSubblock(pch::PCH_BLOCK_ID, 2);
+  WriteSourceManagerBlock(Context.getSourceManager());
   WriteTypesBlock(Context);
   WriteDeclsBlock(Context);
   S.ExitBlock();

Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Thu Apr  9 22:52:48 2009
@@ -45,6 +45,10 @@
 
 PreprocessorFactory::~PreprocessorFactory() {}
 
+bool PreprocessorFactory::FinishInitialization(Preprocessor *PP) {
+  return false;
+}
+
 Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
                            TargetInfo &target, SourceManager &SM, 
                            HeaderSearch &Headers,

Modified: cfe/trunk/test/PCH/variables.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/variables.c?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/test/PCH/variables.c (original)
+++ cfe/trunk/test/PCH/variables.c Thu Apr  9 22:52:48 2009
@@ -3,4 +3,8 @@
 
 int *ip2 = &x;
 float *fp = &ip; // expected-warning{{incompatible pointer types}}
+// FIXME:variables.h expected-note{{previous}}
+double z; // expected-error{{redefinition}}
+
+//double VeryHappy; // FIXME: xpected-error{{redefinition}}
 

Modified: cfe/trunk/test/PCH/variables.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/variables.h?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/test/PCH/variables.h (original)
+++ cfe/trunk/test/PCH/variables.h Thu Apr  9 22:52:48 2009
@@ -1,5 +1,12 @@
 // RUN: clang-cc -emit-pch -o variables.h.pch variables.h
-extern int x;
+// Do not mess with the whitespace in this file. It's important.
 extern float y;
-extern int *ip;
+extern int *ip, x;
+
 float z;
+
+
+
+#define MAKE_HAPPY(X) X##Happy
+int MAKE_HAPPY(Very);
+

Modified: cfe/trunk/tools/clang-cc/clang-cc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/clang-cc.cpp?rev=68758&r1=68757&r2=68758&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/clang-cc.cpp (original)
+++ cfe/trunk/tools/clang-cc/clang-cc.cpp Thu Apr  9 22:52:48 2009
@@ -1379,22 +1379,26 @@
       PP->setPTHManager(PTHMgr.take());
     }
     
+    return PP.take();
+  }
+
+  virtual bool FinishInitialization(Preprocessor *PP) {
     if (InitializePreprocessor(*PP, InitializeSourceMgr, InFile)) {
-      return NULL;
+      return true;
     }
     
     /// FIXME: PP can only handle one callback
     if (ProgAction != PrintPreprocessedInput) {
       std::string ErrStr;
-      bool DFG = CreateDependencyFileGen(PP.get(), ErrStr);
+      bool DFG = CreateDependencyFileGen(PP, ErrStr);
       if (!DFG && !ErrStr.empty()) {
         fprintf(stderr, "%s", ErrStr.c_str());
-        return NULL;
+        return true;
       }
     }
 
     InitializeSourceMgr = false;
-    return PP.take();
+    return false;
   }
 };
 }
@@ -1697,13 +1701,20 @@
     if (!ImplicitIncludePCH.empty()) {
       // The user has asked us to include a precompiled header. Load
       // the precompiled header into the AST context.
-      llvm::OwningPtr<PCHReader> Reader(
-                                   new clang::PCHReader(*ContextOwner.get()));
+      llvm::OwningPtr<PCHReader> 
+        Reader(new clang::PCHReader(PP, *ContextOwner.get()));
       if (Reader->ReadPCH(ImplicitIncludePCH))
         return;
 
       llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
       ContextOwner->setExternalSource(Source);
+
+      // Finish preprocessor initialization. We do this now (rather
+      // than earlier) because this initialization creates new source
+      // location entries in the source manager, which must come after
+      // the source location entries for the PCH file.
+      if (PPF.FinishInitialization(&PP))
+        return;
     }
 
     ParseAST(PP, Consumer.get(), *ContextOwner.get(), Stats);
@@ -1912,6 +1923,10 @@
     if (!PP)
       continue;
 
+    if (ImplicitIncludePCH.empty()
+        && PPFactory.FinishInitialization(PP.get()))
+      continue;
+
     // Create the HTMLDiagnosticsClient if we are using one.  Otherwise,
     // always reset to using TextDiagClient.
     llvm::OwningPtr<DiagnosticClient> TmpClient;





More information about the cfe-commits mailing list