summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTDumper.cpp9
-rw-r--r--clang/lib/AST/ASTImporter.cpp4
-rw-r--r--clang/lib/AST/Stmt.cpp68
-rw-r--r--clang/lib/Sema/SemaStmt.cpp3
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp21
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp16
6 files changed, 93 insertions, 28 deletions
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index 3c4a9ea398b..99524e88937 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -512,6 +512,7 @@ namespace {
void VisitDeclStmt(const DeclStmt *Node);
void VisitAttributedStmt(const AttributedStmt *Node);
void VisitIfStmt(const IfStmt *Node);
+ void VisitSwitchStmt(const SwitchStmt *Node);
void VisitLabelStmt(const LabelStmt *Node);
void VisitGotoStmt(const GotoStmt *Node);
void VisitCXXCatchStmt(const CXXCatchStmt *Node);
@@ -2032,6 +2033,14 @@ void ASTDumper::VisitIfStmt(const IfStmt *Node) {
OS << " has_else";
}
+void ASTDumper::VisitSwitchStmt(const SwitchStmt *Node) {
+ VisitStmt(Node);
+ if (Node->hasInitStorage())
+ OS << " has_init";
+ if (Node->hasVarStorage())
+ OS << " has_var";
+}
+
void ASTDumper::VisitLabelStmt(const LabelStmt *Node) {
VisitStmt(Node);
OS << " '" << Node->getName() << "'";
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index df968099bdd..49623d0e676 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -5790,8 +5790,8 @@ ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
SourceLocation ToSwitchLoc;
std::tie(ToInit, ToConditionVariable, ToCond, ToBody, ToSwitchLoc) = *Imp;
- auto *ToStmt = new (Importer.getToContext()) SwitchStmt(
- Importer.getToContext(), ToInit, ToConditionVariable, ToCond);
+ auto *ToStmt = SwitchStmt::Create(Importer.getToContext(), ToInit,
+ ToConditionVariable, ToCond);
ToStmt->setBody(ToBody);
ToStmt->setSwitchLoc(ToSwitchLoc);
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index 29fb60a83e5..41a4a64f33f 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -913,33 +913,69 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
VarRange.getEnd());
}
-SwitchStmt::SwitchStmt(const ASTContext &C, Stmt *init, VarDecl *Var,
- Expr *cond)
- : Stmt(SwitchStmtClass), FirstCase(nullptr, false) {
- setConditionVariable(C, Var);
- SubExprs[INIT] = init;
- SubExprs[COND] = cond;
- SubExprs[BODY] = nullptr;
- SwitchStmtBits.SwitchLoc = SourceLocation{};
+SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
+ Expr *Cond)
+ : Stmt(SwitchStmtClass), FirstCase(nullptr) {
+ bool HasInit = Init != nullptr;
+ bool HasVar = Var != nullptr;
+ SwitchStmtBits.HasInit = HasInit;
+ SwitchStmtBits.HasVar = HasVar;
+ SwitchStmtBits.AllEnumCasesCovered = false;
+
+ setCond(Cond);
+ setBody(nullptr);
+ if (HasInit)
+ setInit(Init);
+ if (HasVar)
+ setConditionVariable(Ctx, Var);
+
+ setSwitchLoc(SourceLocation{});
}
-VarDecl *SwitchStmt::getConditionVariable() const {
- if (!SubExprs[VAR])
- return nullptr;
+SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar)
+ : Stmt(SwitchStmtClass, Empty) {
+ SwitchStmtBits.HasInit = HasInit;
+ SwitchStmtBits.HasVar = HasVar;
+ SwitchStmtBits.AllEnumCasesCovered = false;
+}
- auto *DS = cast<DeclStmt>(SubExprs[VAR]);
+SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
+ Expr *Cond) {
+ bool HasInit = Init != nullptr;
+ bool HasVar = Var != nullptr;
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
+ alignof(SwitchStmt));
+ return new (Mem) SwitchStmt(Ctx, Init, Var, Cond);
+}
+
+SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit,
+ bool HasVar) {
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
+ alignof(SwitchStmt));
+ return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar);
+}
+
+VarDecl *SwitchStmt::getConditionVariable() {
+ auto *DS = getConditionVariableDeclStmt();
+ if (!DS)
+ return nullptr;
return cast<VarDecl>(DS->getSingleDecl());
}
-void SwitchStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
+void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
+ assert(hasVarStorage() &&
+ "This switch statement has no storage for a condition variable!");
+
if (!V) {
- SubExprs[VAR] = nullptr;
+ getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
return;
}
SourceRange VarRange = V->getSourceRange();
- SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
- VarRange.getEnd());
+ getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
+ DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
}
WhileStmt::WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 67b5a84caf3..2018c874af5 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -727,8 +727,7 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
setFunctionHasBranchIntoScope();
- SwitchStmt *SS = new (Context)
- SwitchStmt(Context, InitStmt, Cond.get().first, CondExpr);
+ auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr);
getCurFunction()->SwitchStack.push_back(
FunctionScopeInfo::SwitchInfo(SS, false));
return SS;
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 1ad33c5dc34..3c63fe1143d 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -240,13 +240,21 @@ void ASTStmtReader::VisitIfStmt(IfStmt *S) {
void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
VisitStmt(S);
- S->setInit(Record.readSubStmt());
- S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+
+ bool HasInit = Record.readInt();
+ bool HasVar = Record.readInt();
+ bool AllEnumCasesCovered = Record.readInt();
+ if (AllEnumCasesCovered)
+ S->setAllEnumCasesCovered();
+
S->setCond(Record.readSubExpr());
S->setBody(Record.readSubStmt());
+ if (HasInit)
+ S->setInit(Record.readSubStmt());
+ if (HasVar)
+ S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+
S->setSwitchLoc(ReadSourceLocation());
- if (Record.readInt())
- S->setAllEnumCasesCovered();
SwitchCase *PrevSC = nullptr;
for (auto E = Record.size(); Record.getIdx() != E; ) {
@@ -2310,7 +2318,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_SWITCH:
- S = new (Context) SwitchStmt(Empty);
+ S = SwitchStmt::CreateEmpty(
+ Context,
+ /* HasInit=*/Record[ASTStmtReader::NumStmtFields + 0],
+ /* HasVar=*/Record[ASTStmtReader::NumStmtFields + 1]);
break;
case STMT_WHILE:
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index e7f9f35dcc2..396cc1c2d05 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -159,12 +159,22 @@ void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
VisitStmt(S);
- Record.AddStmt(S->getInit());
- Record.AddDeclRef(S->getConditionVariable());
+
+ bool HasInit = S->getInit() != nullptr;
+ bool HasVar = S->getConditionVariableDeclStmt() != nullptr;
+ Record.push_back(HasInit);
+ Record.push_back(HasVar);
+ Record.push_back(S->isAllEnumCasesCovered());
+
Record.AddStmt(S->getCond());
Record.AddStmt(S->getBody());
+ if (HasInit)
+ Record.AddStmt(S->getInit());
+ if (HasVar)
+ Record.AddDeclRef(S->getConditionVariable());
+
Record.AddSourceLocation(S->getSwitchLoc());
- Record.push_back(S->isAllEnumCasesCovered());
+
for (SwitchCase *SC = S->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase())
Record.push_back(Writer.RecordSwitchCaseID(SC));
OpenPOWER on IntegriCloud