]> granicus.if.org Git - clang/commitdiff
PCH support for a few very, very simple kinds of expressions. Hook up
authorDouglas Gregor <dgregor@apple.com>
Tue, 14 Apr 2009 21:18:50 +0000 (21:18 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 14 Apr 2009 21:18:50 +0000 (21:18 +0000)
expression (de-)serialization for VLAs, variable initializers,
enum constant initializers, and bitfield widths.

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

19 files changed:
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 [new file with mode: 0644]
test/PCH/exprs.h [new file with mode: 0644]
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

index fd6e210104f66d4338df7ce362b5fe2c5a9d8089..3f4ea122bdbbf72cc409cb64f9f3c445da818a6c 100644 (file)
@@ -807,6 +807,8 @@ public:
   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;
index 6fd2970153e24b04945f833c5f26f5db9d9d1bc1..7001e290fce3c019942bde09b18a69779332859a 100644 (file)
@@ -63,6 +63,9 @@ protected:
     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 @@ public:
   /// @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 @@ public:
   /// @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 @@ public:
   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 @@ public:
     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 @@ public:
   /// \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 @@ public:
   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 @@ public:
   
   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; 
   }
index c99f0a9b2fa80686fec31788c2942446f1f6a107..c20d602a7cc7892c0e5cc85643f26964b7506d32 100644 (file)
@@ -210,7 +210,12 @@ public:
   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);
 
index bda1370c6f7b6edfbba7fd24a17579ee9a3f6d97..54f686bbb08a2eb4c389a776bd008b935e48380b 100644 (file)
@@ -359,6 +359,24 @@ namespace clang {
       /// 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
index 6928d26b0c79c4dce858a3c5762cd177652f8fd6..b9596b6de2672e6c6dc8cfd145024f61d5543717 100644 (file)
@@ -221,6 +221,9 @@ public:
   /// \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; }
index a887e71899c08a7d9383e1c4d82c65b7378974d6..4713b1e4900a6bc0ad5699a46c486306bfd98b65 100644 (file)
@@ -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 @@ class TargetInfo;
 /// 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 @@ class PCHWriter {
   /// 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 @@ class PCHWriter {
   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 @@ public:
 
   /// \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
index f5f6f5d41c99e53b98d1d0f78ba809454e17a3ec..909ecdb100c6d21d648bcf8c5034a4966ebb5993 100644 (file)
@@ -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::VisitValueDecl(ValueDecl *VD) {
 
 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::VisitFunctionDecl(FunctionDecl *FD) {
 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 @@ void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
   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 @@ PCHDeclReader::VisitDeclContext(DeclContext *DC) {
   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 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
   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 @@ bool PCHReader::ParseLanguageOptions(
 /// 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 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
   }
 
   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 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
     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 @@ inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
 
 /// \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 @@ bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
   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 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
   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 @@ llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
   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);
 }
index c7bfa0b74e9768f39088590ed43f1722339157a6..1cf98cea9ca89ec0c6e454c30a244ac43ee39e45 100644 (file)
@@ -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::VisitIncompleteArrayType(const IncompleteArrayType *T) {
 
 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::VisitTypedefType(const TypedefType *T) {
 }
 
 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::VisitValueDecl(ValueDecl *D) {
 
 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::VisitFunctionDecl(FunctionDecl *D) {
 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 @@ void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
   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;
 }
 
@@ -419,6 +425,57 @@ void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
     Record.push_back(VisibleOffset);
 }
 
+//===----------------------------------------------------------------------===//
+// 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 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &S) {
   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 @@ void PCHWriter::WriteType(const Type *T) {
 
   // 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 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
     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 @@ void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
     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);  
+  }
+}
index cfa8d6f3d85b65be10957becbdb238f20e5d9246..c94e314eb06ceefd40f2e74bf59f944f2bdc54f8 100644 (file)
@@ -8,9 +8,9 @@ enum Color {
 
 enum Shape {
   Square,
-  Triangle,
+  Triangle = 17,
   Rhombus,
   Circle
 };
 
-enum Shape aRoundShape = Circle;
+enum Shape aRoundShape;// FIXME: = Circle;
diff --git a/test/PCH/exprs.c b/test/PCH/exprs.c
new file mode 100644 (file)
index 0000000..d1cd563
--- /dev/null
@@ -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;
diff --git a/test/PCH/exprs.h b/test/PCH/exprs.h
new file mode 100644 (file)
index 0000000..db6513c
--- /dev/null
@@ -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;
index fd14c4fa8b3505314fa14dbd756518105051644d..5af21af517a21108fd67d3823f1d3fe7437b5ade 100644 (file)
@@ -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 &&
index 4ac9077d12137ec2462fbeee41a41380715d5b0e..06c4601ccb32bc8e517763a7212af87ff83bf8f5 100644 (file)
@@ -4,7 +4,7 @@
 int x;
 int x2;
 
-// FIXME: check this, once we actually serialize it
+// Definitions
 int y = 17;
 
 // Should not show up
index 220f0794656a6b6d7c6a7d845f8dbb27ea1cf5ff..5ea9fe27570e175ecd306c82ce67d1ea1b82deb7 100644 (file)
@@ -23,6 +23,8 @@ int get_very_fun() {
   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
index 6c256221fa03431c738027f6df779ec6f8ccd82d..2ffdd4aea5864752a1eed65893477077fb68dc07 100644 (file)
@@ -13,7 +13,7 @@ struct Fun;
 struct Fun *fun;
 
 struct Fun {
-  int is_ptr;
+  int is_ptr : 1;
 
   union {
     void *ptr;
index e62a4bbe3bf157ba469373f8641d88cdb31b18c0..425305c584258dfd591a8556238680d382f62399 100644 (file)
@@ -56,7 +56,10 @@ proto *p2 = p1;
 // 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;
index 3713e0b6900db2c78e1e3deecae2062fff3c4a04..54ab2152d7e7886d94032c103b4dc2e691a45b6d 100644 (file)
@@ -35,7 +35,8 @@ typedef float proto(float, float, ...);
 // 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;
index 4f42e50481698a480431cac188349690320efe9b..afd45461d0c490414f8d33147d8758252b654372 100644 (file)
@@ -9,7 +9,8 @@ int *ip2 = &x;
 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}}
 
 
index 82e87aaf4bffed45dbf657eb886f9e78c58735f2..70aec65180910345318eec9cce3963feacb00a20 100644 (file)
@@ -9,7 +9,7 @@ extern int *ip, x;
 
 float z;
 
-
+int z2 = 17;
 
 #define MAKE_HAPPY(X) X##Happy
 int MAKE_HAPPY(Very);