PCH support for the first batch of statements, including null,
compound, case, default, if, switch, and break statements. llvm-svn: 69329
This commit is contained in:
parent
e8eeffdf16
commit
a9af1d13da
|
@ -136,11 +136,22 @@ public:
|
|||
void operator delete(void*, std::size_t) throw() { }
|
||||
void operator delete(void*, void*) throw() { }
|
||||
|
||||
public:
|
||||
/// \brief A placeholder type used to construct an empty shell of a
|
||||
/// type, that will be filled in later (e.g., by some
|
||||
/// de-serialization).
|
||||
struct EmptyShell { };
|
||||
|
||||
protected:
|
||||
/// DestroyChildren - Invoked by destructors of subclasses of Stmt to
|
||||
/// recursively release child AST nodes.
|
||||
void DestroyChildren(ASTContext& Ctx);
|
||||
|
||||
/// \brief Construct an empty statement.
|
||||
explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC) {
|
||||
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
|
||||
}
|
||||
|
||||
public:
|
||||
Stmt(StmtClass SC) : sClass(SC) {
|
||||
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
|
||||
|
@ -211,11 +222,6 @@ public:
|
|||
return const_child_iterator(const_cast<Stmt*>(this)->child_end());
|
||||
}
|
||||
|
||||
/// \brief A placeholder type used to construct an empty shell of a
|
||||
/// type, that will be filled in later (e.g., by some
|
||||
/// de-serialization).
|
||||
struct EmptyShell { };
|
||||
|
||||
void Emit(llvm::Serializer& S) const;
|
||||
static Stmt* Create(llvm::Deserializer& D, ASTContext& C);
|
||||
|
||||
|
@ -288,7 +294,11 @@ class NullStmt : public Stmt {
|
|||
public:
|
||||
NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {}
|
||||
|
||||
/// \brief Build an empty null statement.
|
||||
explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { }
|
||||
|
||||
SourceLocation getSemiLoc() const { return SemiLoc; }
|
||||
void setSemiLoc(SourceLocation L) { SemiLoc = L; }
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
|
||||
|
||||
|
@ -323,9 +333,16 @@ public:
|
|||
Body = new (C) Stmt*[NumStmts];
|
||||
memcpy(Body, StmtStart, numStmts * sizeof(*Body));
|
||||
}
|
||||
|
||||
// \brief Build an empty compound statement.
|
||||
explicit CompoundStmt(EmptyShell Empty)
|
||||
: Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { }
|
||||
|
||||
void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts);
|
||||
|
||||
bool body_empty() const { return NumStmts == 0; }
|
||||
|
||||
unsigned size() const { return NumStmts; }
|
||||
|
||||
typedef Stmt** body_iterator;
|
||||
body_iterator body_begin() { return Body; }
|
||||
body_iterator body_end() { return Body + NumStmts; }
|
||||
|
@ -360,7 +377,9 @@ public:
|
|||
}
|
||||
|
||||
SourceLocation getLBracLoc() const { return LBracLoc; }
|
||||
void setLBracLoc(SourceLocation L) { LBracLoc = L; }
|
||||
SourceLocation getRBracLoc() const { return RBracLoc; }
|
||||
void setRBracLoc(SourceLocation L) { RBracLoc = L; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CompoundStmtClass;
|
||||
|
@ -418,12 +437,17 @@ public:
|
|||
SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
|
||||
CaseLoc = caseLoc;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Build an empty switch case statement.
|
||||
explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass) { }
|
||||
|
||||
SourceLocation getCaseLoc() const { return CaseLoc; }
|
||||
|
||||
void setCaseLoc(SourceLocation L) { CaseLoc = L; }
|
||||
|
||||
Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
|
||||
Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
|
||||
Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
|
||||
|
||||
const Expr *getLHS() const {
|
||||
return reinterpret_cast<const Expr*>(SubExprs[LHS]);
|
||||
}
|
||||
|
@ -465,11 +489,16 @@ class DefaultStmt : public SwitchCase {
|
|||
public:
|
||||
DefaultStmt(SourceLocation DL, Stmt *substmt) :
|
||||
SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL) {}
|
||||
|
||||
|
||||
/// \brief Build an empty default statement.
|
||||
explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { }
|
||||
|
||||
Stmt *getSubStmt() { return SubStmt; }
|
||||
const Stmt *getSubStmt() const { return SubStmt; }
|
||||
|
||||
void setSubStmt(Stmt *S) { SubStmt = S; }
|
||||
|
||||
SourceLocation getDefaultLoc() const { return DefaultLoc; }
|
||||
void setDefaultLoc(SourceLocation L) { DefaultLoc = L; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(DefaultLoc, SubStmt->getLocEnd());
|
||||
|
@ -537,14 +566,23 @@ public:
|
|||
IfLoc = IL;
|
||||
}
|
||||
|
||||
/// \brief Build an empty if/then/else statement
|
||||
explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
|
||||
|
||||
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
|
||||
void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
|
||||
const Stmt *getThen() const { return SubExprs[THEN]; }
|
||||
void setThen(Stmt *S) { SubExprs[THEN] = S; }
|
||||
const Stmt *getElse() const { return SubExprs[ELSE]; }
|
||||
void setElse(Stmt *S) { SubExprs[ELSE] = S; }
|
||||
|
||||
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
|
||||
Stmt *getThen() { return SubExprs[THEN]; }
|
||||
Stmt *getElse() { return SubExprs[ELSE]; }
|
||||
|
||||
SourceLocation getIfLoc() const { return IfLoc; }
|
||||
void setIfLoc(SourceLocation L) { IfLoc = L; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
if (SubExprs[ELSE])
|
||||
return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
|
||||
|
@ -579,13 +617,22 @@ public:
|
|||
SubExprs[BODY] = NULL;
|
||||
}
|
||||
|
||||
/// \brief Build a empty switch statement.
|
||||
explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { }
|
||||
|
||||
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
|
||||
const Stmt *getBody() const { return SubExprs[BODY]; }
|
||||
const SwitchCase *getSwitchCaseList() const { return FirstCase; }
|
||||
|
||||
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
|
||||
void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
|
||||
Stmt *getBody() { return SubExprs[BODY]; }
|
||||
void setBody(Stmt *S) { SubExprs[BODY] = S; }
|
||||
SwitchCase *getSwitchCaseList() { return FirstCase; }
|
||||
void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
|
||||
|
||||
SourceLocation getSwitchLoc() const { return SwitchLoc; }
|
||||
void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
|
||||
|
||||
void setBody(Stmt *S, SourceLocation SL) {
|
||||
SubExprs[BODY] = S;
|
||||
|
@ -814,6 +861,12 @@ class BreakStmt : public Stmt {
|
|||
public:
|
||||
BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {}
|
||||
|
||||
/// \brief Build an empty break statement.
|
||||
explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { }
|
||||
|
||||
SourceLocation getBreakLoc() const { return BreakLoc; }
|
||||
void setBreakLoc(SourceLocation L) { BreakLoc = L; }
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
|
|
|
@ -375,6 +375,20 @@ namespace clang {
|
|||
STMT_STOP,
|
||||
/// \brief A NULL expression.
|
||||
STMT_NULL_PTR,
|
||||
/// \brief A NullStmt record.
|
||||
STMT_NULL,
|
||||
/// \brief A CompoundStmt record.
|
||||
STMT_COMPOUND,
|
||||
/// \brief A CaseStmt record.
|
||||
STMT_CASE,
|
||||
/// \brief A DefaultStmt record.
|
||||
STMT_DEFAULT,
|
||||
/// \brief An IfStmt record.
|
||||
STMT_IF,
|
||||
/// \brief A SwitchStmt record.
|
||||
STMT_SWITCH,
|
||||
/// \brief A BreakStmt record.
|
||||
STMT_BREAK,
|
||||
/// \brief A PredefinedExpr record.
|
||||
EXPR_PREDEFINED,
|
||||
/// \brief A DeclRefExpr record.
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Bitcode/BitstreamReader.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
@ -41,6 +42,7 @@ class Attr;
|
|||
class Decl;
|
||||
class DeclContext;
|
||||
class Preprocessor;
|
||||
class SwitchCase;
|
||||
|
||||
/// \brief Reads a precompiled head containing the contents of a
|
||||
/// translation unit.
|
||||
|
@ -126,6 +128,10 @@ private:
|
|||
/// file.
|
||||
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
|
||||
|
||||
/// \brief Mapping from switch-case IDs in the PCH file to
|
||||
/// switch-case statements.
|
||||
std::map<unsigned, SwitchCase *> SwitchCaseStmts;
|
||||
|
||||
PCHReadResult ReadPCHBlock();
|
||||
bool CheckPredefinesBuffer(const char *PCHPredef,
|
||||
unsigned PCHPredefLen,
|
||||
|
@ -241,6 +247,13 @@ public:
|
|||
/// \brief Retrieve the AST context that this PCH reader
|
||||
/// supplements.
|
||||
ASTContext &getContext() { return Context; }
|
||||
|
||||
/// \brief Record that the given ID maps to the given switch-case
|
||||
/// statement.
|
||||
void RecordSwitchCaseID(SwitchCase *SC, unsigned ID);
|
||||
|
||||
/// \brief Retrieve the switch-case statement with the given ID.
|
||||
SwitchCase *getSwitchCaseWithID(unsigned ID);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "clang/Frontend/PCHBitCodes.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
namespace llvm {
|
||||
|
@ -33,6 +34,7 @@ namespace clang {
|
|||
class ASTContext;
|
||||
class Preprocessor;
|
||||
class SourceManager;
|
||||
class SwitchCase;
|
||||
class TargetInfo;
|
||||
|
||||
/// \brief Writes a precompiled header containing the contents of a
|
||||
|
@ -108,6 +110,9 @@ private:
|
|||
/// declaration or type.
|
||||
llvm::SmallVector<Stmt *, 8> StmtsToEmit;
|
||||
|
||||
/// \brief Mapping from SwitchCase statements to IDs.
|
||||
std::map<SwitchCase *, unsigned> SwitchCaseIDs;
|
||||
|
||||
void WriteTargetTriple(const TargetInfo &Target);
|
||||
void WriteLanguageOptions(const LangOptions &LangOpts);
|
||||
void WriteSourceManagerBlock(SourceManager &SourceMgr);
|
||||
|
@ -170,6 +175,13 @@ public:
|
|||
/// \brief Flush all of the statements and expressions that have
|
||||
/// been added to the queue via AddStmt().
|
||||
void FlushStmts();
|
||||
|
||||
/// \brief Record an ID for the given switch-case statement.
|
||||
unsigned RecordSwitchCaseID(SwitchCase *S);
|
||||
|
||||
/// \brief Retrieve the ID for the given switch-case statement.
|
||||
unsigned getSwitchCaseID(SwitchCase *S);
|
||||
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -96,6 +96,14 @@ bool Stmt::CollectingStats(bool enable) {
|
|||
return StatSwitch;
|
||||
}
|
||||
|
||||
void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
|
||||
if (this->Body)
|
||||
C.Deallocate(Body);
|
||||
this->NumStmts = NumStmts;
|
||||
|
||||
Body = new (C) Stmt*[NumStmts];
|
||||
memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
|
||||
}
|
||||
|
||||
const char *LabelStmt::getName() const {
|
||||
return getID()->getName();
|
||||
|
|
|
@ -139,7 +139,8 @@ void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
|
|||
|
||||
void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||
VisitValueDecl(FD);
|
||||
// FIXME: function body
|
||||
if (Record[Idx++])
|
||||
FD->setBody(cast<CompoundStmt>(Reader.ReadStmt()));
|
||||
FD->setPreviousDeclaration(
|
||||
cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
|
||||
FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
|
||||
|
@ -229,15 +230,28 @@ namespace {
|
|||
unsigned &Idx, llvm::SmallVectorImpl<Stmt *> &StmtStack)
|
||||
: Reader(Reader), Record(Record), Idx(Idx), StmtStack(StmtStack) { }
|
||||
|
||||
/// \brief The number of record fields required for the Stmt class
|
||||
/// itself.
|
||||
static const unsigned NumStmtFields = 0;
|
||||
|
||||
/// \brief The number of record fields required for the Expr class
|
||||
/// itself.
|
||||
static const unsigned NumExprFields = 3;
|
||||
static const unsigned NumExprFields = NumStmtFields + 3;
|
||||
|
||||
// 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 VisitStmt(Stmt *S);
|
||||
unsigned VisitNullStmt(NullStmt *S);
|
||||
unsigned VisitCompoundStmt(CompoundStmt *S);
|
||||
unsigned VisitSwitchCase(SwitchCase *S);
|
||||
unsigned VisitCaseStmt(CaseStmt *S);
|
||||
unsigned VisitDefaultStmt(DefaultStmt *S);
|
||||
unsigned VisitIfStmt(IfStmt *S);
|
||||
unsigned VisitSwitchStmt(SwitchStmt *S);
|
||||
unsigned VisitBreakStmt(BreakStmt *S);
|
||||
unsigned VisitExpr(Expr *E);
|
||||
unsigned VisitPredefinedExpr(PredefinedExpr *E);
|
||||
unsigned VisitDeclRefExpr(DeclRefExpr *E);
|
||||
|
@ -273,7 +287,83 @@ namespace {
|
|||
};
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitStmt(Stmt *S) {
|
||||
assert(Idx == NumStmtFields && "Incorrect statement field count");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitNullStmt(NullStmt *S) {
|
||||
VisitStmt(S);
|
||||
S->setSemiLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) {
|
||||
VisitStmt(S);
|
||||
unsigned NumStmts = Record[Idx++];
|
||||
S->setStmts(Reader.getContext(),
|
||||
&StmtStack[StmtStack.size() - NumStmts], NumStmts);
|
||||
S->setLBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
S->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
return NumStmts;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitSwitchCase(SwitchCase *S) {
|
||||
VisitStmt(S);
|
||||
Reader.RecordSwitchCaseID(S, Record[Idx++]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitCaseStmt(CaseStmt *S) {
|
||||
VisitSwitchCase(S);
|
||||
S->setLHS(cast<Expr>(StmtStack[StmtStack.size() - 3]));
|
||||
S->setRHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
|
||||
S->setSubStmt(StmtStack.back());
|
||||
S->setCaseLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
return 3;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitDefaultStmt(DefaultStmt *S) {
|
||||
VisitSwitchCase(S);
|
||||
S->setSubStmt(StmtStack.back());
|
||||
S->setDefaultLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitIfStmt(IfStmt *S) {
|
||||
VisitStmt(S);
|
||||
S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3]));
|
||||
S->setThen(StmtStack[StmtStack.size() - 2]);
|
||||
S->setElse(StmtStack[StmtStack.size() - 1]);
|
||||
S->setIfLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
return 3;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) {
|
||||
VisitStmt(S);
|
||||
S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 2]));
|
||||
S->setBody(StmtStack.back());
|
||||
S->setSwitchLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
SwitchCase *PrevSC = 0;
|
||||
for (unsigned N = Record.size(); Idx != N; ++Idx) {
|
||||
SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]);
|
||||
if (PrevSC)
|
||||
PrevSC->setNextSwitchCase(SC);
|
||||
else
|
||||
S->setSwitchCaseList(SC);
|
||||
PrevSC = SC;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitBreakStmt(BreakStmt *S) {
|
||||
VisitStmt(S);
|
||||
S->setBreakLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitExpr(Expr *E) {
|
||||
VisitStmt(E);
|
||||
E->setType(Reader.GetType(Record[Idx++]));
|
||||
E->setTypeDependent(Record[Idx++]);
|
||||
E->setValueDependent(Record[Idx++]);
|
||||
|
@ -2002,6 +2092,34 @@ Stmt *PCHReader::ReadStmt() {
|
|||
S = 0;
|
||||
break;
|
||||
|
||||
case pch::STMT_NULL:
|
||||
S = new (Context) NullStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::STMT_COMPOUND:
|
||||
S = new (Context) CompoundStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::STMT_CASE:
|
||||
S = new (Context) CaseStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::STMT_DEFAULT:
|
||||
S = new (Context) DefaultStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::STMT_IF:
|
||||
S = new (Context) IfStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::STMT_SWITCH:
|
||||
S = new (Context) SwitchStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::STMT_BREAK:
|
||||
S = new (Context) BreakStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::EXPR_PREDEFINED:
|
||||
// FIXME: untested (until we can serialize function bodies).
|
||||
S = new (Context) PredefinedExpr(Empty);
|
||||
|
@ -2157,3 +2275,16 @@ DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
|
|||
Context.getSourceManager()),
|
||||
DiagID);
|
||||
}
|
||||
|
||||
/// \brief Record that the given ID maps to the given switch-case
|
||||
/// statement.
|
||||
void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
|
||||
assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
|
||||
SwitchCaseStmts[ID] = SC;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the switch-case statement with the given ID.
|
||||
SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
|
||||
assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
|
||||
return SwitchCaseStmts[ID];
|
||||
}
|
||||
|
|
|
@ -338,7 +338,9 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
|||
|
||||
void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
VisitValueDecl(D);
|
||||
// FIXME: function body
|
||||
Record.push_back(D->isThisDeclarationADefinition());
|
||||
if (D->isThisDeclarationADefinition())
|
||||
Writer.AddStmt(D->getBody());
|
||||
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
|
||||
Record.push_back(D->getStorageClass()); // FIXME: stable encoding
|
||||
Record.push_back(D->isInline());
|
||||
|
@ -443,6 +445,15 @@ namespace {
|
|||
PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
|
||||
: Writer(Writer), Record(Record) { }
|
||||
|
||||
void VisitStmt(Stmt *S);
|
||||
void VisitNullStmt(NullStmt *S);
|
||||
void VisitCompoundStmt(CompoundStmt *S);
|
||||
void VisitSwitchCase(SwitchCase *S);
|
||||
void VisitCaseStmt(CaseStmt *S);
|
||||
void VisitDefaultStmt(DefaultStmt *S);
|
||||
void VisitIfStmt(IfStmt *S);
|
||||
void VisitSwitchStmt(SwitchStmt *S);
|
||||
void VisitBreakStmt(BreakStmt *S);
|
||||
void VisitExpr(Expr *E);
|
||||
void VisitPredefinedExpr(PredefinedExpr *E);
|
||||
void VisitDeclRefExpr(DeclRefExpr *E);
|
||||
|
@ -478,7 +489,75 @@ namespace {
|
|||
};
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitStmt(Stmt *S) {
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitNullStmt(NullStmt *S) {
|
||||
VisitStmt(S);
|
||||
Writer.AddSourceLocation(S->getSemiLoc(), Record);
|
||||
Code = pch::STMT_NULL;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
|
||||
VisitStmt(S);
|
||||
Record.push_back(S->size());
|
||||
for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end();
|
||||
CS != CSEnd; ++CS)
|
||||
Writer.WriteSubStmt(*CS);
|
||||
Writer.AddSourceLocation(S->getLBracLoc(), Record);
|
||||
Writer.AddSourceLocation(S->getRBracLoc(), Record);
|
||||
Code = pch::STMT_COMPOUND;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitSwitchCase(SwitchCase *S) {
|
||||
VisitStmt(S);
|
||||
Record.push_back(Writer.RecordSwitchCaseID(S));
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) {
|
||||
VisitSwitchCase(S);
|
||||
Writer.WriteSubStmt(S->getLHS());
|
||||
Writer.WriteSubStmt(S->getRHS());
|
||||
Writer.WriteSubStmt(S->getSubStmt());
|
||||
Writer.AddSourceLocation(S->getCaseLoc(), Record);
|
||||
Code = pch::STMT_CASE;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
|
||||
VisitSwitchCase(S);
|
||||
Writer.WriteSubStmt(S->getSubStmt());
|
||||
Writer.AddSourceLocation(S->getDefaultLoc(), Record);
|
||||
Code = pch::STMT_DEFAULT;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitIfStmt(IfStmt *S) {
|
||||
VisitStmt(S);
|
||||
Writer.WriteSubStmt(S->getCond());
|
||||
Writer.WriteSubStmt(S->getThen());
|
||||
Writer.WriteSubStmt(S->getElse());
|
||||
Writer.AddSourceLocation(S->getIfLoc(), Record);
|
||||
Code = pch::STMT_IF;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
|
||||
VisitStmt(S);
|
||||
Writer.WriteSubStmt(S->getCond());
|
||||
Writer.WriteSubStmt(S->getBody());
|
||||
Writer.AddSourceLocation(S->getSwitchLoc(), Record);
|
||||
for (SwitchCase *SC = S->getSwitchCaseList(); SC;
|
||||
SC = SC->getNextSwitchCase())
|
||||
Record.push_back(Writer.getSwitchCaseID(SC));
|
||||
Code = pch::STMT_SWITCH;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitBreakStmt(BreakStmt *S) {
|
||||
VisitStmt(S);
|
||||
Writer.AddSourceLocation(S->getBreakLoc(), Record);
|
||||
Code = pch::STMT_BREAK;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitExpr(Expr *E) {
|
||||
VisitStmt(E);
|
||||
Writer.AddTypeRef(E->getType(), Record);
|
||||
Record.push_back(E->isTypeDependent());
|
||||
Record.push_back(E->isValueDependent());
|
||||
|
@ -1708,3 +1787,17 @@ void PCHWriter::FlushStmts() {
|
|||
|
||||
StmtsToEmit.clear();
|
||||
}
|
||||
|
||||
unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) {
|
||||
assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() &&
|
||||
"SwitchCase recorded twice");
|
||||
unsigned NextID = SwitchCaseIDs.size();
|
||||
SwitchCaseIDs[S] = NextID;
|
||||
return NextID;
|
||||
}
|
||||
|
||||
unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) {
|
||||
assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() &&
|
||||
"SwitchCase hasn't been seen yet");
|
||||
return SwitchCaseIDs[S];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// Test this without pch.
|
||||
// RUN: clang-cc -fblocks -include %S/stmts.h -fsyntax-only -emit-llvm -o - %s
|
||||
|
||||
// Test with pch.
|
||||
// RUN: clang-cc -emit-pch -fblocks -o %t %S/stmts.h &&
|
||||
// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -emit-llvm -o - %s
|
||||
|
||||
void g0(void) { f0(5); }
|
|
@ -0,0 +1,22 @@
|
|||
// Header for PCH test stmts.c
|
||||
|
||||
void f0(int x) {
|
||||
// NullStmt
|
||||
;
|
||||
// IfStmt
|
||||
if (x) {
|
||||
} else if (x + 1) {
|
||||
}
|
||||
|
||||
switch (x) {
|
||||
case 0:
|
||||
x = 17;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue