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

Douglas Gregor dgregor at apple.com
Fri Apr 17 11:18:49 PDT 2009


Author: dgregor
Date: Fri Apr 17 13:18:49 2009
New Revision: 69364

URL: http://llvm.org/viewvc/llvm-project?rev=69364&view=rev
Log:
PCH support for labels and goto.

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/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/test/PCH/stmts.h

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

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Fri Apr 17 13:18:49 2009
@@ -530,13 +530,16 @@
   LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt) 
     : Stmt(LabelStmtClass), Label(label), 
       SubStmt(substmt), IdentLoc(IL) {}
+
+  // \brief Build an empty label statement.
+  explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
   
   SourceLocation getIdentLoc() const { return IdentLoc; }
   IdentifierInfo *getID() const { return Label; }
+  void setID(IdentifierInfo *II) { Label = II; }
   const char *getName() const;
   Stmt *getSubStmt() { return SubStmt; }
   const Stmt *getSubStmt() const { return SubStmt; }
-
   void setIdentLoc(SourceLocation L) { IdentLoc = L; }
   void setSubStmt(Stmt *SS) { SubStmt = SS; }
 
@@ -817,7 +820,16 @@
   GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL) 
     : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
   
+  /// \brief Build an empty goto statement.
+  explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { }
+
   LabelStmt *getLabel() const { return Label; }
+  void setLabel(LabelStmt *S) { Label = S; }
+
+  SourceLocation getGotoLoc() const { return GotoLoc; }
+  void setGotoLoc(SourceLocation L) { GotoLoc = L; }
+  SourceLocation getLabelLoc() const { return LabelLoc; }
+  void setLabelLoc(SourceLocation L) { LabelLoc = L; }
 
   virtual SourceRange getSourceRange() const { 
     return SourceRange(GotoLoc, LabelLoc); 

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Fri Apr 17 13:18:49 2009
@@ -383,6 +383,8 @@
       STMT_CASE,
       /// \brief A DefaultStmt record.
       STMT_DEFAULT,
+      /// \brief A LabelStmt record.
+      STMT_LABEL,
       /// \brief An IfStmt record.
       STMT_IF,
       /// \brief A SwitchStmt record.
@@ -393,6 +395,8 @@
       STMT_DO,
       /// \brief A ForStmt record.
       STMT_FOR,
+      /// \brief A GotoStmt record.
+      STMT_GOTO,
       /// \brief A ContinueStmt record.
       STMT_CONTINUE,
       /// \brief A BreakStmt record.

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Fri Apr 17 13:18:49 2009
@@ -41,6 +41,8 @@
 class Attr;
 class Decl;
 class DeclContext;
+class GotoStmt;
+class LabelStmt;
 class Preprocessor;
 class SwitchCase;
 
@@ -132,6 +134,15 @@
   /// switch-case statements.
   std::map<unsigned, SwitchCase *> SwitchCaseStmts;
 
+  /// \brief Mapping from label statement IDs in the PCH file to label
+  /// statements.
+  std::map<unsigned, LabelStmt *> LabelStmts;
+
+  /// \brief Mapping from label IDs to the set of "goto" statements
+  /// that point to that label before the label itself has been
+  /// de-serialized.
+  std::multimap<unsigned, GotoStmt *> UnresolvedGotoStmts;
+
   PCHReadResult ReadPCHBlock();
   bool CheckPredefinesBuffer(const char *PCHPredef, 
                              unsigned PCHPredefLen,
@@ -254,6 +265,19 @@
 
   /// \brief Retrieve the switch-case statement with the given ID.
   SwitchCase *getSwitchCaseWithID(unsigned ID);
+
+  /// \brief Record that the given label statement has been
+  /// deserialized and has the given ID.
+  void RecordLabelStmt(LabelStmt *S, unsigned ID);
+
+  /// \brief Set the label of the given statement 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(GotoStmt *S, 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=69364&r1=69363&r2=69364&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Fri Apr 17 13:18:49 2009
@@ -32,6 +32,7 @@
 namespace clang {
 
 class ASTContext;
+class LabelStmt;
 class Preprocessor;
 class SourceManager;
 class SwitchCase;
@@ -113,6 +114,9 @@
   /// \brief Mapping from SwitchCase statements to IDs.
   std::map<SwitchCase *, unsigned> SwitchCaseIDs;
   
+  /// \brief Mapping from LabelStmt statements to IDs.
+  std::map<LabelStmt *, unsigned> LabelIDs;
+
   void WriteTargetTriple(const TargetInfo &Target);
   void WriteLanguageOptions(const LangOptions &LangOpts);
   void WriteSourceManagerBlock(SourceManager &SourceMgr);
@@ -182,6 +186,10 @@
   /// \brief Retrieve the ID for the given switch-case statement.
   unsigned getSwitchCaseID(SwitchCase *S);
 
+  /// \brief Retrieve the ID for the given label statement, which may
+  /// or may not have been emitted yet.
+  unsigned GetLabelID(LabelStmt *S);
+
 };
 
 } // end namespace clang

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Fri Apr 17 13:18:49 2009
@@ -249,11 +249,13 @@
     unsigned VisitSwitchCase(SwitchCase *S);
     unsigned VisitCaseStmt(CaseStmt *S);
     unsigned VisitDefaultStmt(DefaultStmt *S);
+    unsigned VisitLabelStmt(LabelStmt *S);
     unsigned VisitIfStmt(IfStmt *S);
     unsigned VisitSwitchStmt(SwitchStmt *S);
     unsigned VisitWhileStmt(WhileStmt *S);
     unsigned VisitDoStmt(DoStmt *S);
     unsigned VisitForStmt(ForStmt *S);
+    unsigned VisitGotoStmt(GotoStmt *S);
     unsigned VisitContinueStmt(ContinueStmt *S);
     unsigned VisitBreakStmt(BreakStmt *S);
     unsigned VisitReturnStmt(ReturnStmt *S);
@@ -336,6 +338,15 @@
   return 1;
 }
 
+unsigned PCHStmtReader::VisitLabelStmt(LabelStmt *S) {
+  VisitStmt(S);
+  S->setID(Reader.GetIdentifierInfo(Record, Idx));
+  S->setSubStmt(StmtStack.back());
+  S->setIdentLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  Reader.RecordLabelStmt(S, Record[Idx++]);
+  return 1;
+}
+
 unsigned PCHStmtReader::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3]));
@@ -388,6 +399,14 @@
   return 4;
 }
 
+unsigned PCHStmtReader::VisitGotoStmt(GotoStmt *S) {
+  VisitStmt(S);
+  Reader.SetLabelOf(S, Record[Idx++]);
+  S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
 unsigned PCHStmtReader::VisitContinueStmt(ContinueStmt *S) {
   VisitStmt(S);
   S->setContinueLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -2172,6 +2191,10 @@
       S = new (Context) DefaultStmt(Empty);
       break;
 
+    case pch::STMT_LABEL:
+      S = new (Context) LabelStmt(Empty);
+      break;
+
     case pch::STMT_IF:
       S = new (Context) IfStmt(Empty);
       break;
@@ -2192,6 +2215,10 @@
       S = new (Context) ForStmt(Empty);
       break;
 
+    case pch::STMT_GOTO:
+      S = new (Context) GotoStmt(Empty);
+      break;
+
     case pch::STMT_CONTINUE:
       S = new (Context) ContinueStmt(Empty);
       break;
@@ -2342,7 +2369,7 @@
       }
     }
 
-    assert(Idx == Record.size() && "Invalid deserialization of expression");
+    assert(Idx == Record.size() && "Invalid deserialization of statement");
     StmtStack.push_back(S);
   }
   assert(StmtStack.size() == 1 && "Extra expressions on stack!");
@@ -2376,3 +2403,39 @@
   assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
   return SwitchCaseStmts[ID];
 }
+
+/// \brief Record that the given label statement has been
+/// deserialized and has the given ID.
+void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
+  assert(LabelStmts.find(ID) == LabelStmts.end() && 
+         "Deserialized label twice");
+  LabelStmts[ID] = S;
+
+  // If we've already seen any goto statements that point to this
+  // label, resolve them now.
+  typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
+  std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
+  for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
+    Goto->second->setLabel(S);
+  UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
+}
+
+/// \brief Set the label of the given statement 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(GotoStmt *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 goto and
+    // we're done.
+    S->setLabel(Label->second);
+  } else {
+    // We haven't seen this label yet, so add this goto to the set of
+    // unresolved goto statements.
+    UnresolvedGotoStmts.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=69364&r1=69363&r2=69364&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Fri Apr 17 13:18:49 2009
@@ -451,11 +451,13 @@
     void VisitSwitchCase(SwitchCase *S);
     void VisitCaseStmt(CaseStmt *S);
     void VisitDefaultStmt(DefaultStmt *S);
+    void VisitLabelStmt(LabelStmt *S);
     void VisitIfStmt(IfStmt *S);
     void VisitSwitchStmt(SwitchStmt *S);
     void VisitWhileStmt(WhileStmt *S);
     void VisitDoStmt(DoStmt *S);
     void VisitForStmt(ForStmt *S);
+    void VisitGotoStmt(GotoStmt *S);
     void VisitContinueStmt(ContinueStmt *S);
     void VisitBreakStmt(BreakStmt *S);
     void VisitReturnStmt(ReturnStmt *S);
@@ -536,6 +538,15 @@
   Code = pch::STMT_DEFAULT;
 }
 
+void PCHStmtWriter::VisitLabelStmt(LabelStmt *S) {
+  VisitStmt(S);
+  Writer.AddIdentifierRef(S->getID(), Record);
+  Writer.WriteSubStmt(S->getSubStmt());
+  Writer.AddSourceLocation(S->getIdentLoc(), Record);
+  Record.push_back(Writer.GetLabelID(S));
+  Code = pch::STMT_LABEL;
+}
+
 void PCHStmtWriter::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   Writer.WriteSubStmt(S->getCond());
@@ -582,6 +593,14 @@
   Code = pch::STMT_FOR;
 }
 
+void PCHStmtWriter::VisitGotoStmt(GotoStmt *S) {
+  VisitStmt(S);
+  Record.push_back(Writer.GetLabelID(S->getLabel()));
+  Writer.AddSourceLocation(S->getGotoLoc(), Record);
+  Writer.AddSourceLocation(S->getLabelLoc(), Record);
+  Code = pch::STMT_GOTO;
+}
+
 void PCHStmtWriter::VisitContinueStmt(ContinueStmt *S) {
   VisitStmt(S);
   Writer.AddSourceLocation(S->getContinueLoc(), Record);
@@ -1857,3 +1876,15 @@
          "SwitchCase hasn't been seen yet");
   return SwitchCaseIDs[S];
 }
+
+/// \brief Retrieve the ID for the given label statement, which may
+/// or may not have been emitted yet.
+unsigned PCHWriter::GetLabelID(LabelStmt *S) {
+  std::map<LabelStmt *, unsigned>::iterator Pos = LabelIDs.find(S);
+  if (Pos != LabelIDs.end())
+    return Pos->second;
+
+  unsigned NextID = LabelIDs.size();
+  LabelIDs[S] = NextID;
+  return NextID;
+}

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

==============================================================================
--- cfe/trunk/test/PCH/stmts.h (original)
+++ cfe/trunk/test/PCH/stmts.h Fri Apr 17 13:18:49 2009
@@ -33,17 +33,25 @@
       continue;
     } else if (x < 5)
       break;
+    else
+      goto done;
   }
 
   do {
     x++;
   } while (x < 10);
 
+ almost_done:
   for (int y = x; y < 20; ++y) {
     if (x + y == 12)
       return;
+    else if (x - y == 7)
+      goto almost_done;
   }
 
+ done:
+  x = x + 2;
+
   int z = x, *y, j = 5;
 }
 





More information about the cfe-commits mailing list