[cfe-commits] r69329 - in /cfe/trunk: include/clang/AST/Stmt.h include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h include/clang/Frontend/PCHWriter.h lib/AST/Stmt.cpp lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp test/PCH/stmts.c test/PCH/stmts.h

Douglas Gregor dgregor at apple.com
Thu Apr 16 17:04:07 PDT 2009


Author: dgregor
Date: Thu Apr 16 19:04:06 2009
New Revision: 69329

URL: http://llvm.org/viewvc/llvm-project?rev=69329&view=rev
Log:
PCH support for the first batch of statements, including null,
compound, case, default, if, switch, and break statements.

Added:
    cfe/trunk/test/PCH/stmts.c
    cfe/trunk/test/PCH/stmts.h
Modified:
    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/AST/Stmt.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Thu Apr 16 19:04:06 2009
@@ -136,11 +136,22 @@
   void operator delete(void*, std::size_t) throw() { }
   void operator delete(void*, void*) throw() { }
 
+public:
+  /// \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 { };
+
 protected:
   /// DestroyChildren - Invoked by destructors of subclasses of Stmt to
   ///  recursively release child AST nodes.
   void DestroyChildren(ASTContext& Ctx);
   
+  /// \brief Construct an empty statement.
+  explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC) { 
+    if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
+  }
+
 public:
   Stmt(StmtClass SC) : sClass(SC) { 
     if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
@@ -211,11 +222,6 @@
     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);
 
@@ -288,7 +294,11 @@
 public:
   NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {}
 
+  /// \brief Build an empty null statement.
+  explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { }
+
   SourceLocation getSemiLoc() const { return SemiLoc; }
+  void setSemiLoc(SourceLocation L) { SemiLoc = L; }
 
   virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
   
@@ -323,9 +333,16 @@
     Body = new (C) Stmt*[NumStmts];
     memcpy(Body, StmtStart, numStmts * sizeof(*Body));
   }           
+
+  // \brief Build an empty compound statement.
+  explicit CompoundStmt(EmptyShell Empty)
+    : Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { }
+
+  void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts);
   
   bool body_empty() const { return NumStmts == 0; }
-  
+  unsigned size() const { return NumStmts; }
+
   typedef Stmt** body_iterator;
   body_iterator body_begin() { return Body; }
   body_iterator body_end() { return Body + NumStmts; }
@@ -360,7 +377,9 @@
   }
   
   SourceLocation getLBracLoc() const { return LBracLoc; }
+  void setLBracLoc(SourceLocation L) { LBracLoc = L; }
   SourceLocation getRBracLoc() const { return RBracLoc; }
+  void setRBracLoc(SourceLocation L) { RBracLoc = L; }
   
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == CompoundStmtClass; 
@@ -418,12 +437,17 @@
     SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
     CaseLoc = caseLoc;
   }
-  
+
+  /// \brief Build an empty switch case statement.
+  explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass) { }
+
   SourceLocation getCaseLoc() const { return CaseLoc; }
-  
+  void setCaseLoc(SourceLocation L) { CaseLoc = L; }
+
   Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
   Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
   Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
+
   const Expr *getLHS() const { 
     return reinterpret_cast<const Expr*>(SubExprs[LHS]); 
   }
@@ -465,11 +489,16 @@
 public:
   DefaultStmt(SourceLocation DL, Stmt *substmt) : 
     SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL) {}
-    
+
+  /// \brief Build an empty default statement.
+  explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { }
+
   Stmt *getSubStmt() { return SubStmt; }
   const Stmt *getSubStmt() const { return SubStmt; }
-    
+  void setSubStmt(Stmt *S) { SubStmt = S; }
+
   SourceLocation getDefaultLoc() const { return DefaultLoc; }
+  void setDefaultLoc(SourceLocation L) { DefaultLoc = L; }
 
   virtual SourceRange getSourceRange() const { 
     return SourceRange(DefaultLoc, SubStmt->getLocEnd()); 
@@ -537,14 +566,23 @@
     IfLoc = IL;
   }
   
+  /// \brief Build an empty if/then/else statement
+  explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
+
   const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+  void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
   const Stmt *getThen() const { return SubExprs[THEN]; }
+  void setThen(Stmt *S) { SubExprs[THEN] = S; } 
   const Stmt *getElse() const { return SubExprs[ELSE]; }
+  void setElse(Stmt *S) { SubExprs[ELSE] = S; }
 
   Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
   Stmt *getThen() { return SubExprs[THEN]; }
   Stmt *getElse() { return SubExprs[ELSE]; }
 
+  SourceLocation getIfLoc() const { return IfLoc; }
+  void setIfLoc(SourceLocation L) { IfLoc = L; }
+
   virtual SourceRange getSourceRange() const { 
     if (SubExprs[ELSE])
       return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
@@ -579,13 +617,22 @@
       SubExprs[BODY] = NULL;
     }
   
+  /// \brief Build a empty switch statement.
+  explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { }
+
   const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
   const Stmt *getBody() const { return SubExprs[BODY]; }
   const SwitchCase *getSwitchCaseList() const { return FirstCase; }
 
   Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+  void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
   Stmt *getBody() { return SubExprs[BODY]; }
+  void setBody(Stmt *S) { SubExprs[BODY] = S; }
   SwitchCase *getSwitchCaseList() { return FirstCase; }
+  void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
+
+  SourceLocation getSwitchLoc() const { return SwitchLoc; }
+  void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
 
   void setBody(Stmt *S, SourceLocation SL) { 
     SubExprs[BODY] = S; 
@@ -814,6 +861,12 @@
 public:
   BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {}
   
+  /// \brief Build an empty break statement.
+  explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { }
+
+  SourceLocation getBreakLoc() const { return BreakLoc; }
+  void setBreakLoc(SourceLocation L) { BreakLoc = L; }
+
   virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
 
   static bool classof(const Stmt *T) { 

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Thu Apr 16 19:04:06 2009
@@ -375,6 +375,20 @@
       STMT_STOP,
       /// \brief A NULL expression.
       STMT_NULL_PTR,
+      /// \brief A NullStmt record.
+      STMT_NULL,
+      /// \brief A CompoundStmt record.
+      STMT_COMPOUND,
+      /// \brief A CaseStmt record.
+      STMT_CASE,
+      /// \brief A DefaultStmt record.
+      STMT_DEFAULT,
+      /// \brief An IfStmt record.
+      STMT_IF,
+      /// \brief A SwitchStmt record.
+      STMT_SWITCH,
+      /// \brief A BreakStmt record.
+      STMT_BREAK,
       /// \brief A PredefinedExpr record.
       EXPR_PREDEFINED,
       /// \brief A DeclRefExpr record.

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Thu Apr 16 19:04:06 2009
@@ -26,6 +26,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Bitcode/BitstreamReader.h"
 #include "llvm/Support/DataTypes.h"
+#include <map>
 #include <string>
 #include <utility>
 #include <vector>
@@ -41,6 +42,7 @@
 class Decl;
 class DeclContext;
 class Preprocessor;
+class SwitchCase;
 
 /// \brief Reads a precompiled head containing the contents of a
 /// translation unit.
@@ -126,6 +128,10 @@
   /// file.
   llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
 
+  /// \brief Mapping from switch-case IDs in the PCH file to
+  /// switch-case statements.
+  std::map<unsigned, SwitchCase *> SwitchCaseStmts;
+
   PCHReadResult ReadPCHBlock();
   bool CheckPredefinesBuffer(const char *PCHPredef, 
                              unsigned PCHPredefLen,
@@ -241,6 +247,13 @@
   /// \brief Retrieve the AST context that this PCH reader
   /// supplements.
   ASTContext &getContext() { return Context; }
+
+  /// \brief Record that the given ID maps to the given switch-case
+  /// statement.
+  void RecordSwitchCaseID(SwitchCase *SC, unsigned ID);
+
+  /// \brief Retrieve the switch-case statement with the given ID.
+  SwitchCase *getSwitchCaseWithID(unsigned ID);
 };
 
 } // end namespace clang

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Thu Apr 16 19:04:06 2009
@@ -20,6 +20,7 @@
 #include "clang/Frontend/PCHBitCodes.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include <map>
 #include <queue>
 
 namespace llvm {
@@ -33,6 +34,7 @@
 class ASTContext;
 class Preprocessor;
 class SourceManager;
+class SwitchCase;
 class TargetInfo;
 
 /// \brief Writes a precompiled header containing the contents of a
@@ -108,6 +110,9 @@
   /// declaration or type.
   llvm::SmallVector<Stmt *, 8> StmtsToEmit;
 
+  /// \brief Mapping from SwitchCase statements to IDs.
+  std::map<SwitchCase *, unsigned> SwitchCaseIDs;
+  
   void WriteTargetTriple(const TargetInfo &Target);
   void WriteLanguageOptions(const LangOptions &LangOpts);
   void WriteSourceManagerBlock(SourceManager &SourceMgr);
@@ -170,6 +175,13 @@
   /// \brief Flush all of the statements and expressions that have
   /// been added to the queue via AddStmt().
   void FlushStmts();
+
+  /// \brief Record an ID for the given switch-case statement.
+  unsigned RecordSwitchCaseID(SwitchCase *S);
+
+  /// \brief Retrieve the ID for the given switch-case statement.
+  unsigned getSwitchCaseID(SwitchCase *S);
+
 };
 
 } // end namespace clang

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=69329&r1=69328&r2=69329&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Thu Apr 16 19:04:06 2009
@@ -96,6 +96,14 @@
   return StatSwitch;
 }
 
+void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
+  if (this->Body)
+    C.Deallocate(Body);
+  this->NumStmts = NumStmts;
+
+  Body = new (C) Stmt*[NumStmts];
+  memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
+}
 
 const char *LabelStmt::getName() const {
   return getID()->getName();

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Thu Apr 16 19:04:06 2009
@@ -139,7 +139,8 @@
 
 void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
   VisitValueDecl(FD);
-  // FIXME: function body
+  if (Record[Idx++])
+    FD->setBody(cast<CompoundStmt>(Reader.ReadStmt()));
   FD->setPreviousDeclaration(
                    cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
   FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
@@ -229,15 +230,28 @@
                   unsigned &Idx, llvm::SmallVectorImpl<Stmt *> &StmtStack)
       : Reader(Reader), Record(Record), Idx(Idx), StmtStack(StmtStack) { }
 
+    /// \brief The number of record fields required for the Stmt class
+    /// itself.
+    static const unsigned NumStmtFields = 0;
+
     /// \brief The number of record fields required for the Expr class
     /// itself.
-    static const unsigned NumExprFields = 3;
+    static const unsigned NumExprFields = NumStmtFields + 3;
 
     // Each of the Visit* functions reads in part of the expression
     // from the given record and the current expression stack, then
     // return the total number of operands that it read from the
     // expression stack.
 
+    unsigned VisitStmt(Stmt *S);
+    unsigned VisitNullStmt(NullStmt *S);
+    unsigned VisitCompoundStmt(CompoundStmt *S);
+    unsigned VisitSwitchCase(SwitchCase *S);
+    unsigned VisitCaseStmt(CaseStmt *S);
+    unsigned VisitDefaultStmt(DefaultStmt *S);
+    unsigned VisitIfStmt(IfStmt *S);
+    unsigned VisitSwitchStmt(SwitchStmt *S);
+    unsigned VisitBreakStmt(BreakStmt *S);
     unsigned VisitExpr(Expr *E);
     unsigned VisitPredefinedExpr(PredefinedExpr *E);
     unsigned VisitDeclRefExpr(DeclRefExpr *E);
@@ -273,7 +287,83 @@
   };
 }
 
+unsigned PCHStmtReader::VisitStmt(Stmt *S) {
+  assert(Idx == NumStmtFields && "Incorrect statement field count");
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitNullStmt(NullStmt *S) {
+  VisitStmt(S);
+  S->setSemiLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) {
+  VisitStmt(S);
+  unsigned NumStmts = Record[Idx++];
+  S->setStmts(Reader.getContext(), 
+              &StmtStack[StmtStack.size() - NumStmts], NumStmts);
+  S->setLBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return NumStmts;
+}
+
+unsigned PCHStmtReader::VisitSwitchCase(SwitchCase *S) {
+  VisitStmt(S);
+  Reader.RecordSwitchCaseID(S, Record[Idx++]);
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitCaseStmt(CaseStmt *S) {
+  VisitSwitchCase(S);
+  S->setLHS(cast<Expr>(StmtStack[StmtStack.size() - 3]));
+  S->setRHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
+  S->setSubStmt(StmtStack.back());
+  S->setCaseLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 3;
+}
+
+unsigned PCHStmtReader::VisitDefaultStmt(DefaultStmt *S) {
+  VisitSwitchCase(S);
+  S->setSubStmt(StmtStack.back());
+  S->setDefaultLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitIfStmt(IfStmt *S) {
+  VisitStmt(S);
+  S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3]));
+  S->setThen(StmtStack[StmtStack.size() - 2]);
+  S->setElse(StmtStack[StmtStack.size() - 1]);
+  S->setIfLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 3;
+}
+
+unsigned PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) {
+  VisitStmt(S);
+  S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 2]));
+  S->setBody(StmtStack.back());
+  S->setSwitchLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  SwitchCase *PrevSC = 0;
+  for (unsigned N = Record.size(); Idx != N; ++Idx) {
+    SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]);
+    if (PrevSC)
+      PrevSC->setNextSwitchCase(SC);
+    else
+      S->setSwitchCaseList(SC);
+    PrevSC = SC;
+  }
+  return 2;
+}
+
+unsigned PCHStmtReader::VisitBreakStmt(BreakStmt *S) {
+  VisitStmt(S);
+  S->setBreakLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
 unsigned PCHStmtReader::VisitExpr(Expr *E) {
+  VisitStmt(E);
   E->setType(Reader.GetType(Record[Idx++]));
   E->setTypeDependent(Record[Idx++]);
   E->setValueDependent(Record[Idx++]);
@@ -2002,6 +2092,34 @@
       S = 0; 
       break;
 
+    case pch::STMT_NULL:
+      S = new (Context) NullStmt(Empty);
+      break;
+
+    case pch::STMT_COMPOUND:
+      S = new (Context) CompoundStmt(Empty);
+      break;
+
+    case pch::STMT_CASE:
+      S = new (Context) CaseStmt(Empty);
+      break;
+
+    case pch::STMT_DEFAULT:
+      S = new (Context) DefaultStmt(Empty);
+      break;
+
+    case pch::STMT_IF:
+      S = new (Context) IfStmt(Empty);
+      break;
+
+    case pch::STMT_SWITCH:
+      S = new (Context) SwitchStmt(Empty);
+      break;
+
+    case pch::STMT_BREAK:
+      S = new (Context) BreakStmt(Empty);
+      break;
+
     case pch::EXPR_PREDEFINED:
       // FIXME: untested (until we can serialize function bodies).
       S = new (Context) PredefinedExpr(Empty);
@@ -2157,3 +2275,16 @@
                                                   Context.getSourceManager()),
                                     DiagID);
 }
+
+/// \brief Record that the given ID maps to the given switch-case
+/// statement.
+void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
+  assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
+  SwitchCaseStmts[ID] = SC;
+}
+
+/// \brief Retrieve the switch-case statement with the given ID.
+SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
+  assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
+  return SwitchCaseStmts[ID];
+}

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Thu Apr 16 19:04:06 2009
@@ -338,7 +338,9 @@
 
 void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
   VisitValueDecl(D);
-  // FIXME: function body
+  Record.push_back(D->isThisDeclarationADefinition());
+  if (D->isThisDeclarationADefinition())
+    Writer.AddStmt(D->getBody());
   Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
   Record.push_back(D->getStorageClass()); // FIXME: stable encoding
   Record.push_back(D->isInline());
@@ -443,6 +445,15 @@
     PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
       : Writer(Writer), Record(Record) { }
 
+    void VisitStmt(Stmt *S);
+    void VisitNullStmt(NullStmt *S);
+    void VisitCompoundStmt(CompoundStmt *S);
+    void VisitSwitchCase(SwitchCase *S);
+    void VisitCaseStmt(CaseStmt *S);
+    void VisitDefaultStmt(DefaultStmt *S);
+    void VisitIfStmt(IfStmt *S);
+    void VisitSwitchStmt(SwitchStmt *S);
+    void VisitBreakStmt(BreakStmt *S);
     void VisitExpr(Expr *E);
     void VisitPredefinedExpr(PredefinedExpr *E);
     void VisitDeclRefExpr(DeclRefExpr *E);
@@ -478,7 +489,75 @@
   };
 }
 
+void PCHStmtWriter::VisitStmt(Stmt *S) { 
+}
+
+void PCHStmtWriter::VisitNullStmt(NullStmt *S) {
+  VisitStmt(S);
+  Writer.AddSourceLocation(S->getSemiLoc(), Record);
+  Code = pch::STMT_NULL;
+}
+
+void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
+  VisitStmt(S);
+  Record.push_back(S->size());
+  for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end();
+       CS != CSEnd; ++CS)
+    Writer.WriteSubStmt(*CS);
+  Writer.AddSourceLocation(S->getLBracLoc(), Record);
+  Writer.AddSourceLocation(S->getRBracLoc(), Record);
+  Code = pch::STMT_COMPOUND;
+}
+
+void PCHStmtWriter::VisitSwitchCase(SwitchCase *S) {
+  VisitStmt(S);
+  Record.push_back(Writer.RecordSwitchCaseID(S));
+}
+
+void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) {
+  VisitSwitchCase(S);
+  Writer.WriteSubStmt(S->getLHS());
+  Writer.WriteSubStmt(S->getRHS());
+  Writer.WriteSubStmt(S->getSubStmt());
+  Writer.AddSourceLocation(S->getCaseLoc(), Record);
+  Code = pch::STMT_CASE;
+}
+
+void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
+  VisitSwitchCase(S);
+  Writer.WriteSubStmt(S->getSubStmt());
+  Writer.AddSourceLocation(S->getDefaultLoc(), Record);
+  Code = pch::STMT_DEFAULT;
+}
+
+void PCHStmtWriter::VisitIfStmt(IfStmt *S) {
+  VisitStmt(S);
+  Writer.WriteSubStmt(S->getCond());
+  Writer.WriteSubStmt(S->getThen());
+  Writer.WriteSubStmt(S->getElse());
+  Writer.AddSourceLocation(S->getIfLoc(), Record);
+  Code = pch::STMT_IF;
+}
+
+void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
+  VisitStmt(S);
+  Writer.WriteSubStmt(S->getCond());
+  Writer.WriteSubStmt(S->getBody());
+  Writer.AddSourceLocation(S->getSwitchLoc(), Record);
+  for (SwitchCase *SC = S->getSwitchCaseList(); SC; 
+       SC = SC->getNextSwitchCase())
+    Record.push_back(Writer.getSwitchCaseID(SC));
+  Code = pch::STMT_SWITCH;
+}
+
+void PCHStmtWriter::VisitBreakStmt(BreakStmt *S) {
+  VisitStmt(S);
+  Writer.AddSourceLocation(S->getBreakLoc(), Record);
+  Code = pch::STMT_BREAK;
+}
+
 void PCHStmtWriter::VisitExpr(Expr *E) {
+  VisitStmt(E);
   Writer.AddTypeRef(E->getType(), Record);
   Record.push_back(E->isTypeDependent());
   Record.push_back(E->isValueDependent());
@@ -1708,3 +1787,17 @@
 
   StmtsToEmit.clear();
 }
+
+unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) {
+  assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && 
+         "SwitchCase recorded twice");
+  unsigned NextID = SwitchCaseIDs.size();
+  SwitchCaseIDs[S] = NextID;
+  return NextID;
+}
+
+unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) {
+  assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() && 
+         "SwitchCase hasn't been seen yet");
+  return SwitchCaseIDs[S];
+}

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

==============================================================================
--- cfe/trunk/test/PCH/stmts.c (added)
+++ cfe/trunk/test/PCH/stmts.c Thu Apr 16 19:04:06 2009
@@ -0,0 +1,8 @@
+// Test this without pch.
+// RUN: clang-cc -fblocks -include %S/stmts.h -fsyntax-only -emit-llvm -o - %s
+
+// Test with pch.
+// RUN: clang-cc -emit-pch -fblocks -o %t %S/stmts.h &&
+// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -emit-llvm -o - %s 
+
+void g0(void) { f0(5); }

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

==============================================================================
--- cfe/trunk/test/PCH/stmts.h (added)
+++ cfe/trunk/test/PCH/stmts.h Thu Apr 16 19:04:06 2009
@@ -0,0 +1,22 @@
+// Header for PCH test stmts.c
+
+void f0(int x) { 
+  // NullStmt
+  ;
+  // IfStmt
+  if (x) {
+  } else if (x + 1) {
+  }
+
+  switch (x) {
+  case 0:
+    x = 17;
+    break;
+
+  case 1:
+    break;
+
+  default:
+    break;
+  }
+}





More information about the cfe-commits mailing list