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

Douglas Gregor dgregor at apple.com
Fri Apr 17 11:58:21 PDT 2009


Author: dgregor
Date: Fri Apr 17 13:58:21 2009
New Revision: 69369

URL: http://llvm.org/viewvc/llvm-project?rev=69369&view=rev
Log:
PCH support for indirect gotos and address-of-label expressions.

Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/test/PCH/stmts.c
    cfe/trunk/test/PCH/stmts.h

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

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Fri Apr 17 13:58:21 2009
@@ -1601,12 +1601,22 @@
                 QualType t)
     : Expr(AddrLabelExprClass, t), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
   
+  /// \brief Build an empty address of a label expression.
+  explicit AddrLabelExpr(EmptyShell Empty) 
+    : Expr(AddrLabelExprClass, Empty) { }
+
+  SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; }
+  void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; }
+  SourceLocation getLabelLoc() const { return LabelLoc; }
+  void setLabelLoc(SourceLocation L) { LabelLoc = L; }
+
   virtual SourceRange getSourceRange() const {
     return SourceRange(AmpAmpLoc, LabelLoc);
   }
   
   LabelStmt *getLabel() const { return Label; }
-  
+  void setLabel(LabelStmt *S) { Label = S; }
+
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == AddrLabelExprClass; 
   }

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

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Fri Apr 17 13:58:21 2009
@@ -852,13 +852,18 @@
 class IndirectGotoStmt : public Stmt {
   Stmt *Target;
   // FIXME: Add location information (e.g. SourceLocation objects).
-  //        When doing so, update the serialization routines.
+  //        When doing so, update the PCH serialization routines.
 public:
   IndirectGotoStmt(Expr *target) : Stmt(IndirectGotoStmtClass),
                                    Target((Stmt*)target){}
+
+  /// \brief Build an empty indirect goto statement.
+  explicit IndirectGotoStmt(EmptyShell Empty) 
+    : Stmt(IndirectGotoStmtClass, Empty) { }
   
   Expr *getTarget();
   const Expr *getTarget() const;
+  void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
 
   virtual SourceRange getSourceRange() const { return SourceRange(); }
   

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Fri Apr 17 13:58:21 2009
@@ -397,6 +397,8 @@
       STMT_FOR,
       /// \brief A GotoStmt record.
       STMT_GOTO,
+      /// \brief An IndirectGotoStmt record.
+      STMT_INDIRECT_GOTO,
       /// \brief A ContinueStmt record.
       STMT_CONTINUE,
       /// \brief A BreakStmt record.
@@ -405,6 +407,7 @@
       STMT_RETURN,
       /// \brief A DeclStmt record.
       STMT_DECL,
+      /// FIXME: An AsmStmt record.
       /// \brief A PredefinedExpr record.
       EXPR_PREDEFINED,
       /// \brief A DeclRefExpr record.
@@ -453,7 +456,8 @@
       EXPR_IMPLICIT_VALUE_INIT,
       /// \brief A VAArgExpr record.
       EXPR_VA_ARG,
-      // FIXME: AddrLabelExpr
+      // An AddrLabelExpr record.
+      EXPR_ADDR_LABEL,
       // FIXME: StmtExpr
       /// \brief A TypesCompatibleExpr record.
       EXPR_TYPES_COMPATIBLE,

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Fri Apr 17 13:58:21 2009
@@ -37,6 +37,7 @@
 
 namespace clang {
 
+class AddrLabelExpr;
 class ASTContext;
 class Attr;
 class Decl;
@@ -143,6 +144,11 @@
   /// de-serialized.
   std::multimap<unsigned, GotoStmt *> UnresolvedGotoStmts;
 
+  /// \brief Mapping from label IDs to the set of address label
+  /// expressions that point to that label before the label itself has
+  /// been de-serialized.
+  std::multimap<unsigned, AddrLabelExpr *> UnresolvedAddrLabelExprs;
+
   PCHReadResult ReadPCHBlock();
   bool CheckPredefinesBuffer(const char *PCHPredef, 
                              unsigned PCHPredefLen,
@@ -278,6 +284,15 @@
   /// immediately (updating the statement) or it may queue the
   /// statement to be back-patched later.
   void SetLabelOf(GotoStmt *S, unsigned ID);
+
+  /// \brief Set the label of the given expression to the label
+  /// identified by ID.
+  ///
+  /// Depending on the order in which the label and other statements
+  /// referencing that label occur, this operation may complete
+  /// immediately (updating the statement) or it may queue the
+  /// statement to be back-patched later.
+  void SetLabelOf(AddrLabelExpr *S, unsigned ID);
 };
 
 } // end namespace clang

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Fri Apr 17 13:58:21 2009
@@ -256,6 +256,7 @@
     unsigned VisitDoStmt(DoStmt *S);
     unsigned VisitForStmt(ForStmt *S);
     unsigned VisitGotoStmt(GotoStmt *S);
+    unsigned VisitIndirectGotoStmt(IndirectGotoStmt *S);
     unsigned VisitContinueStmt(ContinueStmt *S);
     unsigned VisitBreakStmt(BreakStmt *S);
     unsigned VisitReturnStmt(ReturnStmt *S);
@@ -287,6 +288,7 @@
     unsigned VisitDesignatedInitExpr(DesignatedInitExpr *E);
     unsigned VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
     unsigned VisitVAArgExpr(VAArgExpr *E);
+    unsigned VisitAddrLabelExpr(AddrLabelExpr *E);
     unsigned VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
     unsigned VisitChooseExpr(ChooseExpr *E);
     unsigned VisitGNUNullExpr(GNUNullExpr *E);
@@ -407,6 +409,12 @@
   return 0;
 }
 
+unsigned PCHStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+  VisitStmt(S);
+  S->setTarget(cast_or_null<Expr>(StmtStack.back()));
+  return 1;
+}
+
 unsigned PCHStmtReader::VisitContinueStmt(ContinueStmt *S) {
   VisitStmt(S);
   S->setContinueLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -733,6 +741,14 @@
   return 1;
 }
 
+unsigned PCHStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
+  VisitExpr(E);
+  E->setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  Reader.SetLabelOf(E, Record[Idx++]);
+  return 0;
+}
+
 unsigned PCHStmtReader::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
   VisitExpr(E);
   E->setArgType1(Reader.GetType(Record[Idx++]));
@@ -2218,6 +2234,10 @@
     case pch::STMT_GOTO:
       S = new (Context) GotoStmt(Empty);
       break;
+      
+    case pch::STMT_INDIRECT_GOTO:
+      S = new (Context) IndirectGotoStmt(Empty);
+      break;
 
     case pch::STMT_CONTINUE:
       S = new (Context) ContinueStmt(Empty);
@@ -2335,6 +2355,10 @@
       S = new (Context) VAArgExpr(Empty);
       break;
 
+    case pch::EXPR_ADDR_LABEL:
+      S = new (Context) AddrLabelExpr(Empty);
+      break;
+
     case pch::EXPR_TYPES_COMPATIBLE:
       S = new (Context) TypesCompatibleExpr(Empty);
       break;
@@ -2418,6 +2442,16 @@
   for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
     Goto->second->setLabel(S);
   UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
+
+  // If we've already seen any address-label statements that point to
+  // this label, resolve them now.
+  typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
+  std::pair<AddrLabelIter, AddrLabelIter> AddrLabels 
+    = UnresolvedAddrLabelExprs.equal_range(ID);
+  for (AddrLabelIter AddrLabel = AddrLabels.first; 
+       AddrLabel != AddrLabels.second; ++AddrLabel)
+    AddrLabel->second->setLabel(S);
+  UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
 }
 
 /// \brief Set the label of the given statement to the label
@@ -2439,3 +2473,23 @@
     UnresolvedGotoStmts.insert(std::make_pair(ID, S));
   }
 }
+
+/// \brief Set the label of the given expression to the label
+/// identified by ID.
+///
+/// Depending on the order in which the label and other statements
+/// referencing that label occur, this operation may complete
+/// immediately (updating the statement) or it may queue the
+/// statement to be back-patched later.
+void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
+  std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
+  if (Label != LabelStmts.end()) {
+    // We've already seen this label, so set the label of the
+    // label-address expression and we're done.
+    S->setLabel(Label->second);
+  } else {
+    // We haven't seen this label yet, so add this label-address
+    // expression to the set of unresolved label-address expressions.
+    UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
+  }
+}

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Fri Apr 17 13:58:21 2009
@@ -458,6 +458,7 @@
     void VisitDoStmt(DoStmt *S);
     void VisitForStmt(ForStmt *S);
     void VisitGotoStmt(GotoStmt *S);
+    void VisitIndirectGotoStmt(IndirectGotoStmt *S);
     void VisitContinueStmt(ContinueStmt *S);
     void VisitBreakStmt(BreakStmt *S);
     void VisitReturnStmt(ReturnStmt *S);
@@ -489,6 +490,7 @@
     void VisitDesignatedInitExpr(DesignatedInitExpr *E);
     void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
     void VisitVAArgExpr(VAArgExpr *E);
+    void VisitAddrLabelExpr(AddrLabelExpr *E);
     void VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
     void VisitChooseExpr(ChooseExpr *E);
     void VisitGNUNullExpr(GNUNullExpr *E);
@@ -601,6 +603,12 @@
   Code = pch::STMT_GOTO;
 }
 
+void PCHStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+  VisitStmt(S);
+  Writer.WriteSubStmt(S->getTarget());
+  Code = pch::STMT_INDIRECT_GOTO;
+}
+
 void PCHStmtWriter::VisitContinueStmt(ContinueStmt *S) {
   VisitStmt(S);
   Writer.AddSourceLocation(S->getContinueLoc(), Record);
@@ -880,6 +888,14 @@
   Code = pch::EXPR_VA_ARG;
 }
 
+void PCHStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getAmpAmpLoc(), Record);
+  Writer.AddSourceLocation(E->getLabelLoc(), Record);
+  Record.push_back(Writer.GetLabelID(E->getLabel()));
+  Code = pch::EXPR_ADDR_LABEL;
+}
+
 void PCHStmtWriter::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
   VisitExpr(E);
   Writer.AddTypeRef(E->getArgType1(), Record);

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

==============================================================================
--- cfe/trunk/test/PCH/stmts.c (original)
+++ cfe/trunk/test/PCH/stmts.c Fri Apr 17 13:58:21 2009
@@ -8,3 +8,5 @@
 void g0(void) { f0(5); }
 int g1(int x) { return f1(x); }
 const char* query_name(void) { return what_is_my_name(); }
+
+int use_computed_goto(int x) { return computed_goto(x); }

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

==============================================================================
--- cfe/trunk/test/PCH/stmts.h (original)
+++ cfe/trunk/test/PCH/stmts.h Fri Apr 17 13:58:21 2009
@@ -68,3 +68,21 @@
 }
 
 const char* what_is_my_name(void) { return __func__; }
+
+int computed_goto(int x) {
+ start:
+  x = x << 1;
+  void *location = &&start;
+
+  if (x > 17)
+    location = &&done;
+
+  while (x > 12) {
+    --x;
+    if (x == 15)
+      goto *location;
+  }
+
+  done:
+  return 5;
+}





More information about the cfe-commits mailing list