diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7461,8 +7461,6 @@ /// source each time it is called, and is meant to be used via a /// LazyOffsetPtr (which is used by Decls for the body of functions, etc). Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) { - // Switch case IDs are per Decl. - ClearSwitchCaseIDs(); // Offset here is a global offset across the entire chain. RecordLocation Loc = getLocalBitOffset(Offset); @@ -9067,8 +9065,7 @@ /// Record that the given ID maps to the given switch-case /// statement. void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) { - assert((*CurrSwitchCaseStmts)[ID] == nullptr && - "Already have a SwitchCase with this ID"); + // We may already have a SwitchCase with this ID, drop the existing. (*CurrSwitchCaseStmts)[ID] = SC; } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2453,9 +2453,6 @@ } void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { - // Switch case IDs are per function body. - Writer->ClearSwitchCaseIDs(); - assert(FD->doesThisDeclarationHaveABody()); bool ModulesCodegen = false; if (Writer->WritingModule && !FD->isDependentContext()) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2611,11 +2611,12 @@ //===----------------------------------------------------------------------===// unsigned ASTWriter::RecordSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && - "SwitchCase recorded twice"); unsigned NextID = SwitchCaseIDs.size(); - SwitchCaseIDs[S] = NextID; - return NextID; + assert(NextID < UINT_MAX && "Too many SwitchCase to serialize"); + // If we already recorded this SwitchCase then just return with its ID, else + // insert it with the next ID. + auto Res = SwitchCaseIDs.insert({S, NextID}); + return Res.first->second; } unsigned ASTWriter::getSwitchCaseID(SwitchCase *S) { diff --git a/clang/test/AST/ast-dump-lambda.cpp b/clang/test/AST/ast-dump-lambda.cpp --- a/clang/test/AST/ast-dump-lambda.cpp +++ b/clang/test/AST/ast-dump-lambda.cpp @@ -34,6 +34,21 @@ []() noexcept {}; []() -> int { return 0; }; } + +class { +public: + enum {} a; +} b; +void should_not_crash_with_switch_in_lambda() { + switch (b.a) + default:; + enum { e } d; + auto f = [d] { + switch (d) + case e:; + }; +} + // CHECK:Dumping test: // CHECK-NEXT:FunctionTemplateDecl {{.*}} <{{.*}}ast-dump-lambda.cpp:15:1, line:36:1> line:15:32{{( imported)?}} test // CHECK-NEXT:|-TemplateTypeParmDecl {{.*}} col:23{{( imported)?}} referenced typename depth 0 index 0 ... Ts