r328153 - [Modules] Fix creating fake definition data for lambdas.

Volodymyr Sapsai via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 21 14:28:55 PDT 2018


Author: vsapsai
Date: Wed Mar 21 14:28:54 2018
New Revision: 328153

URL: http://llvm.org/viewvc/llvm-project?rev=328153&view=rev
Log:
[Modules] Fix creating fake definition data for lambdas.

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 assign definition data before reading it. Fixes PR32556.

rdar://problem/37461072

Reviewers: rsmith, bruno

Reviewed By: rsmith

Subscribers: cfe-commits, jkorous-apple, aprantl

Differential Revision: https://reviews.llvm.org/D43494


Added:
    cfe/trunk/test/Modules/Inputs/self-referencing-lambda/
    cfe/trunk/test/Modules/Inputs/self-referencing-lambda/a.h
    cfe/trunk/test/Modules/Inputs/self-referencing-lambda/module.modulemap
    cfe/trunk/test/Modules/self-referencing-lambda.cpp
Modified:
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=328153&r1=328152&r2=328153&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Mar 21 14:28:54 2018
@@ -1784,29 +1784,31 @@ void ASTDeclReader::ReadCXXRecordDefinit
   else
     DD = new (C) struct CXXRecordDecl::DefinitionData(D);
 
+  CXXRecordDecl *Canon = D->getCanonicalDecl();
+  // Set decl definition data before reading it, so that during deserialization
+  // when we read CXXRecordDecl, it already has definition data and we don't
+  // set fake one.
+  if (!Canon->DefinitionData)
+    Canon->DefinitionData = DD;
+  D->DefinitionData = Canon->DefinitionData;
   ReadCXXDefinitionData(*DD, D);
 
-  // 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
-  // merging. Either way, just merge into it.
-  CXXRecordDecl *Canon = D->getCanonicalDecl();
-  if (Canon->DefinitionData) {
+  // We might already have a different definition for this record. This can
+  // happen either because we're reading an update record, or because we've
+  // already done some merging. Either way, just merge into it.
+  if (Canon->DefinitionData != DD) {
     MergeDefinitionData(Canon, std::move(*DD));
-    D->DefinitionData = Canon->DefinitionData;
     return;
   }
 
   // Mark this declaration as being a definition.
   D->IsCompleteDefinition = true;
-  D->DefinitionData = DD;
 
   // If this is not the first declaration or is an update record, we can have
   // other redeclarations already. Make a note that we need to propagate the
   // DefinitionData pointer onto them.
-  if (Update || Canon != D) {
-    Canon->DefinitionData = D->DefinitionData;
+  if (Update || Canon != D)
     Reader.PendingDefinitions.insert(D);
-  }
 }
 
 ASTDeclReader::RedeclarableResult

Added: cfe/trunk/test/Modules/Inputs/self-referencing-lambda/a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/self-referencing-lambda/a.h?rev=328153&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/self-referencing-lambda/a.h (added)
+++ cfe/trunk/test/Modules/Inputs/self-referencing-lambda/a.h Wed Mar 21 14:28:54 2018
@@ -0,0 +1,4 @@
+void f() {
+  int x = 0;
+  auto q = [xm = x]{};
+}

Added: cfe/trunk/test/Modules/Inputs/self-referencing-lambda/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/self-referencing-lambda/module.modulemap?rev=328153&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/self-referencing-lambda/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/self-referencing-lambda/module.modulemap Wed Mar 21 14:28:54 2018
@@ -0,0 +1,4 @@
+module "a.h" {
+  header "a.h"
+  export *
+}

Added: cfe/trunk/test/Modules/self-referencing-lambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/self-referencing-lambda.cpp?rev=328153&view=auto
==============================================================================
--- cfe/trunk/test/Modules/self-referencing-lambda.cpp (added)
+++ cfe/trunk/test/Modules/self-referencing-lambda.cpp Wed Mar 21 14:28:54 2018
@@ -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"




More information about the cfe-commits mailing list