[PATCH] D43494: [Modules] Fix creating fake definition data for lambdas.

Volodymyr Sapsai via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 19 16:45:29 PST 2018


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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D43494.134991.patch
Type: text/x-patch
Size: 2002 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180220/549dcfc7/attachment.bin>


More information about the cfe-commits mailing list