forked from OSchip/llvm-project
parent
059c6f6293
commit
6cc68a47b5
|
@ -530,13 +530,16 @@ public:
|
|||
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 @@ public:
|
|||
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);
|
||||
|
|
|
@ -383,6 +383,8 @@ namespace clang {
|
|||
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 @@ namespace clang {
|
|||
STMT_DO,
|
||||
/// \brief A ForStmt record.
|
||||
STMT_FOR,
|
||||
/// \brief A GotoStmt record.
|
||||
STMT_GOTO,
|
||||
/// \brief A ContinueStmt record.
|
||||
STMT_CONTINUE,
|
||||
/// \brief A BreakStmt record.
|
||||
|
|
|
@ -41,6 +41,8 @@ class ASTContext;
|
|||
class Attr;
|
||||
class Decl;
|
||||
class DeclContext;
|
||||
class GotoStmt;
|
||||
class LabelStmt;
|
||||
class Preprocessor;
|
||||
class SwitchCase;
|
||||
|
||||
|
@ -132,6 +134,15 @@ private:
|
|||
/// 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 @@ public:
|
|||
|
||||
/// \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
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace llvm {
|
|||
namespace clang {
|
||||
|
||||
class ASTContext;
|
||||
class LabelStmt;
|
||||
class Preprocessor;
|
||||
class SourceManager;
|
||||
class SwitchCase;
|
||||
|
@ -113,6 +114,9 @@ private:
|
|||
/// \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 @@ public:
|
|||
/// \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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -451,11 +451,13 @@ namespace {
|
|||
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 @@ void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
|
|||
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 @@ void PCHStmtWriter::VisitForStmt(ForStmt *S) {
|
|||
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 @@ unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) {
|
|||
"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;
|
||||
}
|
||||
|
|
|
@ -33,17 +33,25 @@ void f0(int x) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue