[PATCH] D94067: [clang][ASTImporter] Fix a possible assertion failure `NeedsInjectedClassNameType(Decl)'.

Balázs Kéri via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 5 01:01:14 PST 2021


balazske created this revision.
Herald added subscribers: martong, teemperor, gamesh411, Szelethus, dkrupp.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
balazske requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The assertion can happen if ASTImporter imports a CXXRecordDecl in a template
and then imports another redeclaration of this declaration, while the first import is in progress.
The process of first import did not set the "described template" yet
and the second import finds the first declaration at setting the injected types.
Setting the injected type requires in the assertion that the described template is set.
The exact assertion was:
clang/lib/AST/ASTContext.cpp:4411:
clang::QualType clang::ASTContext::getInjectedClassNameType(clang::CXXRecordDecl*, clang::QualType) const:
Assertion `NeedsInjectedClassNameType(Decl)' failed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D94067

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp


Index: clang/unittests/AST/ASTImporterTest.cpp
===================================================================
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -6141,6 +6141,41 @@
   EXPECT_EQ(ToAttr->getAnnotation(), "A");
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase,
+       ImportOfTemplatedDeclWhenPreviousDeclHasNoDescribedTemplateSet) {
+  Decl *FromTU = getTuDecl(
+      R"(
+
+      namespace std {
+        template<typename T>
+        class basic_stringbuf;
+      }
+      namespace std {
+        class char_traits;
+        template<typename T = char_traits>
+        class basic_stringbuf;
+      }
+      namespace std {
+        template<typename T>
+        class basic_stringbuf {};
+      }
+
+      )",
+      Lang_CXX11);
+
+  auto *From1 = FirstDeclMatcher<ClassTemplateDecl>().match(
+      FromTU,
+      classTemplateDecl(hasName("basic_stringbuf"), unless(isImplicit())));
+  auto *To1 = cast_or_null<ClassTemplateDecl>(Import(From1, Lang_CXX11));
+  EXPECT_TRUE(To1);
+
+  auto *From2 = LastDeclMatcher<ClassTemplateDecl>().match(
+      FromTU,
+      classTemplateDecl(hasName("basic_stringbuf"), unless(isImplicit())));
+  auto *To2 = cast_or_null<ClassTemplateDecl>(Import(From2, Lang_CXX11));
+  EXPECT_TRUE(To2);
+}
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
                         DefaultTestValuesForRunOptions, );
 
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -2897,6 +2897,17 @@
             getCanonicalForwardRedeclChain(D2CXX);
         for (auto *R : Redecls) {
           auto *RI = cast<CXXRecordDecl>(R);
+          // Skip this declaration if it is currently under import and
+          // incomplete. Because it is under import we will reach this place in
+          // its own import call. At import of a "templated" CXXRecordDecl the
+          // described template is imported first and that import call sets the
+          // described template. But before this is done other imports happen so
+          // this case may occur.
+          if (!RI->getDescribedTemplate())
+            continue;
+          // Skip the declaration if injected type is already set.
+          if (isa<InjectedClassNameType>(RI->getTypeForDecl()))
+            continue;
           RI->setTypeForDecl(nullptr);
           // Below we create a new injected type and assign that to the
           // canonical decl, subsequent declarations in the chain will reuse


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D94067.314518.patch
Type: text/x-patch
Size: 2611 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210105/8cd4b171/attachment.bin>


More information about the cfe-commits mailing list