[cfe-commits] r69075 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/Expr.h include/clang/AST/Stmt.h include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h include/clang/Frontend/PCHWriter.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp test/PCH/enum.h test/PCH/exprs.c test/PCH/exprs.h test/PCH/external-defs.c test/PCH/external-defs.h test/PCH/struct.c test/PCH/struct.h test/PCH/types.c test/PCH/types.h test/PCH/variables.c test/PCH/variables.h

Douglas Gregor dgregor at apple.com
Tue Apr 14 14:18:51 PDT 2009


Author: dgregor
Date: Tue Apr 14 16:18:50 2009
New Revision: 69075

URL: http://llvm.org/viewvc/llvm-project?rev=69075&view=rev
Log:
PCH support for a few very, very simple kinds of expressions. Hook up
expression (de-)serialization for VLAs, variable initializers,
enum constant initializers, and bitfield widths.


Added:
    cfe/trunk/test/PCH/exprs.c
    cfe/trunk/test/PCH/exprs.h
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/include/clang/Frontend/PCHWriter.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/test/PCH/enum.h
    cfe/trunk/test/PCH/external-defs.c
    cfe/trunk/test/PCH/external-defs.h
    cfe/trunk/test/PCH/struct.c
    cfe/trunk/test/PCH/struct.h
    cfe/trunk/test/PCH/types.c
    cfe/trunk/test/PCH/types.h
    cfe/trunk/test/PCH/variables.c
    cfe/trunk/test/PCH/variables.h

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=69075&r1=69074&r2=69075&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Apr 14 16:18:50 2009
@@ -807,6 +807,8 @@
   bool isAnonymousStructOrUnion() const;
 
   Expr *getBitWidth() const { return BitWidth; }
+  void setBitWidth(Expr *BW) { BitWidth = BW; }
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
     return D->getKind() >= FieldFirst && D->getKind() <= FieldLast;

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=69075&r1=69074&r2=69075&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Apr 14 16:18:50 2009
@@ -63,6 +63,9 @@
     setType(T);
   }
 
+  /// \brief Construct an empty expression.
+  explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
+
 public:  
   QualType getType() const { return TR; }
   void setType(QualType t) { 
@@ -88,6 +91,9 @@
   /// @endcode
   bool isValueDependent() const { return ValueDependent; }
 
+  /// \brief Set whether this expression is value-dependent or not.
+  void setValueDependent(bool VD) { ValueDependent = VD; }
+
   /// isTypeDependent - Determines whether this expression is
   /// type-dependent (C++ [temp.dep.expr]), which means that its type
   /// could change from one template instantiation to the next. For
@@ -101,6 +107,9 @@
   /// @endcode
   bool isTypeDependent() const { return TypeDependent; }
 
+  /// \brief Set whether this expression is type-dependent or not.
+  void setTypeDependent(bool TD) { TypeDependent = TD; }
+
   /// SourceLocation tokens are not useful in isolation - they are low level
   /// value objects created/interpreted by SourceManager. We assume AST
   /// clients will have a pointer to the respective SourceManager.
@@ -315,11 +324,16 @@
   DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) : 
     Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {}
   
+  /// \brief Construct an empty declaration reference expression.
+  explicit DeclRefExpr(EmptyShell Empty) 
+    : Expr(DeclRefExprClass, Empty) { }
+
   NamedDecl *getDecl() { return D; }
   const NamedDecl *getDecl() const { return D; }
   void setDecl(NamedDecl *NewD) { D = NewD; }
 
   SourceLocation getLocation() const { return Loc; }
+  void setLocation(SourceLocation L) { Loc = L; }
   virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
   
   static bool classof(const Stmt *T) { 
@@ -381,6 +395,10 @@
     assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
   }
 
+  /// \brief Construct an empty integer literal.
+  explicit IntegerLiteral(EmptyShell Empty) 
+    : Expr(IntegerLiteralClass, Empty) { }
+
   IntegerLiteral* Clone(ASTContext &C) const;
   
   const llvm::APInt &getValue() const { return Value; }
@@ -389,6 +407,9 @@
   /// \brief Retrieve the location of the literal.
   SourceLocation getLocation() const { return Loc; }
 
+  void setValue(const llvm::APInt &Val) { Value = Val; }
+  void setLocation(SourceLocation Location) { Loc = Location; }
+
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == IntegerLiteralClass; 
   }
@@ -411,6 +432,10 @@
   CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
     : Expr(CharacterLiteralClass, type), Value(value), Loc(l), IsWide(iswide) {
   }
+
+  /// \brief Construct an empty character literal.
+  CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
+
   SourceLocation getLoc() const { return Loc; }
   bool isWide() const { return IsWide; }
   
@@ -418,6 +443,10 @@
   
   unsigned getValue() const { return Value; }
 
+  void setLocation(SourceLocation Location) { Loc = Location; }
+  void setWide(bool W) { IsWide = W; }
+  void setValue(unsigned Val) { Value = Val; }
+
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == CharacterLiteralClass; 
   }

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=69075&r1=69074&r2=69075&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Tue Apr 14 16:18:50 2009
@@ -210,7 +210,12 @@
   const_child_iterator child_end() const {
     return const_child_iterator(const_cast<Stmt*>(this)->child_end());
   }
-  
+
+  /// \brief A placeholder type used to construct an empty shell of a
+  /// type, that will be filled in later (e.g., by some
+  /// de-serialization).
+  struct EmptyShell { };
+
   void Emit(llvm::Serializer& S) const;
   static Stmt* Create(llvm::Deserializer& D, ASTContext& C);
 

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Tue Apr 14 16:18:50 2009
@@ -359,6 +359,24 @@
       /// into a DeclContext via DeclContext::lookup.
       DECL_CONTEXT_VISIBLE
     };
+
+    /// \brief Record codes for each kind of statement or expression.
+    ///
+    /// These constants describe the records that describe statements
+    /// or expressions. These records can occur within either the type
+    /// or declaration blocks, so they begin with record values of
+    /// 100. Each constant describes a record for a specific
+    /// statement or expression class in the AST.
+    enum StmtCode {
+      /// \brief A NULL expression.
+      EXPR_NULL = 100,
+      /// \brief A DeclRefExpr record.
+      EXPR_DECL_REF,
+      /// \brief An IntegerLiteral record.
+      EXPR_INTEGER_LITERAL,
+      /// \brief A CharacterLiteral record.
+      EXPR_CHARACTER_LITERAL
+    };
     /// @}
   }
 } // 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=69075&r1=69074&r2=69075&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Tue Apr 14 16:18:50 2009
@@ -221,6 +221,9 @@
   /// \brief Read a signed integral value
   llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
 
+  /// \brief Reads an expression from the current stream position.
+  Expr *ReadExpr();
+
   /// \brief Retrieve the AST context that this PCH reader
   /// supplements.
   ASTContext &getContext() { return Context; }

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Tue Apr 14 16:18:50 2009
@@ -21,7 +21,6 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
 #include <queue>
-#include <vector>
 
 namespace llvm {
   class APInt;
@@ -43,6 +42,10 @@
 /// data structures. This bitstream can be de-serialized via an
 /// instance of the PCHReader class.
 class PCHWriter {
+public:
+  typedef llvm::SmallVector<uint64_t, 64> RecordData;
+
+private:
   /// \brief The bitstream writer used to emit this precompiled header.
   llvm::BitstreamWriter &S;
 
@@ -100,6 +103,13 @@
   /// record.
   llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
 
+  /// \brief Expressions that we've encountered while serializing a
+  /// declaration or type.
+  ///
+  /// The expressions in this queue will be emitted following the
+  /// declaration or type.
+  std::queue<Expr *> ExprsToEmit;
+
   void WriteTargetTriple(const TargetInfo &Target);
   void WriteLanguageOptions(const LangOptions &LangOpts);
   void WriteSourceManagerBlock(SourceManager &SourceMgr);
@@ -112,8 +122,6 @@
   void WriteIdentifierTable();
 
 public:
-  typedef llvm::SmallVector<uint64_t, 64> RecordData;
-
   /// \brief Create a new precompiled header writer that outputs to
   /// the given bitstream.
   PCHWriter(llvm::BitstreamWriter &S);
@@ -141,6 +149,14 @@
 
   /// \brief Emit a declaration name.
   void AddDeclarationName(DeclarationName Name, RecordData &Record);
+
+  /// \brief Add the given expression to the queue of expressions to
+  /// emit.
+  void AddExpr(Expr *E) { ExprsToEmit.push(E); }
+
+  /// \brief Flush all of the expressions that have been added to the
+  /// queue via AddExpr().
+  void FlushExprs();
 };
 
 } // end namespace clang

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Apr 14 16:18:50 2009
@@ -16,6 +16,8 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclGroup.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Preprocessor.h"
@@ -127,7 +129,8 @@
 
 void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
   VisitValueDecl(ECD);
-  // FIXME: read the initialization expression
+  if (Record[Idx++])
+    ECD->setInitExpr(Reader.ReadExpr());
   ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
 }
 
@@ -155,7 +158,8 @@
 void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
   VisitValueDecl(FD);
   FD->setMutable(Record[Idx++]);
-  // FIXME: Read the bit width.
+  if (Record[Idx++])
+    FD->setBitWidth(Reader.ReadExpr());
 }
 
 void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
@@ -167,6 +171,8 @@
   VD->setPreviousDeclaration(
                          cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
   VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  if (Record[Idx++])
+    VD->setInit(Reader.ReadExpr());
 }
 
 void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
@@ -204,6 +210,53 @@
   return std::make_pair(LexicalOffset, VisibleOffset);
 }
 
+//===----------------------------------------------------------------------===//
+// Statement/expression deserialization
+//===----------------------------------------------------------------------===//
+namespace {
+  class VISIBILITY_HIDDEN PCHStmtReader 
+    : public StmtVisitor<PCHStmtReader, void> {
+    PCHReader &Reader;
+    const PCHReader::RecordData &Record;
+    unsigned &Idx;
+
+  public:
+    PCHStmtReader(PCHReader &Reader, const PCHReader::RecordData &Record,
+                  unsigned &Idx)
+      : Reader(Reader), Record(Record), Idx(Idx) { }
+
+    void VisitExpr(Expr *E);
+    void VisitDeclRefExpr(DeclRefExpr *E);
+    void VisitIntegerLiteral(IntegerLiteral *E);
+    void VisitCharacterLiteral(CharacterLiteral *E);
+  };
+}
+
+void PCHStmtReader::VisitExpr(Expr *E) {
+  E->setType(Reader.GetType(Record[Idx++]));
+  E->setTypeDependent(Record[Idx++]);
+  E->setValueDependent(Record[Idx++]);
+}
+
+void PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
+  VisitExpr(E);
+  E->setDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+
+void PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
+  VisitExpr(E);
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setValue(Reader.ReadAPInt(Record, Idx));
+}
+
+void PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
+  VisitExpr(E);
+  E->setValue(Record[Idx++]);
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setWide(Record[Idx++]);
+}
+
 // FIXME: use the diagnostics machinery
 static bool Error(const char *Str) {
   std::fprintf(stderr, "%s\n", Str);
@@ -755,6 +808,26 @@
   return Success;
 }
 
+namespace {
+  /// \brief Helper class that saves the current stream position and
+  /// then restores it when destroyed.
+  struct VISIBILITY_HIDDEN SavedStreamPosition {
+    explicit SavedStreamPosition(llvm::BitstreamReader &Stream)
+      : Stream(Stream), Offset(Stream.GetCurrentBitNo()),
+        EndOfStream(Stream.AtEndOfStream()){ }
+
+    ~SavedStreamPosition() {
+      if (!EndOfStream) 
+        Stream.JumpToBit(Offset);
+    }
+
+  private:
+    llvm::BitstreamReader &Stream;
+    uint64_t Offset;
+    bool EndOfStream;
+  };
+}
+
 /// \brief Parse the record that corresponds to a LangOptions data
 /// structure.
 ///
@@ -850,6 +923,10 @@
 /// at the given offset in the bitstream. It is a helper routine for
 /// GetType, which deals with reading type IDs.
 QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this type.
+  SavedStreamPosition SavedPosition(Stream);
+
   Stream.JumpToBit(Offset);
   RecordData Record;
   unsigned Code = Stream.ReadCode();
@@ -918,9 +995,11 @@
   }
 
   case pch::TYPE_VARIABLE_ARRAY: {
-    // FIXME: implement this
-    assert(false && "Unable to de-serialize variable-length array type");
-    return QualType();
+    QualType ElementType = GetType(Record[0]);
+    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+    unsigned IndexTypeQuals = Record[2];
+    return Context.getVariableArrayType(ElementType, ReadExpr(),
+                                        ASM, IndexTypeQuals);
   }
 
   case pch::TYPE_VECTOR: {
@@ -972,9 +1051,7 @@
     return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
 
   case pch::TYPE_TYPEOF_EXPR:
-    // FIXME: Deserialize TypeOfExprType
-    assert(false && "Cannot de-serialize typeof(expr) from a PCH file");
-    return QualType();
+    return Context.getTypeOfExprType(ReadExpr());
 
   case pch::TYPE_TYPEOF: {
     if (Record.size() != 1) {
@@ -1032,12 +1109,17 @@
 
 /// \brief Read the declaration at the given offset from the PCH file.
 Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this declaration.
+  SavedStreamPosition SavedPosition(Stream);
+
   Decl *D = 0;
   Stream.JumpToBit(Offset);
   RecordData Record;
   unsigned Code = Stream.ReadCode();
   unsigned Idx = 0;
   PCHDeclReader Reader(*this, Record, Idx);
+
   switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
   case pch::DECL_TRANSLATION_UNIT:
     assert(Index == 0 && "Translation unit must be at index 0");
@@ -1237,6 +1319,10 @@
   uint64_t Offset = DeclContextOffsets[DC].first;
   assert(Offset && "DeclContext has no lexical decls in storage");
 
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this context.
+  SavedStreamPosition SavedPosition(Stream);
+
   // Load the record containing all of the declarations lexically in
   // this context.
   Stream.JumpToBit(Offset);
@@ -1258,6 +1344,10 @@
   uint64_t Offset = DeclContextOffsets[DC].second;
   assert(Offset && "DeclContext has no visible decls in storage");
 
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this context.
+  SavedStreamPosition SavedPosition(Stream);
+
   // Load the record containing all of the declarations visible in
   // this context.
   Stream.JumpToBit(Offset);
@@ -1394,6 +1484,44 @@
   return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
 }
 
+Expr *PCHReader::ReadExpr() {
+  RecordData Record;
+  unsigned Code = Stream.ReadCode();
+  unsigned Idx = 0;
+  PCHStmtReader Reader(*this, Record, Idx);
+  Stmt::EmptyShell Empty;
+
+  Expr *E = 0;
+  switch ((pch::StmtCode)Stream.ReadRecord(Code, Record)) {
+  case pch::EXPR_NULL: 
+    E = 0; 
+    break;
+
+  case pch::EXPR_DECL_REF: 
+    E = new (Context) DeclRefExpr(Empty); 
+    break;
+
+  case pch::EXPR_INTEGER_LITERAL: 
+    E = new (Context) IntegerLiteral(Empty);
+    break;
+
+  case pch::EXPR_CHARACTER_LITERAL:
+    E = new (Context) CharacterLiteral(Empty);
+    break;
+
+  default:
+    assert(false && "Unhandled expression kind");
+    break;
+  }
+
+  if (E)
+    Reader.Visit(E);
+
+  assert(Idx == Record.size() && "Invalid deserialization of expression");
+
+  return E;
+}
+
 DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
   return Diag(SourceLocation(), DiagID);
 }

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Apr 14 16:18:50 2009
@@ -16,6 +16,8 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclContextInternals.h"
 #include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Preprocessor.h"
@@ -122,8 +124,7 @@
 
 void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
   VisitArrayType(T);
-  // FIXME: Serialize array size expression.
-  assert(false && "Cannot serialize variable-length arrays");
+  Writer.AddExpr(T->getSizeExpr());
   Code = pch::TYPE_VARIABLE_ARRAY;
 }
 
@@ -163,8 +164,7 @@
 }
 
 void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
-  // FIXME: serialize the typeof expression
-  assert(false && "Cannot serialize typeof(expr)");
+  Writer.AddExpr(T->getUnderlyingExpr());
   Code = pch::TYPE_TYPEOF_EXPR;
 }
 
@@ -327,7 +327,9 @@
 
 void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
   VisitValueDecl(D);
-  // FIXME: Writer.AddExprRef(D->getInitExpr());
+  Record.push_back(D->getInitExpr()? 1 : 0);
+  if (D->getInitExpr())
+    Writer.AddExpr(D->getInitExpr());
   Writer.AddAPSInt(D->getInitVal(), Record);
   Code = pch::DECL_ENUM_CONSTANT;
 }
@@ -354,7 +356,9 @@
 void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
   VisitValueDecl(D);
   Record.push_back(D->isMutable());
-  // FIXME: Writer.AddExprRef(D->getBitWidth());
+  Record.push_back(D->getBitWidth()? 1 : 0);
+  if (D->getBitWidth())
+    Writer.AddExpr(D->getBitWidth());
   Code = pch::DECL_FIELD;
 }
 
@@ -366,7 +370,9 @@
   Record.push_back(D->isDeclaredInCondition());
   Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
   Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
-  // FIXME: emit initializer
+  Record.push_back(D->getInit()? 1 : 0);
+  if (D->getInit())
+    Writer.AddExpr(D->getInit());
   Code = pch::DECL_VAR;
 }
 
@@ -420,6 +426,57 @@
 }
 
 //===----------------------------------------------------------------------===//
+// Statement/expression serialization
+//===----------------------------------------------------------------------===//
+namespace {
+  class VISIBILITY_HIDDEN PCHStmtWriter
+    : public StmtVisitor<PCHStmtWriter, void> {
+
+    PCHWriter &Writer;
+    PCHWriter::RecordData &Record;
+
+  public:
+    pch::StmtCode Code;
+
+    PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
+      : Writer(Writer), Record(Record) { }
+
+    void VisitExpr(Expr *E);
+    void VisitDeclRefExpr(DeclRefExpr *E);
+    void VisitIntegerLiteral(IntegerLiteral *E);
+    void VisitCharacterLiteral(CharacterLiteral *E);
+  };
+}
+
+void PCHStmtWriter::VisitExpr(Expr *E) {
+  Writer.AddTypeRef(E->getType(), Record);
+  Record.push_back(E->isTypeDependent());
+  Record.push_back(E->isValueDependent());
+}
+
+void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
+  VisitExpr(E);
+  Writer.AddDeclRef(E->getDecl(), Record);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Code = pch::EXPR_DECL_REF;
+}
+
+void PCHStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Writer.AddAPInt(E->getValue(), Record);
+  Code = pch::EXPR_INTEGER_LITERAL;
+}
+
+void PCHStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) {
+  VisitExpr(E);
+  Record.push_back(E->getValue());
+  Writer.AddSourceLocation(E->getLoc(), Record);
+  Record.push_back(E->isWide());
+  Code = pch::EXPR_CHARACTER_LITERAL;
+}
+
+//===----------------------------------------------------------------------===//
 // PCHWriter Implementation
 //===----------------------------------------------------------------------===//
 
@@ -513,8 +570,6 @@
   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);
 }
@@ -805,6 +860,9 @@
 
   // Emit the serialized record.
   S.EmitRecord(W.Code, Record);
+
+  // Flush any expressions that were written as part of this type.
+  FlushExprs();
 }
 
 /// \brief Write a block containing all of the types.
@@ -937,6 +995,9 @@
     assert(W.Code && "Unhandled declaration kind while generating PCH");
     S.EmitRecord(W.Code, Record);
 
+    // Flush any expressions that were written as part of this declaration.
+    FlushExprs();
+    
     // Note external declarations so that we can add them to a record
     // in the PCH file later.
     if (isa<FileScopeAsmDecl>(D))
@@ -1160,3 +1221,26 @@
     break;
   }
 }
+
+/// \brief Flush all of the expressions that have been added to the
+/// queue via AddExpr().
+void PCHWriter::FlushExprs() {
+  RecordData Record;
+  PCHStmtWriter Writer(*this, Record);
+  while (!ExprsToEmit.empty()) {
+    Expr *E = ExprsToEmit.front();
+    ExprsToEmit.pop();
+
+    Record.clear();
+    if (!E) {
+      S.EmitRecord(pch::EXPR_NULL, Record);
+      continue;
+    }
+
+    Writer.Code = pch::EXPR_NULL;
+    Writer.Visit(E);
+    assert(Writer.Code != pch::EXPR_NULL && 
+           "Unhandled expression writing PCH file");
+    S.EmitRecord(Writer.Code, Record);  
+  }
+}

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

==============================================================================
--- cfe/trunk/test/PCH/enum.h (original)
+++ cfe/trunk/test/PCH/enum.h Tue Apr 14 16:18:50 2009
@@ -8,9 +8,9 @@
 
 enum Shape {
   Square,
-  Triangle,
+  Triangle = 17,
   Rhombus,
   Circle
 };
 
-enum Shape aRoundShape = Circle;
+enum Shape aRoundShape;// FIXME: = Circle;

Added: cfe/trunk/test/PCH/exprs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.c?rev=69075&view=auto

==============================================================================
--- cfe/trunk/test/PCH/exprs.c (added)
+++ cfe/trunk/test/PCH/exprs.c Tue Apr 14 16:18:50 2009
@@ -0,0 +1,19 @@
+// Test this without pch.
+// RUN: clang-cc -fblocks -include %S/exprs.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: clang-cc -emit-pch -fblocks -o %t %S/exprs.h &&
+// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -verify %s 
+
+int integer;
+long long_integer;
+
+// DeclRefExpr
+int_decl_ref *int_ptr1 = &integer;
+enum_decl_ref *enum_ptr1 = &integer;
+// IntegerLiteralExpr
+integer_literal *int_ptr2 = &integer;
+long_literal *long_ptr1 = &long_integer;
+
+// CharacterLiteralExpr
+char_literal *int_ptr3 = &integer;

Added: cfe/trunk/test/PCH/exprs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=69075&view=auto

==============================================================================
--- cfe/trunk/test/PCH/exprs.h (added)
+++ cfe/trunk/test/PCH/exprs.h Tue Apr 14 16:18:50 2009
@@ -0,0 +1,14 @@
+// Header for PCH test exprs.c
+
+// DeclRefExpr
+int i = 17;
+enum Enum { Enumerator = 18 };
+typedef typeof(i) int_decl_ref;
+typedef typeof(Enumerator) enum_decl_ref;
+
+// IntegerLiteralExpr
+typedef typeof(17) integer_literal;
+typedef typeof(17l) long_literal;
+
+// CharacterLiteralExpr
+typedef typeof('a') char_literal;

Modified: cfe/trunk/test/PCH/external-defs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/external-defs.c?rev=69075&r1=69074&r2=69075&view=diff

==============================================================================
--- cfe/trunk/test/PCH/external-defs.c (original)
+++ cfe/trunk/test/PCH/external-defs.c Tue Apr 14 16:18:50 2009
@@ -3,8 +3,7 @@
 // RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -emit-llvm -o %t %s &&
 
 // RUN: grep "@x = common global i32 0" %t | count 1 &&
-// FIXME below: should be i32 17, but we don't serialize y's value yet
-// RUN: grep "@y = common global i32 0"  %t | count 1 &&
+// RUN: grep "@y = global i32 17"  %t | count 1 &&
 // RUN: grep "@z" %t | count 0 &&
 
 // RUN: grep "@x2 = global i32 19" %t | count 1 &&

Modified: cfe/trunk/test/PCH/external-defs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/external-defs.h?rev=69075&r1=69074&r2=69075&view=diff

==============================================================================
--- cfe/trunk/test/PCH/external-defs.h (original)
+++ cfe/trunk/test/PCH/external-defs.h Tue Apr 14 16:18:50 2009
@@ -4,7 +4,7 @@
 int x;
 int x2;
 
-// FIXME: check this, once we actually serialize it
+// Definitions
 int y = 17;
 
 // Should not show up

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

==============================================================================
--- cfe/trunk/test/PCH/struct.c (original)
+++ cfe/trunk/test/PCH/struct.c Tue Apr 14 16:18:50 2009
@@ -23,6 +23,8 @@
   return fun2->very_fun;
 }
 
+int *int_ptr_fail = &fun->is_ptr; // expected-error{{address of bit-field requested}}
+
 /* FIXME: DeclContexts aren't yet able to find "struct Nested" nested
    within "struct S", so causing the following to fail. When not using
    PCH, this works because Sema puts the nested struct onto the

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

==============================================================================
--- cfe/trunk/test/PCH/struct.h (original)
+++ cfe/trunk/test/PCH/struct.h Tue Apr 14 16:18:50 2009
@@ -13,7 +13,7 @@
 struct Fun *fun;
 
 struct Fun {
-  int is_ptr;
+  int is_ptr : 1;
 
   union {
     void *ptr;

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

==============================================================================
--- cfe/trunk/test/PCH/types.c (original)
+++ cfe/trunk/test/PCH/types.c Tue Apr 14 16:18:50 2009
@@ -56,7 +56,10 @@
 // TYPE_TYPEDEF
 int_ptr_ptr ipp = &int_value_ptr;
 
-// FIXME: TYPE_TYPEOF_EXPR
+// TYPE_TYPEOF_EXPR
+typeof_17 *t17 = &int_value;
+struct S { int x, y; };
+typeof_17 t17_2 = (struct S){1, 2}; // expected-error{{incompatible type initializing}}
 
 // TYPE_TYPEOF
 int_ptr_ptr2 ipp2 = &int_value_ptr;

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

==============================================================================
--- cfe/trunk/test/PCH/types.h (original)
+++ cfe/trunk/test/PCH/types.h Tue Apr 14 16:18:50 2009
@@ -35,7 +35,8 @@
 // TYPE_TYPEDEF
 typedef int_ptr * int_ptr_ptr;
 
-// FIXME: TYPE_TYPEOF_EXPR
+// TYPE_TYPEOF_EXPR
+typedef typeof(17) typeof_17;
 
 // TYPE_TYPEOF
 typedef typeof(int_ptr *) int_ptr_ptr2;

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

==============================================================================
--- cfe/trunk/test/PCH/variables.c (original)
+++ cfe/trunk/test/PCH/variables.c Tue Apr 14 16:18:50 2009
@@ -9,7 +9,8 @@
 float *fp = &ip; // expected-warning{{incompatible pointer types}}
 // FIXME:variables.h expected-note{{previous}}
 double z; // expected-error{{redefinition}}
-
+// FIXME:variables.h expected-note{{previous}}
+int z2 = 18; // 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=69075&r1=69074&r2=69075&view=diff

==============================================================================
--- cfe/trunk/test/PCH/variables.h (original)
+++ cfe/trunk/test/PCH/variables.h Tue Apr 14 16:18:50 2009
@@ -9,7 +9,7 @@
 
 float z;
 
-
+int z2 = 17;
 
 #define MAKE_HAPPY(X) X##Happy
 int MAKE_HAPPY(Very);





More information about the cfe-commits mailing list