[cfe-commits] r69101 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHWriter.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp test/PCH/enum.h tools/clang-cc/ASTConsumers.cpp

Douglas Gregor dgregor at apple.com
Tue Apr 14 16:32:43 PDT 2009


Author: dgregor
Date: Tue Apr 14 18:32:43 2009
New Revision: 69101

URL: http://llvm.org/viewvc/llvm-project?rev=69101&view=rev
Log:
Add PCH support for ImplicitCastExprs. This is the first expression
kind PCH handles that has an expression as an operand, so most of this
work is in the infrastructure to rebuild expression trees from the
serialized representation. We now store expressions in post-order
(e.g., Reverse Polish Notation), so that we can easily rebuild the
appropriate expression tree.


Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/include/clang/Frontend/PCHWriter.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/test/PCH/enum.h
    cfe/trunk/tools/clang-cc/ASTConsumers.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Apr 14 18:32:43 2009
@@ -1116,10 +1116,15 @@
          ty->isDependentType() || (op && op->isValueDependent())), 
     Op(op) {}
   
+  /// \brief Construct an empty cast.
+  CastExpr(StmtClass SC, EmptyShell Empty) 
+    : Expr(SC, Empty) { }
+  
 public:
   Expr *getSubExpr() { return cast<Expr>(Op); }
   const Expr *getSubExpr() const { return cast<Expr>(Op); }
-  
+  void setSubExpr(Expr *E) { Op = E; }
+
   static bool classof(const Stmt *T) { 
     StmtClass SC = T->getStmtClass();
     if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass)
@@ -1161,6 +1166,11 @@
   ImplicitCastExpr(QualType ty, Expr *op, bool Lvalue) : 
     CastExpr(ImplicitCastExprClass, ty, op), LvalueCast(Lvalue) { }
 
+  /// \brief Construct an empty implicit cast.
+  explicit ImplicitCastExpr(EmptyShell Shell) 
+    : CastExpr(ImplicitCastExprClass, Shell) { }
+
+
   virtual SourceRange getSourceRange() const {
     return getSubExpr()->getSourceRange();
   }

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Tue Apr 14 18:32:43 2009
@@ -368,8 +368,11 @@
     /// 100. Each constant describes a record for a specific
     /// statement or expression class in the AST.
     enum StmtCode {
+      /// \brief A marker record that indicates that we are at the end
+      /// of an expression.
+      EXPR_STOP,
       /// \brief A NULL expression.
-      EXPR_NULL = 100,
+      EXPR_NULL,
       /// \brief A PredefinedExpr record.
       EXPR_PREDEFINED,
       /// \brief A DeclRefExpr record.
@@ -379,7 +382,9 @@
       /// \brief A FloatingLiteral record.
       EXPR_FLOATING_LITERAL,
       /// \brief A CharacterLiteral record.
-      EXPR_CHARACTER_LITERAL
+      EXPR_CHARACTER_LITERAL,
+      /// \brief An ImplicitCastExpr record.
+      EXPR_IMPLICIT_CAST
     };
     /// @}
   }

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Tue Apr 14 18:32:43 2009
@@ -106,10 +106,7 @@
 
   /// \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;
+  llvm::SmallVector<Expr *, 8> ExprsToEmit;
 
   void WriteTargetTriple(const TargetInfo &Target);
   void WriteLanguageOptions(const LangOptions &LangOpts);
@@ -156,7 +153,16 @@
 
   /// \brief Add the given expression to the queue of expressions to
   /// emit.
-  void AddExpr(Expr *E) { ExprsToEmit.push(E); }
+  ///
+  /// This routine should be used when emitting types and declarations
+  /// that have expressions as part of their formulation. Once the
+  /// type or declaration has been written, call FlushExprs() to write
+  /// the corresponding expressions just after the type or
+  /// declaration.
+  void AddExpr(Expr *E) { ExprsToEmit.push_back(E); }
+
+  /// \brief Write the given subexpression to the bitstream.
+  void WriteSubExpr(Expr *E);
 
   /// \brief Flush all of the expressions that have been added to the
   /// queue via AddExpr().

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Apr 14 18:32:43 2009
@@ -215,61 +215,87 @@
 //===----------------------------------------------------------------------===//
 namespace {
   class VISIBILITY_HIDDEN PCHStmtReader 
-    : public StmtVisitor<PCHStmtReader, void> {
+    : public StmtVisitor<PCHStmtReader, unsigned> {
     PCHReader &Reader;
     const PCHReader::RecordData &Record;
     unsigned &Idx;
+    llvm::SmallVectorImpl<Expr *> &ExprStack;
 
   public:
     PCHStmtReader(PCHReader &Reader, const PCHReader::RecordData &Record,
-                  unsigned &Idx)
-      : Reader(Reader), Record(Record), Idx(Idx) { }
+                  unsigned &Idx, llvm::SmallVectorImpl<Expr *> &ExprStack)
+      : Reader(Reader), Record(Record), Idx(Idx), ExprStack(ExprStack) { }
 
-    void VisitExpr(Expr *E);
-    void VisitPredefinedExpr(PredefinedExpr *E);
-    void VisitDeclRefExpr(DeclRefExpr *E);
-    void VisitIntegerLiteral(IntegerLiteral *E);
-    void VisitFloatingLiteral(FloatingLiteral *E);
-    void VisitCharacterLiteral(CharacterLiteral *E);
+    // 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 VisitExpr(Expr *E);
+    unsigned VisitPredefinedExpr(PredefinedExpr *E);
+    unsigned VisitDeclRefExpr(DeclRefExpr *E);
+    unsigned VisitIntegerLiteral(IntegerLiteral *E);
+    unsigned VisitFloatingLiteral(FloatingLiteral *E);
+    unsigned VisitCharacterLiteral(CharacterLiteral *E);
+    unsigned VisitCastExpr(CastExpr *E);
+    unsigned VisitImplicitCastExpr(ImplicitCastExpr *E);
   };
 }
 
-void PCHStmtReader::VisitExpr(Expr *E) {
+unsigned PCHStmtReader::VisitExpr(Expr *E) {
   E->setType(Reader.GetType(Record[Idx++]));
   E->setTypeDependent(Record[Idx++]);
   E->setValueDependent(Record[Idx++]);
+  return 0;
 }
 
-void PCHStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
+unsigned PCHStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
   VisitExpr(E);
   E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
   E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]);
+  return 0;
 }
 
-void PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
+unsigned PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
   VisitExpr(E);
   E->setDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
   E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
 }
 
-void PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
+unsigned PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
   VisitExpr(E);
   E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
   E->setValue(Reader.ReadAPInt(Record, Idx));
+  return 0;
 }
 
-void PCHStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
+unsigned PCHStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
   VisitExpr(E);
   E->setValue(Reader.ReadAPFloat(Record, Idx));
   E->setExact(Record[Idx++]);
   E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
 }
 
-void PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
+unsigned PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
   VisitExpr(E);
   E->setValue(Record[Idx++]);
   E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
   E->setWide(Record[Idx++]);
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitCastExpr(CastExpr *E) {
+  VisitExpr(E);
+  E->setSubExpr(ExprStack.back());
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+  VisitCastExpr(E);
+  E->setLvalueCast(Record[Idx++]);
+  return 1;
 }
 
 // FIXME: use the diagnostics machinery
@@ -1507,46 +1533,100 @@
 }
 
 Expr *PCHReader::ReadExpr() {
+  // Within the bitstream, expressions are stored in Reverse Polish
+  // Notation, with each of the subexpressions preceding the
+  // expression they are stored in. To evaluate expressions, we
+  // continue reading expressions and placing them on the stack, with
+  // expressions having operands removing those operands from the
+  // stack. Evaluation terminates when we see a EXPR_STOP record, and
+  // the single remaining expression on the stack is our result.
   RecordData Record;
-  unsigned Code = Stream.ReadCode();
-  unsigned Idx = 0;
-  PCHStmtReader Reader(*this, Record, Idx);
+  unsigned Idx;
+  llvm::SmallVector<Expr *, 16> ExprStack;
+  PCHStmtReader Reader(*this, Record, Idx, ExprStack);
   Stmt::EmptyShell Empty;
 
-  Expr *E = 0;
-  switch ((pch::StmtCode)Stream.ReadRecord(Code, Record)) {
-  case pch::EXPR_NULL: 
-    E = 0; 
-    break;
+  while (true) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd()) {
+        Error("Error at end of Source Manager block");
+        return 0;
+      }
+      break;
+    }
 
-  case pch::EXPR_PREDEFINED:
-    // FIXME: untested (until we can serialize function bodies).
-    E = new (Context) PredefinedExpr(Empty);
-    break;
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock()) {
+        Error("Malformed block record");
+        return 0;
+      }
+      continue;
+    }
 
-  case pch::EXPR_DECL_REF: 
-    E = new (Context) DeclRefExpr(Empty); 
-    break;
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
 
-  case pch::EXPR_INTEGER_LITERAL: 
-    E = new (Context) IntegerLiteral(Empty);
-    break;
+    Expr *E = 0;
+    Idx = 0;
+    Record.clear();
+    bool Finished = false;
+    switch ((pch::StmtCode)Stream.ReadRecord(Code, Record)) {
+    case pch::EXPR_STOP:
+      Finished = true;
+      break;
 
-  case pch::EXPR_FLOATING_LITERAL:
-    E = new (Context) FloatingLiteral(Empty);
-    break;
+    case pch::EXPR_NULL: 
+      E = 0; 
+      break;
 
-  case pch::EXPR_CHARACTER_LITERAL:
-    E = new (Context) CharacterLiteral(Empty);
-    break;
-  }
+    case pch::EXPR_PREDEFINED:
+      // FIXME: untested (until we can serialize function bodies).
+      E = new (Context) PredefinedExpr(Empty);
+      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_FLOATING_LITERAL:
+      E = new (Context) FloatingLiteral(Empty);
+      break;
+      
+    case pch::EXPR_CHARACTER_LITERAL:
+      E = new (Context) CharacterLiteral(Empty);
+      break;
 
-  if (E)
-    Reader.Visit(E);
+    case pch::EXPR_IMPLICIT_CAST:
+      E = new (Context) ImplicitCastExpr(Empty);
+      break;
+    }
+
+    // We hit an EXPR_STOP, so we're done with this expression.
+    if (Finished)
+      break;
 
-  assert(Idx == Record.size() && "Invalid deserialization of expression");
+    if (E) {
+      unsigned NumSubExprs = Reader.Visit(E);
+      while (NumSubExprs > 0) {
+        ExprStack.pop_back();
+        --NumSubExprs;
+      }
+    }
 
-  return E;
+    assert(Idx == Record.size() && "Invalid deserialization of expression");
+    ExprStack.push_back(E);
+  }
+  assert(ExprStack.size() == 1 && "Extra expressions on stack!");
+  return ExprStack.back();
 }
 
 DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Apr 14 18:32:43 2009
@@ -449,6 +449,8 @@
     void VisitIntegerLiteral(IntegerLiteral *E);
     void VisitFloatingLiteral(FloatingLiteral *E);
     void VisitCharacterLiteral(CharacterLiteral *E);
+    void VisitCastExpr(CastExpr *E);
+    void VisitImplicitCastExpr(ImplicitCastExpr *E);
   };
 }
 
@@ -495,6 +497,17 @@
   Code = pch::EXPR_CHARACTER_LITERAL;
 }
 
+void PCHStmtWriter::VisitCastExpr(CastExpr *E) {
+  VisitExpr(E);
+  Writer.WriteSubExpr(E->getSubExpr());
+}
+
+void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+  VisitCastExpr(E);
+  Record.push_back(E->isLvalueCast());
+  Code = pch::EXPR_IMPLICIT_CAST;
+}
+
 //===----------------------------------------------------------------------===//
 // PCHWriter Implementation
 //===----------------------------------------------------------------------===//
@@ -1245,16 +1258,32 @@
   }
 }
 
+/// \brief Write the given subexpression to the bitstream.
+void PCHWriter::WriteSubExpr(Expr *E) {
+  RecordData Record;
+  PCHStmtWriter Writer(*this, Record);
+
+  if (!E) {
+    S.EmitRecord(pch::EXPR_NULL, Record);
+    return;
+  }
+  
+  Writer.Code = pch::EXPR_NULL;
+  Writer.Visit(E);
+  assert(Writer.Code != pch::EXPR_NULL && 
+         "Unhandled expression writing PCH file");
+  S.EmitRecord(Writer.Code, Record);    
+}
+
 /// \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();
+  for (unsigned I = 0, N = ExprsToEmit.size(); I != N; ++I) {
+    Expr *E = ExprsToEmit[I];
+
     if (!E) {
       S.EmitRecord(pch::EXPR_NULL, Record);
       continue;
@@ -1265,5 +1294,16 @@
     assert(Writer.Code != pch::EXPR_NULL && 
            "Unhandled expression writing PCH file");
     S.EmitRecord(Writer.Code, Record);  
+
+    assert(N == ExprsToEmit.size() && 
+           "Subexpression writen via AddExpr rather than WriteSubExpr!");
+
+    // Note that we are at the end of a full expression. Any
+    // expression records that follow this one are part of a different
+    // expression.
+    Record.clear();
+    S.EmitRecord(pch::EXPR_STOP, Record);
   }
+
+  ExprsToEmit.clear();
 }

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

==============================================================================
--- cfe/trunk/test/PCH/enum.h (original)
+++ cfe/trunk/test/PCH/enum.h Tue Apr 14 18:32:43 2009
@@ -13,4 +13,4 @@
   Circle
 };
 
-enum Shape aRoundShape;// FIXME: = Circle;
+enum Shape aRoundShape = Circle;

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

==============================================================================
--- cfe/trunk/tools/clang-cc/ASTConsumers.cpp (original)
+++ cfe/trunk/tools/clang-cc/ASTConsumers.cpp Tue Apr 14 18:32:43 2009
@@ -190,7 +190,14 @@
     std::string Name = ND->getNameAsString();
     // This forms: "int a".
     dyn_cast<ValueDecl>(ND)->getType().getAsStringInternal(Name);
-    Out << Name << ";\n";
+    Out << Name;
+    if (VarDecl *Var = dyn_cast<VarDecl>(ND)) {
+      if (Var->getInit()) {
+        Out << " = ";
+        Var->getInit()->printPretty(Out);
+      }
+    }
+    Out << ";\n";
     break;
   }
   case Decl::Namespace:





More information about the cfe-commits mailing list