forked from OSchip/llvm-project
				
			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. llvm-svn: 69075
This commit is contained in:
		
							parent
							
								
									a723ba97db
								
							
						
					
					
						commit
						feb84b0074
					
				| 
						 | 
					@ -807,6 +807,8 @@ public:
 | 
				
			||||||
  bool isAnonymousStructOrUnion() const;
 | 
					  bool isAnonymousStructOrUnion() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Expr *getBitWidth() const { return BitWidth; }
 | 
					  Expr *getBitWidth() const { return BitWidth; }
 | 
				
			||||||
 | 
					  void setBitWidth(Expr *BW) { BitWidth = BW; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Implement isa/cast/dyncast/etc.
 | 
					  // Implement isa/cast/dyncast/etc.
 | 
				
			||||||
  static bool classof(const Decl *D) {
 | 
					  static bool classof(const Decl *D) {
 | 
				
			||||||
    return D->getKind() >= FieldFirst && D->getKind() <= FieldLast;
 | 
					    return D->getKind() >= FieldFirst && D->getKind() <= FieldLast;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,6 +63,9 @@ protected:
 | 
				
			||||||
    setType(T);
 | 
					    setType(T);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// \brief Construct an empty expression.
 | 
				
			||||||
 | 
					  explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:  
 | 
					public:  
 | 
				
			||||||
  QualType getType() const { return TR; }
 | 
					  QualType getType() const { return TR; }
 | 
				
			||||||
  void setType(QualType t) { 
 | 
					  void setType(QualType t) { 
 | 
				
			||||||
| 
						 | 
					@ -88,6 +91,9 @@ public:
 | 
				
			||||||
  /// @endcode
 | 
					  /// @endcode
 | 
				
			||||||
  bool isValueDependent() const { return ValueDependent; }
 | 
					  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
 | 
					  /// isTypeDependent - Determines whether this expression is
 | 
				
			||||||
  /// type-dependent (C++ [temp.dep.expr]), which means that its type
 | 
					  /// type-dependent (C++ [temp.dep.expr]), which means that its type
 | 
				
			||||||
  /// could change from one template instantiation to the next. For
 | 
					  /// could change from one template instantiation to the next. For
 | 
				
			||||||
| 
						 | 
					@ -101,6 +107,9 @@ public:
 | 
				
			||||||
  /// @endcode
 | 
					  /// @endcode
 | 
				
			||||||
  bool isTypeDependent() const { return TypeDependent; }
 | 
					  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
 | 
					  /// SourceLocation tokens are not useful in isolation - they are low level
 | 
				
			||||||
  /// value objects created/interpreted by SourceManager. We assume AST
 | 
					  /// value objects created/interpreted by SourceManager. We assume AST
 | 
				
			||||||
  /// clients will have a pointer to the respective SourceManager.
 | 
					  /// 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) : 
 | 
					  DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) : 
 | 
				
			||||||
    Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {}
 | 
					    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; }
 | 
					  NamedDecl *getDecl() { return D; }
 | 
				
			||||||
  const NamedDecl *getDecl() const { return D; }
 | 
					  const NamedDecl *getDecl() const { return D; }
 | 
				
			||||||
  void setDecl(NamedDecl *NewD) { D = NewD; }
 | 
					  void setDecl(NamedDecl *NewD) { D = NewD; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SourceLocation getLocation() const { return Loc; }
 | 
					  SourceLocation getLocation() const { return Loc; }
 | 
				
			||||||
 | 
					  void setLocation(SourceLocation L) { Loc = L; }
 | 
				
			||||||
  virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
 | 
					  virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  static bool classof(const Stmt *T) { 
 | 
					  static bool classof(const Stmt *T) { 
 | 
				
			||||||
| 
						 | 
					@ -381,6 +395,10 @@ public:
 | 
				
			||||||
    assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
 | 
					    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;
 | 
					  IntegerLiteral* Clone(ASTContext &C) const;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  const llvm::APInt &getValue() const { return Value; }
 | 
					  const llvm::APInt &getValue() const { return Value; }
 | 
				
			||||||
| 
						 | 
					@ -389,6 +407,9 @@ public:
 | 
				
			||||||
  /// \brief Retrieve the location of the literal.
 | 
					  /// \brief Retrieve the location of the literal.
 | 
				
			||||||
  SourceLocation getLocation() const { return Loc; }
 | 
					  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) { 
 | 
					  static bool classof(const Stmt *T) { 
 | 
				
			||||||
    return T->getStmtClass() == IntegerLiteralClass; 
 | 
					    return T->getStmtClass() == IntegerLiteralClass; 
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -411,6 +432,10 @@ public:
 | 
				
			||||||
  CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
 | 
					  CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
 | 
				
			||||||
    : Expr(CharacterLiteralClass, type), Value(value), Loc(l), IsWide(iswide) {
 | 
					    : 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; }
 | 
					  SourceLocation getLoc() const { return Loc; }
 | 
				
			||||||
  bool isWide() const { return IsWide; }
 | 
					  bool isWide() const { return IsWide; }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
| 
						 | 
					@ -418,6 +443,10 @@ public:
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  unsigned getValue() const { return Value; }
 | 
					  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) { 
 | 
					  static bool classof(const Stmt *T) { 
 | 
				
			||||||
    return T->getStmtClass() == CharacterLiteralClass; 
 | 
					    return T->getStmtClass() == CharacterLiteralClass; 
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -211,6 +211,11 @@ public:
 | 
				
			||||||
    return const_child_iterator(const_cast<Stmt*>(this)->child_end());
 | 
					    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;
 | 
					  void Emit(llvm::Serializer& S) const;
 | 
				
			||||||
  static Stmt* Create(llvm::Deserializer& D, ASTContext& C);
 | 
					  static Stmt* Create(llvm::Deserializer& D, ASTContext& C);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -359,6 +359,24 @@ namespace clang {
 | 
				
			||||||
      /// into a DeclContext via DeclContext::lookup.
 | 
					      /// into a DeclContext via DeclContext::lookup.
 | 
				
			||||||
      DECL_CONTEXT_VISIBLE
 | 
					      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
 | 
					} // end namespace clang
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -221,6 +221,9 @@ public:
 | 
				
			||||||
  /// \brief Read a signed integral value
 | 
					  /// \brief Read a signed integral value
 | 
				
			||||||
  llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
 | 
					  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
 | 
					  /// \brief Retrieve the AST context that this PCH reader
 | 
				
			||||||
  /// supplements.
 | 
					  /// supplements.
 | 
				
			||||||
  ASTContext &getContext() { return Context; }
 | 
					  ASTContext &getContext() { return Context; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,6 @@
 | 
				
			||||||
#include "llvm/ADT/DenseMap.h"
 | 
					#include "llvm/ADT/DenseMap.h"
 | 
				
			||||||
#include "llvm/ADT/SmallVector.h"
 | 
					#include "llvm/ADT/SmallVector.h"
 | 
				
			||||||
#include <queue>
 | 
					#include <queue>
 | 
				
			||||||
#include <vector>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace llvm {
 | 
					namespace llvm {
 | 
				
			||||||
  class APInt;
 | 
					  class APInt;
 | 
				
			||||||
| 
						 | 
					@ -43,6 +42,10 @@ class TargetInfo;
 | 
				
			||||||
/// data structures. This bitstream can be de-serialized via an
 | 
					/// data structures. This bitstream can be de-serialized via an
 | 
				
			||||||
/// instance of the PCHReader class.
 | 
					/// instance of the PCHReader class.
 | 
				
			||||||
class PCHWriter {
 | 
					class PCHWriter {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  typedef llvm::SmallVector<uint64_t, 64> RecordData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
  /// \brief The bitstream writer used to emit this precompiled header.
 | 
					  /// \brief The bitstream writer used to emit this precompiled header.
 | 
				
			||||||
  llvm::BitstreamWriter &S;
 | 
					  llvm::BitstreamWriter &S;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,6 +103,13 @@ class PCHWriter {
 | 
				
			||||||
  /// record.
 | 
					  /// record.
 | 
				
			||||||
  llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
 | 
					  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 WriteTargetTriple(const TargetInfo &Target);
 | 
				
			||||||
  void WriteLanguageOptions(const LangOptions &LangOpts);
 | 
					  void WriteLanguageOptions(const LangOptions &LangOpts);
 | 
				
			||||||
  void WriteSourceManagerBlock(SourceManager &SourceMgr);
 | 
					  void WriteSourceManagerBlock(SourceManager &SourceMgr);
 | 
				
			||||||
| 
						 | 
					@ -112,8 +122,6 @@ class PCHWriter {
 | 
				
			||||||
  void WriteIdentifierTable();
 | 
					  void WriteIdentifierTable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  typedef llvm::SmallVector<uint64_t, 64> RecordData;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /// \brief Create a new precompiled header writer that outputs to
 | 
					  /// \brief Create a new precompiled header writer that outputs to
 | 
				
			||||||
  /// the given bitstream.
 | 
					  /// the given bitstream.
 | 
				
			||||||
  PCHWriter(llvm::BitstreamWriter &S);
 | 
					  PCHWriter(llvm::BitstreamWriter &S);
 | 
				
			||||||
| 
						 | 
					@ -141,6 +149,14 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Emit a declaration name.
 | 
					  /// \brief Emit a declaration name.
 | 
				
			||||||
  void AddDeclarationName(DeclarationName Name, RecordData &Record);
 | 
					  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
 | 
					} // end namespace clang
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,8 @@
 | 
				
			||||||
#include "clang/AST/ASTContext.h"
 | 
					#include "clang/AST/ASTContext.h"
 | 
				
			||||||
#include "clang/AST/Decl.h"
 | 
					#include "clang/AST/Decl.h"
 | 
				
			||||||
#include "clang/AST/DeclGroup.h"
 | 
					#include "clang/AST/DeclGroup.h"
 | 
				
			||||||
 | 
					#include "clang/AST/Expr.h"
 | 
				
			||||||
 | 
					#include "clang/AST/StmtVisitor.h"
 | 
				
			||||||
#include "clang/AST/Type.h"
 | 
					#include "clang/AST/Type.h"
 | 
				
			||||||
#include "clang/Lex/MacroInfo.h"
 | 
					#include "clang/Lex/MacroInfo.h"
 | 
				
			||||||
#include "clang/Lex/Preprocessor.h"
 | 
					#include "clang/Lex/Preprocessor.h"
 | 
				
			||||||
| 
						 | 
					@ -127,7 +129,8 @@ void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
 | 
					void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
 | 
				
			||||||
  VisitValueDecl(ECD);
 | 
					  VisitValueDecl(ECD);
 | 
				
			||||||
  // FIXME: read the initialization expression
 | 
					  if (Record[Idx++])
 | 
				
			||||||
 | 
					    ECD->setInitExpr(Reader.ReadExpr());
 | 
				
			||||||
  ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
 | 
					  ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,7 +158,8 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
 | 
				
			||||||
void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
 | 
					void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
 | 
				
			||||||
  VisitValueDecl(FD);
 | 
					  VisitValueDecl(FD);
 | 
				
			||||||
  FD->setMutable(Record[Idx++]);
 | 
					  FD->setMutable(Record[Idx++]);
 | 
				
			||||||
  // FIXME: Read the bit width.
 | 
					  if (Record[Idx++])
 | 
				
			||||||
 | 
					    FD->setBitWidth(Reader.ReadExpr());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
 | 
					void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
 | 
				
			||||||
| 
						 | 
					@ -167,6 +171,8 @@ void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
 | 
				
			||||||
  VD->setPreviousDeclaration(
 | 
					  VD->setPreviousDeclaration(
 | 
				
			||||||
                         cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
 | 
					                         cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
 | 
				
			||||||
  VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 | 
					  VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 | 
				
			||||||
 | 
					  if (Record[Idx++])
 | 
				
			||||||
 | 
					    VD->setInit(Reader.ReadExpr());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
 | 
					void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
 | 
				
			||||||
| 
						 | 
					@ -204,6 +210,53 @@ PCHDeclReader::VisitDeclContext(DeclContext *DC) {
 | 
				
			||||||
  return std::make_pair(LexicalOffset, VisibleOffset);
 | 
					  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
 | 
					// FIXME: use the diagnostics machinery
 | 
				
			||||||
static bool Error(const char *Str) {
 | 
					static bool Error(const char *Str) {
 | 
				
			||||||
  std::fprintf(stderr, "%s\n", Str);
 | 
					  std::fprintf(stderr, "%s\n", Str);
 | 
				
			||||||
| 
						 | 
					@ -755,6 +808,26 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
 | 
				
			||||||
  return Success;
 | 
					  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
 | 
					/// \brief Parse the record that corresponds to a LangOptions data
 | 
				
			||||||
/// structure.
 | 
					/// structure.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
| 
						 | 
					@ -850,6 +923,10 @@ bool PCHReader::ParseLanguageOptions(
 | 
				
			||||||
/// at the given offset in the bitstream. It is a helper routine for
 | 
					/// at the given offset in the bitstream. It is a helper routine for
 | 
				
			||||||
/// GetType, which deals with reading type IDs.
 | 
					/// GetType, which deals with reading type IDs.
 | 
				
			||||||
QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
 | 
					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);
 | 
					  Stream.JumpToBit(Offset);
 | 
				
			||||||
  RecordData Record;
 | 
					  RecordData Record;
 | 
				
			||||||
  unsigned Code = Stream.ReadCode();
 | 
					  unsigned Code = Stream.ReadCode();
 | 
				
			||||||
| 
						 | 
					@ -918,9 +995,11 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  case pch::TYPE_VARIABLE_ARRAY: {
 | 
					  case pch::TYPE_VARIABLE_ARRAY: {
 | 
				
			||||||
    // FIXME: implement this
 | 
					    QualType ElementType = GetType(Record[0]);
 | 
				
			||||||
    assert(false && "Unable to de-serialize variable-length array type");
 | 
					    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
 | 
				
			||||||
    return QualType();
 | 
					    unsigned IndexTypeQuals = Record[2];
 | 
				
			||||||
 | 
					    return Context.getVariableArrayType(ElementType, ReadExpr(),
 | 
				
			||||||
 | 
					                                        ASM, IndexTypeQuals);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  case pch::TYPE_VECTOR: {
 | 
					  case pch::TYPE_VECTOR: {
 | 
				
			||||||
| 
						 | 
					@ -972,9 +1051,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
 | 
				
			||||||
    return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
 | 
					    return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  case pch::TYPE_TYPEOF_EXPR:
 | 
					  case pch::TYPE_TYPEOF_EXPR:
 | 
				
			||||||
    // FIXME: Deserialize TypeOfExprType
 | 
					    return Context.getTypeOfExprType(ReadExpr());
 | 
				
			||||||
    assert(false && "Cannot de-serialize typeof(expr) from a PCH file");
 | 
					 | 
				
			||||||
    return QualType();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  case pch::TYPE_TYPEOF: {
 | 
					  case pch::TYPE_TYPEOF: {
 | 
				
			||||||
    if (Record.size() != 1) {
 | 
					    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.
 | 
					/// \brief Read the declaration at the given offset from the PCH file.
 | 
				
			||||||
Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
 | 
					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;
 | 
					  Decl *D = 0;
 | 
				
			||||||
  Stream.JumpToBit(Offset);
 | 
					  Stream.JumpToBit(Offset);
 | 
				
			||||||
  RecordData Record;
 | 
					  RecordData Record;
 | 
				
			||||||
  unsigned Code = Stream.ReadCode();
 | 
					  unsigned Code = Stream.ReadCode();
 | 
				
			||||||
  unsigned Idx = 0;
 | 
					  unsigned Idx = 0;
 | 
				
			||||||
  PCHDeclReader Reader(*this, Record, Idx);
 | 
					  PCHDeclReader Reader(*this, Record, Idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
 | 
					  switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
 | 
				
			||||||
  case pch::DECL_TRANSLATION_UNIT:
 | 
					  case pch::DECL_TRANSLATION_UNIT:
 | 
				
			||||||
    assert(Index == 0 && "Translation unit must be at index 0");
 | 
					    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;
 | 
					  uint64_t Offset = DeclContextOffsets[DC].first;
 | 
				
			||||||
  assert(Offset && "DeclContext has no lexical decls in storage");
 | 
					  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
 | 
					  // Load the record containing all of the declarations lexically in
 | 
				
			||||||
  // this context.
 | 
					  // this context.
 | 
				
			||||||
  Stream.JumpToBit(Offset);
 | 
					  Stream.JumpToBit(Offset);
 | 
				
			||||||
| 
						 | 
					@ -1258,6 +1344,10 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
 | 
				
			||||||
  uint64_t Offset = DeclContextOffsets[DC].second;
 | 
					  uint64_t Offset = DeclContextOffsets[DC].second;
 | 
				
			||||||
  assert(Offset && "DeclContext has no visible decls in storage");
 | 
					  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
 | 
					  // Load the record containing all of the declarations visible in
 | 
				
			||||||
  // this context.
 | 
					  // this context.
 | 
				
			||||||
  Stream.JumpToBit(Offset);
 | 
					  Stream.JumpToBit(Offset);
 | 
				
			||||||
| 
						 | 
					@ -1394,6 +1484,44 @@ llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
 | 
				
			||||||
  return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
 | 
					  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) {
 | 
					DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
 | 
				
			||||||
  return Diag(SourceLocation(), DiagID);
 | 
					  return Diag(SourceLocation(), DiagID);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,8 @@
 | 
				
			||||||
#include "clang/AST/Decl.h"
 | 
					#include "clang/AST/Decl.h"
 | 
				
			||||||
#include "clang/AST/DeclContextInternals.h"
 | 
					#include "clang/AST/DeclContextInternals.h"
 | 
				
			||||||
#include "clang/AST/DeclVisitor.h"
 | 
					#include "clang/AST/DeclVisitor.h"
 | 
				
			||||||
 | 
					#include "clang/AST/Expr.h"
 | 
				
			||||||
 | 
					#include "clang/AST/StmtVisitor.h"
 | 
				
			||||||
#include "clang/AST/Type.h"
 | 
					#include "clang/AST/Type.h"
 | 
				
			||||||
#include "clang/Lex/MacroInfo.h"
 | 
					#include "clang/Lex/MacroInfo.h"
 | 
				
			||||||
#include "clang/Lex/Preprocessor.h"
 | 
					#include "clang/Lex/Preprocessor.h"
 | 
				
			||||||
| 
						 | 
					@ -122,8 +124,7 @@ void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
 | 
					void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
 | 
				
			||||||
  VisitArrayType(T);
 | 
					  VisitArrayType(T);
 | 
				
			||||||
  // FIXME: Serialize array size expression.
 | 
					  Writer.AddExpr(T->getSizeExpr());
 | 
				
			||||||
  assert(false && "Cannot serialize variable-length arrays");
 | 
					 | 
				
			||||||
  Code = pch::TYPE_VARIABLE_ARRAY;
 | 
					  Code = pch::TYPE_VARIABLE_ARRAY;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,8 +164,7 @@ void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
 | 
					void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
 | 
				
			||||||
  // FIXME: serialize the typeof expression
 | 
					  Writer.AddExpr(T->getUnderlyingExpr());
 | 
				
			||||||
  assert(false && "Cannot serialize typeof(expr)");
 | 
					 | 
				
			||||||
  Code = pch::TYPE_TYPEOF_EXPR;
 | 
					  Code = pch::TYPE_TYPEOF_EXPR;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -327,7 +327,9 @@ void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
 | 
					void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
 | 
				
			||||||
  VisitValueDecl(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);
 | 
					  Writer.AddAPSInt(D->getInitVal(), Record);
 | 
				
			||||||
  Code = pch::DECL_ENUM_CONSTANT;
 | 
					  Code = pch::DECL_ENUM_CONSTANT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -354,7 +356,9 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
 | 
				
			||||||
void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
 | 
					void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
 | 
				
			||||||
  VisitValueDecl(D);
 | 
					  VisitValueDecl(D);
 | 
				
			||||||
  Record.push_back(D->isMutable());
 | 
					  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;
 | 
					  Code = pch::DECL_FIELD;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -366,7 +370,9 @@ void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
 | 
				
			||||||
  Record.push_back(D->isDeclaredInCondition());
 | 
					  Record.push_back(D->isDeclaredInCondition());
 | 
				
			||||||
  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
 | 
					  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
 | 
				
			||||||
  Writer.AddSourceLocation(D->getTypeSpecStartLoc(), 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;
 | 
					  Code = pch::DECL_VAR;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -419,6 +425,57 @@ void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
 | 
				
			||||||
    Record.push_back(VisibleOffset);
 | 
					    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
 | 
					// PCHWriter Implementation
 | 
				
			||||||
//===----------------------------------------------------------------------===//
 | 
					//===----------------------------------------------------------------------===//
 | 
				
			||||||
| 
						 | 
					@ -513,8 +570,6 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &S) {
 | 
				
			||||||
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
 | 
					  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
 | 
				
			||||||
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
 | 
					  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
 | 
				
			||||||
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
 | 
					  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
 | 
					  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
 | 
				
			||||||
  return S.EmitAbbrev(Abbrev);
 | 
					  return S.EmitAbbrev(Abbrev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -805,6 +860,9 @@ void PCHWriter::WriteType(const Type *T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Emit the serialized record.
 | 
					  // Emit the serialized record.
 | 
				
			||||||
  S.EmitRecord(W.Code, 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.
 | 
					/// \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");
 | 
					    assert(W.Code && "Unhandled declaration kind while generating PCH");
 | 
				
			||||||
    S.EmitRecord(W.Code, Record);
 | 
					    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
 | 
					    // Note external declarations so that we can add them to a record
 | 
				
			||||||
    // in the PCH file later.
 | 
					    // in the PCH file later.
 | 
				
			||||||
    if (isa<FileScopeAsmDecl>(D))
 | 
					    if (isa<FileScopeAsmDecl>(D))
 | 
				
			||||||
| 
						 | 
					@ -1160,3 +1221,26 @@ void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
 | 
				
			||||||
    break;
 | 
					    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);  
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,9 @@ enum Color {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum Shape {
 | 
					enum Shape {
 | 
				
			||||||
  Square,
 | 
					  Square,
 | 
				
			||||||
  Triangle,
 | 
					  Triangle = 17,
 | 
				
			||||||
  Rhombus,
 | 
					  Rhombus,
 | 
				
			||||||
  Circle
 | 
					  Circle
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum Shape aRoundShape = Circle;
 | 
					enum Shape aRoundShape;// FIXME: = Circle;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					@ -3,8 +3,7 @@
 | 
				
			||||||
// RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -emit-llvm -o %t %s &&
 | 
					// 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 &&
 | 
					// 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 = global i32 17"  %t | count 1 &&
 | 
				
			||||||
// RUN: grep "@y = common global i32 0"  %t | count 1 &&
 | 
					 | 
				
			||||||
// RUN: grep "@z" %t | count 0 &&
 | 
					// RUN: grep "@z" %t | count 0 &&
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RUN: grep "@x2 = global i32 19" %t | count 1 &&
 | 
					// RUN: grep "@x2 = global i32 19" %t | count 1 &&
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
int x;
 | 
					int x;
 | 
				
			||||||
int x2;
 | 
					int x2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FIXME: check this, once we actually serialize it
 | 
					// Definitions
 | 
				
			||||||
int y = 17;
 | 
					int y = 17;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Should not show up
 | 
					// Should not show up
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,8 @@ int get_very_fun() {
 | 
				
			||||||
  return fun2->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
 | 
					/* FIXME: DeclContexts aren't yet able to find "struct Nested" nested
 | 
				
			||||||
   within "struct S", so causing the following to fail. When not using
 | 
					   within "struct S", so causing the following to fail. When not using
 | 
				
			||||||
   PCH, this works because Sema puts the nested struct onto the
 | 
					   PCH, this works because Sema puts the nested struct onto the
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ struct Fun;
 | 
				
			||||||
struct Fun *fun;
 | 
					struct Fun *fun;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Fun {
 | 
					struct Fun {
 | 
				
			||||||
  int is_ptr;
 | 
					  int is_ptr : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  union {
 | 
					  union {
 | 
				
			||||||
    void *ptr;
 | 
					    void *ptr;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,10 @@ proto *p2 = p1;
 | 
				
			||||||
// TYPE_TYPEDEF
 | 
					// TYPE_TYPEDEF
 | 
				
			||||||
int_ptr_ptr ipp = &int_value_ptr;
 | 
					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
 | 
					// TYPE_TYPEOF
 | 
				
			||||||
int_ptr_ptr2 ipp2 = &int_value_ptr;
 | 
					int_ptr_ptr2 ipp2 = &int_value_ptr;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,8 @@ typedef float proto(float, float, ...);
 | 
				
			||||||
// TYPE_TYPEDEF
 | 
					// TYPE_TYPEDEF
 | 
				
			||||||
typedef int_ptr * int_ptr_ptr;
 | 
					typedef int_ptr * int_ptr_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FIXME: TYPE_TYPEOF_EXPR
 | 
					// TYPE_TYPEOF_EXPR
 | 
				
			||||||
 | 
					typedef typeof(17) typeof_17;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TYPE_TYPEOF
 | 
					// TYPE_TYPEOF
 | 
				
			||||||
typedef typeof(int_ptr *) int_ptr_ptr2;
 | 
					typedef typeof(int_ptr *) int_ptr_ptr2;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,8 @@ int *ip2 = &x;
 | 
				
			||||||
float *fp = &ip; // expected-warning{{incompatible pointer types}}
 | 
					float *fp = &ip; // expected-warning{{incompatible pointer types}}
 | 
				
			||||||
// FIXME:variables.h expected-note{{previous}}
 | 
					// FIXME:variables.h expected-note{{previous}}
 | 
				
			||||||
double z; // expected-error{{redefinition}}
 | 
					double z; // expected-error{{redefinition}}
 | 
				
			||||||
 | 
					// FIXME:variables.h expected-note{{previous}}
 | 
				
			||||||
 | 
					int z2 = 18; // expected-error{{redefinition}}
 | 
				
			||||||
//double VeryHappy; // FIXME: xpected-error{{redefinition}}
 | 
					//double VeryHappy; // FIXME: xpected-error{{redefinition}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ extern int *ip, x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float z;
 | 
					float z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int z2 = 17;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAKE_HAPPY(X) X##Happy
 | 
					#define MAKE_HAPPY(X) X##Happy
 | 
				
			||||||
int MAKE_HAPPY(Very);
 | 
					int MAKE_HAPPY(Very);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue