diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-04-17 18:18:49 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-04-17 18:18:49 +0000 |
commit | 1de05feeeafe5b215fe7617594a7076a5192a6e2 (patch) | |
tree | 1adf57ca6434d22306af1104eb07a242c797760e /lib/Frontend/PCHReader.cpp | |
parent | 5abd66ff444d31bd0537d8151b1abf354cfcb1af (diff) |
PCH support for labels and goto.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69364 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/PCHReader.cpp')
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 50378966e1..9597b37082 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -249,11 +249,13 @@ namespace { 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 @@ unsigned PCHStmtReader::VisitDefaultStmt(DefaultStmt *S) { 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 @@ unsigned PCHStmtReader::VisitForStmt(ForStmt *S) { 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 @@ Stmt *PCHReader::ReadStmt() { 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 @@ Stmt *PCHReader::ReadStmt() { 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 @@ Stmt *PCHReader::ReadStmt() { } } - 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 @@ SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) { 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)); + } +} |