vsapsai created this revision. vsapsai added reviewers: rsmith, bruno. Herald added a subscriber: jkorous-apple.
During reading C++ definition data for lambda we can access CXXRecordDecl representing lambda before we finished reading the definition data. This can happen by reading a captured variable which is VarDecl, then reading its decl context which is CXXMethodDecl `operator()`, then trying to merge redeclarable methods and accessing enclosing CXXRecordDecl. The call stack looks roughly like VisitCXXRecordDecl ReadCXXRecordDefinition VisitVarDecl VisitCXXMethodDecl mergeRedeclarable getPrimaryContextForMerging If we add fake definition data at this point, later we'll hit the assertion Assertion failed: (!DD.IsLambda && !MergeDD.IsLambda && "faked up lambda definition?"), function MergeDefinitionData, file clang/lib/Serialization/ASTReaderDecl.cpp, line 1675. The fix is to check if we are still reading real definition data and to avoid adding a fake one in this case. Fixes PR32556. rdar://problem/37461072 https://reviews.llvm.org/D43494 Files: clang/lib/Serialization/ASTReaderDecl.cpp clang/test/Modules/Inputs/self-referencing-lambda/a.h clang/test/Modules/Inputs/self-referencing-lambda/module.modulemap clang/test/Modules/self-referencing-lambda.cpp Index: clang/test/Modules/self-referencing-lambda.cpp =================================================================== --- /dev/null +++ clang/test/Modules/self-referencing-lambda.cpp @@ -0,0 +1,5 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/self-referencing-lambda %s -verify -emit-obj -o %t2.o +// expected-no-diagnostics + +#include "a.h" Index: clang/test/Modules/Inputs/self-referencing-lambda/module.modulemap =================================================================== --- /dev/null +++ clang/test/Modules/Inputs/self-referencing-lambda/module.modulemap @@ -0,0 +1,4 @@ +module "a.h" { + header "a.h" + export * +} Index: clang/test/Modules/Inputs/self-referencing-lambda/a.h =================================================================== --- /dev/null +++ clang/test/Modules/Inputs/self-referencing-lambda/a.h @@ -0,0 +1,4 @@ +void f() { + int x = 0; + auto q = [xm = x]{}; +} Index: clang/lib/Serialization/ASTReaderDecl.cpp =================================================================== --- clang/lib/Serialization/ASTReaderDecl.cpp +++ clang/lib/Serialization/ASTReaderDecl.cpp @@ -1782,7 +1782,10 @@ else DD = new (C) struct CXXRecordDecl::DefinitionData(D); + assert(!D->IsBeingDefined && "Should not overwrite definition in progress"); + D->IsBeingDefined = true; ReadCXXDefinitionData(*DD, D); + D->IsBeingDefined = false; // We might already have a definition for this record. This can happen either // because we're reading an update record, or because we've already done some @@ -2963,6 +2966,9 @@ if (!DD) DD = RD->getCanonicalDecl()->DefinitionData; + if (!DD && RD->isBeingDefined()) + return nullptr; + // If there's no definition yet, then DC's definition is added by an update // record, but we've not yet loaded that update record. In this case, we // commit to DC being the canonical definition now, and will fix this when
Index: clang/test/Modules/self-referencing-lambda.cpp =================================================================== --- /dev/null +++ clang/test/Modules/self-referencing-lambda.cpp @@ -0,0 +1,5 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/self-referencing-lambda %s -verify -emit-obj -o %t2.o +// expected-no-diagnostics + +#include "a.h" Index: clang/test/Modules/Inputs/self-referencing-lambda/module.modulemap =================================================================== --- /dev/null +++ clang/test/Modules/Inputs/self-referencing-lambda/module.modulemap @@ -0,0 +1,4 @@ +module "a.h" { + header "a.h" + export * +} Index: clang/test/Modules/Inputs/self-referencing-lambda/a.h =================================================================== --- /dev/null +++ clang/test/Modules/Inputs/self-referencing-lambda/a.h @@ -0,0 +1,4 @@ +void f() { + int x = 0; + auto q = [xm = x]{}; +} Index: clang/lib/Serialization/ASTReaderDecl.cpp =================================================================== --- clang/lib/Serialization/ASTReaderDecl.cpp +++ clang/lib/Serialization/ASTReaderDecl.cpp @@ -1782,7 +1782,10 @@ else DD = new (C) struct CXXRecordDecl::DefinitionData(D); + assert(!D->IsBeingDefined && "Should not overwrite definition in progress"); + D->IsBeingDefined = true; ReadCXXDefinitionData(*DD, D); + D->IsBeingDefined = false; // We might already have a definition for this record. This can happen either // because we're reading an update record, or because we've already done some @@ -2963,6 +2966,9 @@ if (!DD) DD = RD->getCanonicalDecl()->DefinitionData; + if (!DD && RD->isBeingDefined()) + return nullptr; + // If there's no definition yet, then DC's definition is added by an update // record, but we've not yet loaded that update record. In this case, we // commit to DC being the canonical definition now, and will fix this when
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits