Error ASTNodeImporter::ImportDefinition(
RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind) {
+ auto DefinitionCompleter = [To]() {
+ // There are cases in LLDB when we first import a class without its
+ // members. The class will have DefinitionData, but no members. Then,
+ // importDefinition is called from LLDB, which tries to get the members, so
+ // when we get here, the class already has the DefinitionData set, so we
+ // must unset the CompleteDefinition here to be able to complete again the
+ // definition.
+ To->setCompleteDefinition(false);
+ To->completeDefinition();
+ };
+
if (To->getDefinition() || To->isBeingDefined()) {
if (Kind == IDK_Everything ||
// In case of lambdas, the class already has a definition ptr set, but
Error Result = ImportDeclContext(From, /*ForceImport=*/true);
// Finish the definition of the lambda, set isBeingDefined to false.
if (To->isLambda())
- To->completeDefinition();
+ DefinitionCompleter();
return Result;
}
// Complete the definition even if error is returned.
// The RecordDecl may be already part of the AST so it is better to
// have it in complete state even if something is wrong with it.
- auto DefinitionCompleter =
- llvm::make_scope_exit([To]() { To->completeDefinition(); });
+ auto DefinitionCompleterScopeExit =
+ llvm::make_scope_exit(DefinitionCompleter);
if (Error Err = setTypedefNameForAnonDecl(From, To, Importer))
return Err;
SharedState->getLookupTable()->lookup(ReDC, Name);
return FoundDeclsTy(LookupResult.begin(), LookupResult.end());
} else {
- // FIXME Can we remove this kind of lookup?
- // Or lldb really needs this C/C++ lookup?
- FoundDeclsTy Result;
- ReDC->localUncachedLookup(Name, Result);
+ DeclContext::lookup_result NoloadLookupResult = ReDC->noload_lookup(Name);
+ FoundDeclsTy Result(NoloadLookupResult.begin(), NoloadLookupResult.end());
+ // We must search by the slow case of localUncachedLookup because that is
+ // working even if there is no LookupPtr for the DC. We could use
+ // DC::buildLookup() to create the LookupPtr, but that would load external
+ // decls again, we must avoid that case.
+ // Also, even if we had the LookupPtr, we must find Decls which are not
+ // in the LookupPtr, so we need the slow case.
+ // These cases are handled in ASTImporterLookupTable, but we cannot use
+ // that with LLDB since that traverses through the AST which initiates the
+ // load of external decls again via DC::decls(). And again, we must avoid
+ // loading external decls during the import.
+ if (Result.empty())
+ ReDC->localUncachedLookup(Name, Result);
return Result;
}
}
EXPECT_EQ(ToLSize, FromLSize);
}
+struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
+ LLDBLookupTest() {
+ Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
+ ASTContext &FromContext, FileManager &FromFileManager,
+ bool MinimalImport,
+ const std::shared_ptr<ASTImporterSharedState> &SharedState) {
+ return new ASTImporter(ToContext, ToFileManager, FromContext,
+ FromFileManager, MinimalImport,
+ // We use the regular lookup.
+ /*SharedState=*/nullptr);
+ };
+ }
+};
+
+TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ extern "C" {
+ class X{};
+ };
+ )",
+ Lang_CXX);
+ auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
+ ToTU, cxxRecordDecl(hasName("X")));
+
+ // Set up a stub external storage.
+ ToTU->setHasExternalLexicalStorage(true);
+ // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
+ ToTU->setMustBuildLookupTable();
+ struct TestExternalASTSource : ExternalASTSource {};
+ ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ class X;
+ )",
+ Lang_CXX);
+ auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("X")));
+ auto *ImportedX = Import(FromX, Lang_CXX);
+ // The lookup must find the existing class definition in the LinkageSpecDecl.
+ // Then the importer renders the existing and the new decl into one chain.
+ EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
+}
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
DefaultTestValuesForRunOptions, );
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
+ DefaultTestValuesForRunOptions, );
+
} // end namespace ast_matchers
} // end namespace clang