diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTDumper.cpp | 9 | ||||
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 68 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 16 |
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)); |