r360572 - [ASTImporter] Separate unittest files
Gabor Marton via cfe-commits
cfe-commits at lists.llvm.org
Mon May 13 03:06:25 PDT 2019
Author: martong
Date: Mon May 13 03:06:25 2019
New Revision: 360572
URL: http://llvm.org/viewvc/llvm-project?rev=360572&view=rev
Log:
[ASTImporter] Separate unittest files
Summary:
Move generic redecl chain tests and visibility tests into their own
separate test files.
Reviewers: a_sidorin, a.sidorin, shafik
Subscribers: mgorny, rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D61786
Added:
cfe/trunk/unittests/AST/ASTImporterFixtures.cpp
cfe/trunk/unittests/AST/ASTImporterFixtures.h
cfe/trunk/unittests/AST/ASTImporterGenericRedeclTest.cpp
cfe/trunk/unittests/AST/ASTImporterVisibilityTest.cpp
Modified:
cfe/trunk/unittests/AST/ASTImporterTest.cpp
cfe/trunk/unittests/AST/CMakeLists.txt
Added: cfe/trunk/unittests/AST/ASTImporterFixtures.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterFixtures.cpp?rev=360572&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterFixtures.cpp (added)
+++ cfe/trunk/unittests/AST/ASTImporterFixtures.cpp Mon May 13 03:06:25 2019
@@ -0,0 +1,210 @@
+//===- unittest/AST/ASTImporterFixtures.cpp - AST unit test support -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Implementation of fixture classes for testing the ASTImporter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTImporterFixtures.h"
+
+#include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterLookupTable.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Tooling/Tooling.h"
+
+namespace clang {
+namespace ast_matchers {
+
+void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
+ std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
+ assert(ToAST);
+ ASTContext &ToCtx = ToAST->getASTContext();
+ auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
+ &ToCtx.getSourceManager().getFileManager().getVirtualFileSystem());
+ auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
+ OFS->overlays_begin()->get());
+ MFS->addFile(FileName, 0, std::move(Buffer));
+}
+
+void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
+ StringRef Code) {
+ return createVirtualFileIfNeeded(ToAST, FileName,
+ llvm::MemoryBuffer::getMemBuffer(Code));
+}
+
+ASTImporterTestBase::TU::TU(StringRef Code, StringRef FileName, ArgVector Args,
+ ImporterConstructor C)
+ : Code(Code), FileName(FileName),
+ Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args, this->FileName)),
+ TUDecl(Unit->getASTContext().getTranslationUnitDecl()), Creator(C) {
+ Unit->enableSourceFileDiagnostics();
+
+ // If the test doesn't need a specific ASTImporter, we just create a
+ // normal ASTImporter with it.
+ if (!Creator)
+ Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
+ ASTContext &FromContext, FileManager &FromFileManager,
+ bool MinimalImport, ASTImporterLookupTable *LookupTable) {
+ return new ASTImporter(ToContext, ToFileManager, FromContext,
+ FromFileManager, MinimalImport, LookupTable);
+ };
+}
+
+ASTImporterTestBase::TU::~TU() {}
+
+void ASTImporterTestBase::TU::lazyInitImporter(
+ ASTImporterLookupTable &LookupTable, ASTUnit *ToAST) {
+ assert(ToAST);
+ if (!Importer)
+ Importer.reset(Creator(ToAST->getASTContext(), ToAST->getFileManager(),
+ Unit->getASTContext(), Unit->getFileManager(), false,
+ &LookupTable));
+ assert(&ToAST->getASTContext() == &Importer->getToContext());
+ createVirtualFileIfNeeded(ToAST, FileName, Code);
+}
+
+Decl *ASTImporterTestBase::TU::import(ASTImporterLookupTable &LookupTable,
+ ASTUnit *ToAST, Decl *FromDecl) {
+ lazyInitImporter(LookupTable, ToAST);
+ if (auto ImportedOrErr = Importer->Import_New(FromDecl))
+ return *ImportedOrErr;
+ else {
+ llvm::consumeError(ImportedOrErr.takeError());
+ return nullptr;
+ }
+}
+
+QualType ASTImporterTestBase::TU::import(ASTImporterLookupTable &LookupTable,
+ ASTUnit *ToAST, QualType FromType) {
+ lazyInitImporter(LookupTable, ToAST);
+ if (auto ImportedOrErr = Importer->Import_New(FromType))
+ return *ImportedOrErr;
+ else {
+ llvm::consumeError(ImportedOrErr.takeError());
+ return QualType{};
+ }
+}
+
+void ASTImporterTestBase::lazyInitLookupTable(TranslationUnitDecl *ToTU) {
+ assert(ToTU);
+ if (!LookupTablePtr)
+ LookupTablePtr = llvm::make_unique<ASTImporterLookupTable>(*ToTU);
+}
+
+void ASTImporterTestBase::lazyInitToAST(Language ToLang, StringRef ToSrcCode,
+ StringRef FileName) {
+ if (ToAST)
+ return;
+ ArgVector ToArgs = getArgVectorForLanguage(ToLang);
+ // Source code must be a valid live buffer through the tests lifetime.
+ ToCode = ToSrcCode;
+ // Build the AST from an empty file.
+ ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
+ ToAST->enableSourceFileDiagnostics();
+ lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
+}
+
+ASTImporterTestBase::TU *ASTImporterTestBase::findFromTU(Decl *From) {
+ // Create a virtual file in the To Ctx which corresponds to the file from
+ // which we want to import the `From` Decl. Without this source locations
+ // will be invalid in the ToCtx.
+ auto It = llvm::find_if(FromTUs, [From](const TU &E) {
+ return E.TUDecl == From->getTranslationUnitDecl();
+ });
+ assert(It != FromTUs.end());
+ return &*It;
+}
+
+std::tuple<Decl *, Decl *>
+ASTImporterTestBase::getImportedDecl(StringRef FromSrcCode, Language FromLang,
+ StringRef ToSrcCode, Language ToLang,
+ StringRef Identifier) {
+ ArgVector FromArgs = getArgVectorForLanguage(FromLang),
+ ToArgs = getArgVectorForLanguage(ToLang);
+
+ FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs, Creator);
+ TU &FromTU = FromTUs.back();
+
+ assert(!ToAST);
+ lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
+
+ ASTContext &FromCtx = FromTU.Unit->getASTContext();
+
+ IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
+ assert(ImportedII && "Declaration with the given identifier "
+ "should be specified in test!");
+ DeclarationName ImportDeclName(ImportedII);
+ SmallVector<NamedDecl *, 1> FoundDecls;
+ FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
+ FoundDecls);
+
+ assert(FoundDecls.size() == 1);
+
+ Decl *Imported =
+ FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
+
+ assert(Imported);
+ return std::make_tuple(*FoundDecls.begin(), Imported);
+}
+
+TranslationUnitDecl *ASTImporterTestBase::getTuDecl(StringRef SrcCode,
+ Language Lang,
+ StringRef FileName) {
+ assert(llvm::find_if(FromTUs, [FileName](const TU &E) {
+ return E.FileName == FileName;
+ }) == FromTUs.end());
+
+ ArgVector Args = getArgVectorForLanguage(Lang);
+ FromTUs.emplace_back(SrcCode, FileName, Args);
+ TU &Tu = FromTUs.back();
+
+ return Tu.TUDecl;
+}
+
+TranslationUnitDecl *ASTImporterTestBase::getToTuDecl(StringRef ToSrcCode,
+ Language ToLang) {
+ ArgVector ToArgs = getArgVectorForLanguage(ToLang);
+ assert(!ToAST);
+ lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
+ return ToAST->getASTContext().getTranslationUnitDecl();
+}
+
+Decl *ASTImporterTestBase::Import(Decl *From, Language ToLang) {
+ lazyInitToAST(ToLang, "", OutputFileName);
+ TU *FromTU = findFromTU(From);
+ assert(LookupTablePtr);
+ return FromTU->import(*LookupTablePtr, ToAST.get(), From);
+}
+
+QualType ASTImporterTestBase::ImportType(QualType FromType, Decl *TUDecl,
+ Language ToLang) {
+ lazyInitToAST(ToLang, "", OutputFileName);
+ TU *FromTU = findFromTU(TUDecl);
+ assert(LookupTablePtr);
+ return FromTU->import(*LookupTablePtr, ToAST.get(), FromType);
+}
+
+ASTImporterTestBase::~ASTImporterTestBase() {
+ if (!::testing::Test::HasFailure())
+ return;
+
+ for (auto &Tu : FromTUs) {
+ assert(Tu.Unit);
+ llvm::errs() << "FromAST:\n";
+ Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
+ llvm::errs() << "\n";
+ }
+ if (ToAST) {
+ llvm::errs() << "ToAST:\n";
+ ToAST->getASTContext().getTranslationUnitDecl()->dump();
+ }
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
Added: cfe/trunk/unittests/AST/ASTImporterFixtures.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterFixtures.h?rev=360572&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterFixtures.h (added)
+++ cfe/trunk/unittests/AST/ASTImporterFixtures.h Mon May 13 03:06:25 2019
@@ -0,0 +1,176 @@
+//===- unittest/AST/ASTImporterFixtures.h - AST unit test support ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Fixture classes for testing the ASTImporter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_AST_IMPORTER_FIXTURES_H
+#define LLVM_CLANG_UNITTESTS_AST_IMPORTER_FIXTURES_H
+
+#include "gmock/gmock.h"
+
+#include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterLookupTable.h"
+#include "clang/Frontend/ASTUnit.h"
+
+#include "DeclMatcher.h"
+#include "Language.h"
+
+namespace clang {
+
+class ASTImporter;
+class ASTImporterLookupTable;
+class ASTUnit;
+
+namespace ast_matchers {
+
+const StringRef DeclToImportID = "declToImport";
+const StringRef DeclToVerifyID = "declToVerify";
+
+// Creates a virtual file and assigns that to the context of given AST. If the
+// file already exists then the file will not be created again as a duplicate.
+void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
+ std::unique_ptr<llvm::MemoryBuffer> &&Buffer);
+
+void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
+ StringRef Code);
+
+// Common base for the different families of ASTImporter tests that are
+// parameterized on the compiler options which may result a different AST. E.g.
+// -fms-compatibility or -fdelayed-template-parsing.
+class CompilerOptionSpecificTest : public ::testing::Test {
+protected:
+ // Return the extra arguments appended to runtime options at compilation.
+ virtual ArgVector getExtraArgs() const { return ArgVector(); }
+
+ // Returns the argument vector used for a specific language option, this set
+ // can be tweaked by the test parameters.
+ ArgVector getArgVectorForLanguage(Language Lang) const {
+ ArgVector Args = getBasicRunOptionsForLanguage(Lang);
+ ArgVector ExtraArgs = getExtraArgs();
+ for (const auto &Arg : ExtraArgs) {
+ Args.push_back(Arg);
+ }
+ return Args;
+ }
+};
+
+const auto DefaultTestValuesForRunOptions = ::testing::Values(
+ ArgVector(), ArgVector{"-fdelayed-template-parsing"},
+ ArgVector{"-fms-compatibility"},
+ ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
+
+// This class provides generic methods to write tests which can check internal
+// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
+// this fixture makes it possible to import from several "From" contexts.
+class ASTImporterTestBase : public CompilerOptionSpecificTest {
+
+ const char *const InputFileName = "input.cc";
+ const char *const OutputFileName = "output.cc";
+
+public:
+ /// Allocates an ASTImporter (or one of its subclasses).
+ typedef std::function<ASTImporter *(ASTContext &, FileManager &, ASTContext &,
+ FileManager &, bool,
+ ASTImporterLookupTable *)>
+ ImporterConstructor;
+
+ // The lambda that constructs the ASTImporter we use in this test.
+ ImporterConstructor Creator;
+
+private:
+ // Buffer for the To context, must live in the test scope.
+ std::string ToCode;
+
+ // Represents a "From" translation unit and holds an importer object which we
+ // use to import from this translation unit.
+ struct TU {
+ // Buffer for the context, must live in the test scope.
+ std::string Code;
+ std::string FileName;
+ std::unique_ptr<ASTUnit> Unit;
+ TranslationUnitDecl *TUDecl = nullptr;
+ std::unique_ptr<ASTImporter> Importer;
+ ImporterConstructor Creator;
+
+ TU(StringRef Code, StringRef FileName, ArgVector Args,
+ ImporterConstructor C = ImporterConstructor());
+ ~TU();
+
+ void lazyInitImporter(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST);
+ Decl *import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
+ Decl *FromDecl);
+ QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
+ QualType FromType);
+ };
+
+ // We may have several From contexts and related translation units. In each
+ // AST, the buffers for the source are handled via references and are set
+ // during the creation of the AST. These references must point to a valid
+ // buffer until the AST is alive. Thus, we must use a list in order to avoid
+ // moving of the stored objects because that would mean breaking the
+ // references in the AST. By using a vector a move could happen when the
+ // vector is expanding, with the list we won't have these issues.
+ std::list<TU> FromTUs;
+
+ // Initialize the lookup table if not initialized already.
+ void lazyInitLookupTable(TranslationUnitDecl *ToTU);
+
+ void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName);
+ TU *findFromTU(Decl *From);
+
+protected:
+ std::unique_ptr<ASTImporterLookupTable> LookupTablePtr;
+
+public:
+ // We may have several From context but only one To context.
+ std::unique_ptr<ASTUnit> ToAST;
+
+ // Creates an AST both for the From and To source code and imports the Decl
+ // of the identifier into the To context.
+ // Must not be called more than once within the same test.
+ std::tuple<Decl *, Decl *>
+ getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
+ Language ToLang, StringRef Identifier = DeclToImportID);
+
+ // Creates a TU decl for the given source code which can be used as a From
+ // context. May be called several times in a given test (with different file
+ // name).
+ TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
+ StringRef FileName = "input.cc");
+
+ // Creates the To context with the given source code and returns the TU decl.
+ TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang);
+
+ // Import the given Decl into the ToCtx.
+ // May be called several times in a given test.
+ // The different instances of the param From may have different ASTContext.
+ Decl *Import(Decl *From, Language ToLang);
+
+ template <class DeclT> DeclT *Import(DeclT *From, Language Lang) {
+ return cast_or_null<DeclT>(Import(cast<Decl>(From), Lang));
+ }
+
+ QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang);
+
+ ~ASTImporterTestBase();
+};
+
+class ASTImporterOptionSpecificTestBase
+ : public ASTImporterTestBase,
+ public ::testing::WithParamInterface<ArgVector> {
+protected:
+ ArgVector getExtraArgs() const override { return GetParam(); }
+};
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif
Added: cfe/trunk/unittests/AST/ASTImporterGenericRedeclTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterGenericRedeclTest.cpp?rev=360572&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterGenericRedeclTest.cpp (added)
+++ cfe/trunk/unittests/AST/ASTImporterGenericRedeclTest.cpp Mon May 13 03:06:25 2019
@@ -0,0 +1,577 @@
+//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Type-parameterized tests for the correct import of redecl chains.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTImporterFixtures.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using internal::BindableMatcher;
+
+struct Function {
+ using DeclTy = FunctionDecl;
+ static constexpr auto *Prototype = "void X();";
+ static constexpr auto *Definition = "void X() {}";
+ BindableMatcher<Decl> getPattern() {
+ return functionDecl(hasName("X"), unless(isImplicit()));
+ }
+};
+
+struct Class {
+ using DeclTy = CXXRecordDecl;
+ static constexpr auto *Prototype = "class X;";
+ static constexpr auto *Definition = "class X {};";
+ BindableMatcher<Decl> getPattern() {
+ return cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ }
+};
+
+struct Variable {
+ using DeclTy = VarDecl;
+ static constexpr auto *Prototype = "extern int X;";
+ static constexpr auto *Definition = "int X;";
+ BindableMatcher<Decl> getPattern() { return varDecl(hasName("X")); }
+};
+
+struct FunctionTemplate {
+ using DeclTy = FunctionTemplateDecl;
+ static constexpr auto *Prototype = "template <class T> void X();";
+ static constexpr auto *Definition =
+ R"(
+ template <class T> void X() {};
+ // Explicit instantiation is a must because of -fdelayed-template-parsing:
+ template void X<int>();
+ )";
+ BindableMatcher<Decl> getPattern() {
+ return functionTemplateDecl(hasName("X"), unless(isImplicit()));
+ }
+};
+
+struct ClassTemplate {
+ using DeclTy = ClassTemplateDecl;
+ static constexpr auto *Prototype = "template <class T> class X;";
+ static constexpr auto *Definition = "template <class T> class X {};";
+ BindableMatcher<Decl> getPattern() {
+ return classTemplateDecl(hasName("X"), unless(isImplicit()));
+ }
+};
+
+struct FunctionTemplateSpec {
+ using DeclTy = FunctionDecl;
+ static constexpr auto *Prototype =
+ R"(
+ // Proto of the primary template.
+ template <class T>
+ void X();
+ // Proto of the specialization.
+ template <>
+ void X<int>();
+ )";
+ static constexpr auto *Definition =
+ R"(
+ // Proto of the primary template.
+ template <class T>
+ void X();
+ // Specialization and definition.
+ template <>
+ void X<int>() {}
+ )";
+ BindableMatcher<Decl> getPattern() {
+ return functionDecl(hasName("X"), isExplicitTemplateSpecialization());
+ }
+};
+
+struct ClassTemplateSpec {
+ using DeclTy = ClassTemplateSpecializationDecl;
+ static constexpr auto *Prototype =
+ R"(
+ template <class T> class X;
+ template <> class X<int>;
+ )";
+ static constexpr auto *Definition =
+ R"(
+ template <class T> class X;
+ template <> class X<int> {};
+ )";
+ BindableMatcher<Decl> getPattern() {
+ return classTemplateSpecializationDecl(hasName("X"), unless(isImplicit()));
+ }
+};
+
+template <typename TypeParam>
+struct RedeclChain : ASTImporterOptionSpecificTestBase {
+
+ using DeclTy = typename TypeParam::DeclTy;
+ std::string getPrototype() { return TypeParam::Prototype; }
+ std::string getDefinition() { return TypeParam::Definition; }
+ BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); }
+
+ void CheckPreviousDecl(Decl *Prev, Decl *Current) {
+ ASSERT_NE(Prev, Current);
+ ASSERT_EQ(&Prev->getASTContext(), &Current->getASTContext());
+ EXPECT_EQ(Prev->getCanonicalDecl(), Current->getCanonicalDecl());
+
+ // Templates.
+ if (auto *PrevT = dyn_cast<TemplateDecl>(Prev)) {
+ EXPECT_EQ(Current->getPreviousDecl(), Prev);
+ auto *CurrentT = cast<TemplateDecl>(Current);
+ ASSERT_TRUE(PrevT->getTemplatedDecl());
+ ASSERT_TRUE(CurrentT->getTemplatedDecl());
+ EXPECT_EQ(CurrentT->getTemplatedDecl()->getPreviousDecl(),
+ PrevT->getTemplatedDecl());
+ return;
+ }
+
+ // Specializations.
+ if (auto *PrevF = dyn_cast<FunctionDecl>(Prev)) {
+ if (PrevF->getTemplatedKind() ==
+ FunctionDecl::TK_FunctionTemplateSpecialization) {
+ // There may be a hidden fwd spec decl before a spec decl.
+ // In that case the previous visible decl can be reached through that
+ // invisible one.
+ EXPECT_THAT(Prev, testing::AnyOf(
+ Current->getPreviousDecl(),
+ Current->getPreviousDecl()->getPreviousDecl()));
+ auto *ToTU = Prev->getTranslationUnitDecl();
+ auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
+ ToTU, functionTemplateDecl());
+ auto *FirstSpecD = *(TemplateD->spec_begin());
+ EXPECT_EQ(FirstSpecD->getCanonicalDecl(), PrevF->getCanonicalDecl());
+ return;
+ }
+ }
+
+ // The rest: Classes, Functions, etc.
+ EXPECT_EQ(Current->getPreviousDecl(), Prev);
+ }
+
+ void
+ TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() {
+ Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX);
+ auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ ASSERT_FALSE(FromD->isThisDeclarationADefinition());
+
+ Decl *ImportedD = Import(FromD, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
+ auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(ImportedD == ToD);
+ EXPECT_FALSE(ToD->isThisDeclarationADefinition());
+ if (auto *ToT = dyn_cast<TemplateDecl>(ToD)) {
+ EXPECT_TRUE(ToT->getTemplatedDecl());
+ }
+ }
+
+ void TypedTest_DefinitionShouldBeImportedAsADefinition() {
+ Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
+ auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ ASSERT_TRUE(FromD->isThisDeclarationADefinition());
+
+ Decl *ImportedD = Import(FromD, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
+ auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(ToD->isThisDeclarationADefinition());
+ if (auto *ToT = dyn_cast<TemplateDecl>(ToD)) {
+ EXPECT_TRUE(ToT->getTemplatedDecl());
+ }
+ }
+
+ void TypedTest_ImportPrototypeAfterImportedPrototype() {
+ Decl *FromTU = getTuDecl(getPrototype() + getPrototype(), Lang_CXX);
+ auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ auto *From1 = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ ASSERT_FALSE(From0->isThisDeclarationADefinition());
+ ASSERT_FALSE(From1->isThisDeclarationADefinition());
+
+ Decl *Imported0 = Import(From0, Lang_CXX);
+ Decl *Imported1 = Import(From1, Lang_CXX);
+ Decl *ToTU = Imported0->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
+ auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(Imported0 == To0);
+ EXPECT_TRUE(Imported1 == To1);
+ EXPECT_FALSE(To0->isThisDeclarationADefinition());
+ EXPECT_FALSE(To1->isThisDeclarationADefinition());
+
+ CheckPreviousDecl(To0, To1);
+ }
+
+ void TypedTest_ImportDefinitionAfterImportedPrototype() {
+ Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
+ auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ auto *FromDef = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
+ ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
+
+ Decl *ImportedProto = Import(FromProto, Lang_CXX);
+ Decl *ImportedDef = Import(FromDef, Lang_CXX);
+ Decl *ToTU = ImportedProto->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
+ auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(ImportedProto == ToProto);
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+
+ CheckPreviousDecl(ToProto, ToDef);
+ }
+
+ void TypedTest_ImportPrototypeAfterImportedDefinition() {
+ Decl *FromTU = getTuDecl(getDefinition() + getPrototype(), Lang_CXX);
+ auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ auto *FromProto = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
+ ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
+
+ Decl *ImportedDef = Import(FromDef, Lang_CXX);
+ Decl *ImportedProto = Import(FromProto, Lang_CXX);
+ Decl *ToTU = ImportedDef->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
+ auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ImportedProto == ToProto);
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+
+ CheckPreviousDecl(ToDef, ToProto);
+ }
+
+ void TypedTest_ImportPrototypes() {
+ Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
+ Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
+ auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
+ auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
+ ASSERT_FALSE(From0->isThisDeclarationADefinition());
+ ASSERT_FALSE(From1->isThisDeclarationADefinition());
+
+ Decl *Imported0 = Import(From0, Lang_CXX);
+ Decl *Imported1 = Import(From1, Lang_CXX);
+ Decl *ToTU = Imported0->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
+ auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(Imported0 == To0);
+ EXPECT_TRUE(Imported1 == To1);
+ EXPECT_FALSE(To0->isThisDeclarationADefinition());
+ EXPECT_FALSE(To1->isThisDeclarationADefinition());
+
+ CheckPreviousDecl(To0, To1);
+ }
+
+ void TypedTest_ImportDefinitions() {
+ Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
+ Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
+ auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
+ auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
+ ASSERT_TRUE(From0->isThisDeclarationADefinition());
+ ASSERT_TRUE(From1->isThisDeclarationADefinition());
+
+ Decl *Imported0 = Import(From0, Lang_CXX);
+ Decl *Imported1 = Import(From1, Lang_CXX);
+ Decl *ToTU = Imported0->getTranslationUnitDecl();
+
+ EXPECT_EQ(Imported0, Imported1);
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
+ auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(Imported0 == To0);
+ EXPECT_TRUE(To0->isThisDeclarationADefinition());
+ if (auto *ToT0 = dyn_cast<TemplateDecl>(To0)) {
+ EXPECT_TRUE(ToT0->getTemplatedDecl());
+ }
+ }
+
+ void TypedTest_ImportDefinitionThenPrototype() {
+ Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
+ Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
+ auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
+ auto *FromProto =
+ FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
+ ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
+ ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
+
+ Decl *ImportedDef = Import(FromDef, Lang_CXX);
+ Decl *ImportedProto = Import(FromProto, Lang_CXX);
+ Decl *ToTU = ImportedDef->getTranslationUnitDecl();
+
+ EXPECT_NE(ImportedDef, ImportedProto);
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
+ auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ImportedProto == ToProto);
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+
+ CheckPreviousDecl(ToDef, ToProto);
+ }
+
+ void TypedTest_ImportPrototypeThenDefinition() {
+ Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
+ Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
+ auto *FromProto =
+ FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
+ auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
+ ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
+ ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
+
+ Decl *ImportedProto = Import(FromProto, Lang_CXX);
+ Decl *ImportedDef = Import(FromDef, Lang_CXX);
+ Decl *ToTU = ImportedDef->getTranslationUnitDecl();
+
+ EXPECT_NE(ImportedDef, ImportedProto);
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
+ auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ImportedProto == ToProto);
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+
+ CheckPreviousDecl(ToProto, ToDef);
+ }
+
+ void TypedTest_WholeRedeclChainIsImportedAtOnce() {
+ Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
+ auto *FromD = // Definition
+ LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ ASSERT_TRUE(FromD->isThisDeclarationADefinition());
+
+ Decl *ImportedD = Import(FromD, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ // The whole redecl chain is imported at once.
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
+ EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition());
+ }
+
+ void TypedTest_ImportPrototypeThenProtoAndDefinition() {
+ {
+ Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ Import(FromD, Lang_CXX);
+ }
+ {
+ Decl *FromTU =
+ getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+ Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+
+ ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u);
+ DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_FALSE(ProtoD->isThisDeclarationADefinition());
+
+ DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
+ EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition());
+
+ EXPECT_TRUE(DefinitionD->getPreviousDecl());
+ EXPECT_FALSE(
+ DefinitionD->getPreviousDecl()->isThisDeclarationADefinition());
+
+ CheckPreviousDecl(ProtoD, DefinitionD->getPreviousDecl());
+ }
+};
+
+#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \
+ NamePrefix, TestCase) \
+ using BaseTemplate##TypeParam = BaseTemplate<TypeParam>; \
+ TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \
+ TypedTest_##TestCase(); \
+ }
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
+ RedeclChain, Function, ,
+ PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
+ RedeclChain, Class, ,
+ PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
+ RedeclChain, Variable, ,
+ PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
+ RedeclChain, FunctionTemplate, ,
+ PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
+ RedeclChain, ClassTemplate, ,
+ PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
+ RedeclChain, FunctionTemplateSpec, ,
+ PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
+ RedeclChain, ClassTemplateSpec, ,
+ PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ DefinitionShouldBeImportedAsADefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
+ DefinitionShouldBeImportedAsADefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ DefinitionShouldBeImportedAsADefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ DefinitionShouldBeImportedAsADefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
+ DefinitionShouldBeImportedAsADefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ DefinitionShouldBeImportedAsADefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
+ DefinitionShouldBeImportedAsADefinition)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ ImportPrototypeAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
+ ImportPrototypeAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ ImportPrototypeAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportPrototypeAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
+ ImportPrototypeAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ ImportPrototypeAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
+ ImportPrototypeAfterImportedPrototype)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ ImportDefinitionAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
+ ImportDefinitionAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ ImportDefinitionAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportDefinitionAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
+ ImportDefinitionAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ ImportDefinitionAfterImportedPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
+ ImportDefinitionAfterImportedPrototype)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ ImportPrototypeAfterImportedDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
+ ImportPrototypeAfterImportedDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ ImportPrototypeAfterImportedDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportPrototypeAfterImportedDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
+ ImportPrototypeAfterImportedDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ ImportPrototypeAfterImportedDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
+ ImportPrototypeAfterImportedDefinition)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ ImportPrototypes)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ ImportPrototypes)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportPrototypes)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
+ ImportPrototypes)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
+ ImportPrototypes)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ ImportPrototypes)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ ImportDefinitions)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportDefinitions)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ ImportDefinitions)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportDefinitions)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
+ ImportDefinitions)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
+ ImportDefinitions)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ ImportDefinitions)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ ImportDefinitionThenPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
+ ImportDefinitionThenPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ ImportDefinitionThenPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportDefinitionThenPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
+ ImportDefinitionThenPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ ImportDefinitionThenPrototype)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
+ ImportDefinitionThenPrototype)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ ImportPrototypeThenDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
+ ImportPrototypeThenDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ ImportPrototypeThenDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportPrototypeThenDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
+ ImportPrototypeThenDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ ImportPrototypeThenDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
+ ImportPrototypeThenDefinition)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ WholeRedeclChainIsImportedAtOnce)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ WholeRedeclChainIsImportedAtOnce)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ WholeRedeclChainIsImportedAtOnce)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ WholeRedeclChainIsImportedAtOnce)
+
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
+ ImportPrototypeThenProtoAndDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
+ ImportPrototypeThenProtoAndDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportPrototypeThenProtoAndDefinition)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
+ ImportPrototypeThenProtoAndDefinition)
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplateSpec,
+ DefaultTestValuesForRunOptions, );
+
+} // end namespace ast_matchers
+} // end namespace clang
Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=360572&r1=360571&r2=360572&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Mon May 13 03:06:25 2019
@@ -10,24 +10,12 @@
//
//===----------------------------------------------------------------------===//
-// Define this to have ::testing::Combine available.
-// FIXME: Better solution for this?
-#define GTEST_HAS_COMBINE 1
+#include "llvm/ADT/StringMap.h"
-#include "clang/AST/ASTImporter.h"
-#include "MatchVerifier.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclContextInternals.h"
-#include "clang/AST/ASTImporter.h"
-#include "clang/AST/ASTImporterLookupTable.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Tooling/Tooling.h"
-
-#include "DeclMatcher.h"
-#include "Language.h"
-#include "gmock/gmock.h"
-#include "llvm/ADT/StringMap.h"
+
+#include "ASTImporterFixtures.h"
+#include "MatchVerifier.h"
namespace clang {
namespace ast_matchers {
@@ -36,54 +24,6 @@ using internal::Matcher;
using internal::BindableMatcher;
using llvm::StringMap;
-// Creates a virtual file and assigns that to the context of given AST. If the
-// file already exists then the file will not be created again as a duplicate.
-static void
-createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
- std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
- assert(ToAST);
- ASTContext &ToCtx = ToAST->getASTContext();
- auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
- &ToCtx.getSourceManager().getFileManager().getVirtualFileSystem());
- auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
- OFS->overlays_begin()->get());
- MFS->addFile(FileName, 0, std::move(Buffer));
-}
-
-static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
- StringRef Code) {
- return createVirtualFileIfNeeded(ToAST, FileName,
- llvm::MemoryBuffer::getMemBuffer(Code));
-}
-
-const StringRef DeclToImportID = "declToImport";
-const StringRef DeclToVerifyID = "declToVerify";
-
-// Common base for the different families of ASTImporter tests that are
-// parameterized on the compiler options which may result a different AST. E.g.
-// -fms-compatibility or -fdelayed-template-parsing.
-class CompilerOptionSpecificTest : public ::testing::Test {
-protected:
- // Return the extra arguments appended to runtime options at compilation.
- virtual ArgVector getExtraArgs() const { return ArgVector(); }
-
- // Returns the argument vector used for a specific language option, this set
- // can be tweaked by the test parameters.
- ArgVector getArgVectorForLanguage(Language Lang) const {
- ArgVector Args = getBasicRunOptionsForLanguage(Lang);
- ArgVector ExtraArgs = getExtraArgs();
- for (const auto &Arg : ExtraArgs) {
- Args.push_back(Arg);
- }
- return Args;
- }
-};
-
-auto DefaultTestValuesForRunOptions = ::testing::Values(
- ArgVector(), ArgVector{"-fdelayed-template-parsing"},
- ArgVector{"-fms-compatibility"},
- ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
-
// Base class for those tests which use the family of `testImport` functions.
class TestImportBase : public CompilerOptionSpecificTest,
public ::testing::WithParamInterface<ArgVector> {
@@ -305,239 +245,6 @@ template <typename T> RecordDecl *getRec
return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
}
-// This class provides generic methods to write tests which can check internal
-// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
-// this fixture makes it possible to import from several "From" contexts.
-class ASTImporterTestBase : public CompilerOptionSpecificTest {
-
- const char *const InputFileName = "input.cc";
- const char *const OutputFileName = "output.cc";
-
-public:
- /// Allocates an ASTImporter (or one of its subclasses).
- typedef std::function<ASTImporter *(ASTContext &, FileManager &, ASTContext &,
- FileManager &, bool,
- ASTImporterLookupTable *)>
- ImporterConstructor;
-
- // The lambda that constructs the ASTImporter we use in this test.
- ImporterConstructor Creator;
-
-private:
- // Buffer for the To context, must live in the test scope.
- std::string ToCode;
-
- // Represents a "From" translation unit and holds an importer object which we
- // use to import from this translation unit.
- struct TU {
- // Buffer for the context, must live in the test scope.
- std::string Code;
- std::string FileName;
- std::unique_ptr<ASTUnit> Unit;
- TranslationUnitDecl *TUDecl = nullptr;
- std::unique_ptr<ASTImporter> Importer;
- ImporterConstructor Creator;
- TU(StringRef Code, StringRef FileName, ArgVector Args,
- ImporterConstructor C = ImporterConstructor())
- : Code(Code), FileName(FileName),
- Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
- this->FileName)),
- TUDecl(Unit->getASTContext().getTranslationUnitDecl()), Creator(C) {
- Unit->enableSourceFileDiagnostics();
-
- // If the test doesn't need a specific ASTImporter, we just create a
- // normal ASTImporter with it.
- if (!Creator)
- Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
- ASTContext &FromContext, FileManager &FromFileManager,
- bool MinimalImport, ASTImporterLookupTable *LookupTable) {
- return new ASTImporter(ToContext, ToFileManager, FromContext,
- FromFileManager, MinimalImport, LookupTable);
- };
- }
-
- void lazyInitImporter(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST) {
- assert(ToAST);
- if (!Importer)
- Importer.reset(Creator(ToAST->getASTContext(), ToAST->getFileManager(),
- Unit->getASTContext(), Unit->getFileManager(),
- false, &LookupTable));
- assert(&ToAST->getASTContext() == &Importer->getToContext());
- createVirtualFileIfNeeded(ToAST, FileName, Code);
- }
-
- Decl *import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
- Decl *FromDecl) {
- lazyInitImporter(LookupTable, ToAST);
- if (auto ImportedOrErr = Importer->Import_New(FromDecl))
- return *ImportedOrErr;
- else {
- llvm::consumeError(ImportedOrErr.takeError());
- return nullptr;
- }
- }
-
- QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
- QualType FromType) {
- lazyInitImporter(LookupTable, ToAST);
- if (auto ImportedOrErr = Importer->Import_New(FromType))
- return *ImportedOrErr;
- else {
- llvm::consumeError(ImportedOrErr.takeError());
- return QualType{};
- }
- }
- };
-
- // We may have several From contexts and related translation units. In each
- // AST, the buffers for the source are handled via references and are set
- // during the creation of the AST. These references must point to a valid
- // buffer until the AST is alive. Thus, we must use a list in order to avoid
- // moving of the stored objects because that would mean breaking the
- // references in the AST. By using a vector a move could happen when the
- // vector is expanding, with the list we won't have these issues.
- std::list<TU> FromTUs;
-
- // Initialize the lookup table if not initialized already.
- void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
- assert(ToTU);
- if (!LookupTablePtr)
- LookupTablePtr = llvm::make_unique<ASTImporterLookupTable>(*ToTU);
- }
-
- void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
- if (ToAST)
- return;
- ArgVector ToArgs = getArgVectorForLanguage(ToLang);
- // Source code must be a valid live buffer through the tests lifetime.
- ToCode = ToSrcCode;
- // Build the AST from an empty file.
- ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
- ToAST->enableSourceFileDiagnostics();
- lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
- }
-
- TU *findFromTU(Decl *From) {
- // Create a virtual file in the To Ctx which corresponds to the file from
- // which we want to import the `From` Decl. Without this source locations
- // will be invalid in the ToCtx.
- auto It = llvm::find_if(FromTUs, [From](const TU &E) {
- return E.TUDecl == From->getTranslationUnitDecl();
- });
- assert(It != FromTUs.end());
- return &*It;
- }
-
-protected:
-
- std::unique_ptr<ASTImporterLookupTable> LookupTablePtr;
-
-public:
- // We may have several From context but only one To context.
- std::unique_ptr<ASTUnit> ToAST;
-
- // Creates an AST both for the From and To source code and imports the Decl
- // of the identifier into the To context.
- // Must not be called more than once within the same test.
- std::tuple<Decl *, Decl *>
- getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
- Language ToLang, StringRef Identifier = DeclToImportID) {
- ArgVector FromArgs = getArgVectorForLanguage(FromLang),
- ToArgs = getArgVectorForLanguage(ToLang);
-
- FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs, Creator);
- TU &FromTU = FromTUs.back();
-
- assert(!ToAST);
- lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
-
- ASTContext &FromCtx = FromTU.Unit->getASTContext();
-
- IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
- assert(ImportedII && "Declaration with the given identifier "
- "should be specified in test!");
- DeclarationName ImportDeclName(ImportedII);
- SmallVector<NamedDecl *, 1> FoundDecls;
- FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
- FoundDecls);
-
- assert(FoundDecls.size() == 1);
-
- Decl *Imported =
- FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
-
- assert(Imported);
- return std::make_tuple(*FoundDecls.begin(), Imported);
- }
-
- // Creates a TU decl for the given source code which can be used as a From
- // context. May be called several times in a given test (with different file
- // name).
- TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
- StringRef FileName = "input.cc") {
- assert(llvm::find_if(FromTUs, [FileName](const TU &E) {
- return E.FileName == FileName;
- }) == FromTUs.end());
-
- ArgVector Args = getArgVectorForLanguage(Lang);
- FromTUs.emplace_back(SrcCode, FileName, Args);
- TU &Tu = FromTUs.back();
-
- return Tu.TUDecl;
- }
-
- // Creates the To context with the given source code and returns the TU decl.
- TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
- ArgVector ToArgs = getArgVectorForLanguage(ToLang);
- assert(!ToAST);
- lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
- return ToAST->getASTContext().getTranslationUnitDecl();
- }
-
- // Import the given Decl into the ToCtx.
- // May be called several times in a given test.
- // The different instances of the param From may have different ASTContext.
- Decl *Import(Decl *From, Language ToLang) {
- lazyInitToAST(ToLang, "", OutputFileName);
- TU *FromTU = findFromTU(From);
- assert(LookupTablePtr);
- return FromTU->import(*LookupTablePtr, ToAST.get(), From);
- }
-
- template <class DeclT> DeclT *Import(DeclT *From, Language Lang) {
- return cast_or_null<DeclT>(Import(cast<Decl>(From), Lang));
- }
-
- QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
- lazyInitToAST(ToLang, "", OutputFileName);
- TU *FromTU = findFromTU(TUDecl);
- assert(LookupTablePtr);
- return FromTU->import(*LookupTablePtr, ToAST.get(), FromType);
- }
-
- ~ASTImporterTestBase() {
- if (!::testing::Test::HasFailure()) return;
-
- for (auto &Tu : FromTUs) {
- assert(Tu.Unit);
- llvm::errs() << "FromAST:\n";
- Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
- llvm::errs() << "\n";
- }
- if (ToAST) {
- llvm::errs() << "ToAST:\n";
- ToAST->getASTContext().getTranslationUnitDecl()->dump();
- }
- }
-};
-
-class ASTImporterOptionSpecificTestBase
- : public ASTImporterTestBase,
- public ::testing::WithParamInterface<ArgVector> {
-protected:
- ArgVector getExtraArgs() const override { return GetParam(); }
-};
-
struct ImportExpr : TestImportBase {};
struct ImportType : TestImportBase {};
struct ImportDecl : TestImportBase {};
@@ -2451,206 +2158,6 @@ TEST_P(ImportFunctions,
EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
}
-//FIXME Move these tests to a separate test file.
-namespace TypeAndValueParameterizedTests {
-
-// Type parameters for type-parameterized test fixtures.
-struct GetFunPattern {
- using DeclTy = FunctionDecl;
- BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
-};
-struct GetVarPattern {
- using DeclTy = VarDecl;
- BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
-};
-
-// Values for the value-parameterized test fixtures.
-// FunctionDecl:
-auto *ExternF = "void f();";
-auto *StaticF = "static void f();";
-auto *AnonF = "namespace { void f(); }";
-// VarDecl:
-auto *ExternV = "extern int v;";
-auto *StaticV = "static int v;";
-auto *AnonV = "namespace { extern int v; }";
-
-// First value in tuple: Compile options.
-// Second value in tuple: Source code to be used in the test.
-using ImportVisibilityChainParams =
- ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
-// Fixture to test the redecl chain of Decls with the same visibility. Gtest
-// makes it possible to have either value-parameterized or type-parameterized
-// fixtures. However, we cannot have both value- and type-parameterized test
-// fixtures. This is a value-parameterized test fixture in the gtest sense. We
-// intend to mimic gtest's type-parameters via the PatternFactory template
-// parameter. We manually instantiate the different tests with the each types.
-template <typename PatternFactory>
-class ImportVisibilityChain
- : public ASTImporterTestBase, public ImportVisibilityChainParams {
-protected:
- using DeclTy = typename PatternFactory::DeclTy;
- ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
- std::string getCode() const { return std::get<1>(GetParam()); }
- BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
-
- // Type-parameterized test.
- void TypedTest_ImportChain() {
- std::string Code = getCode() + getCode();
- auto Pattern = getPattern();
-
- TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
-
- auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
- auto *FromF1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
-
- auto *ToF0 = Import(FromF0, Lang_CXX);
- auto *ToF1 = Import(FromF1, Lang_CXX);
-
- EXPECT_TRUE(ToF0);
- ASSERT_TRUE(ToF1);
- EXPECT_NE(ToF0, ToF1);
- EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
- }
-};
-
-// Manual instantiation of the fixture with each type.
-using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
-using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
-// Value-parameterized test for the first type.
-TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
- TypedTest_ImportChain();
-}
-// Value-parameterized test for the second type.
-TEST_P(ImportVariablesVisibilityChain, ImportChain) {
- TypedTest_ImportChain();
-}
-
-// Automatic instantiation of the value-parameterized tests.
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
- ::testing::Combine(
- DefaultTestValuesForRunOptions,
- ::testing::Values(ExternF, StaticF, AnonF)), );
-INSTANTIATE_TEST_CASE_P(
- ParameterizedTests, ImportVariablesVisibilityChain,
- ::testing::Combine(
- DefaultTestValuesForRunOptions,
- // There is no point to instantiate with StaticV, because in C++ we can
- // forward declare a variable only with the 'extern' keyword.
- // Consequently, each fwd declared variable has external linkage. This
- // is different in the C language where any declaration without an
- // initializer is a tentative definition, subsequent definitions may be
- // provided but they must have the same linkage. See also the test
- // ImportVariableChainInC which test for this special C Lang case.
- ::testing::Values(ExternV, AnonV)), );
-
-// First value in tuple: Compile options.
-// Second value in tuple: Tuple with informations for the test.
-// Code for first import (or initial code), code to import, whether the `f`
-// functions are expected to be linked in a declaration chain.
-// One value of this tuple is combined with every value of compile options.
-// The test can have a single tuple as parameter only.
-using ImportVisibilityParams = ::testing::WithParamInterface<
- std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
-
-template <typename PatternFactory>
-class ImportVisibility
- : public ASTImporterTestBase,
- public ImportVisibilityParams {
-protected:
- using DeclTy = typename PatternFactory::DeclTy;
- ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
- std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
- std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
- bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
- BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
-
- void TypedTest_ImportAfter() {
- TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
- TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
-
- auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
- auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
-
- auto *ToF1 = Import(FromF1, Lang_CXX);
-
- ASSERT_TRUE(ToF0);
- ASSERT_TRUE(ToF1);
- EXPECT_NE(ToF0, ToF1);
-
- if (shouldBeLinked())
- EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
- else
- EXPECT_FALSE(ToF1->getPreviousDecl());
- }
-
- void TypedTest_ImportAfterImport() {
- TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
- TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
- auto *FromF0 =
- FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
- auto *FromF1 =
- FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
- auto *ToF0 = Import(FromF0, Lang_CXX);
- auto *ToF1 = Import(FromF1, Lang_CXX);
- ASSERT_TRUE(ToF0);
- ASSERT_TRUE(ToF1);
- EXPECT_NE(ToF0, ToF1);
- if (shouldBeLinked())
- EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
- else
- EXPECT_FALSE(ToF1->getPreviousDecl());
- }
-};
-using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
-using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
-
-// FunctionDecl.
-TEST_P(ImportFunctionsVisibility, ImportAfter) {
- TypedTest_ImportAfter();
-}
-TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
- TypedTest_ImportAfterImport();
-}
-// VarDecl.
-TEST_P(ImportVariablesVisibility, ImportAfter) {
- TypedTest_ImportAfter();
-}
-TEST_P(ImportVariablesVisibility, ImportAfterImport) {
- TypedTest_ImportAfterImport();
-}
-
-bool ExpectLink = true;
-bool ExpectNotLink = false;
-
-INSTANTIATE_TEST_CASE_P(
- ParameterizedTests, ImportFunctionsVisibility,
- ::testing::Combine(
- DefaultTestValuesForRunOptions,
- ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
- std::make_tuple(ExternF, StaticF, ExpectNotLink),
- std::make_tuple(ExternF, AnonF, ExpectNotLink),
- std::make_tuple(StaticF, ExternF, ExpectNotLink),
- std::make_tuple(StaticF, StaticF, ExpectNotLink),
- std::make_tuple(StaticF, AnonF, ExpectNotLink),
- std::make_tuple(AnonF, ExternF, ExpectNotLink),
- std::make_tuple(AnonF, StaticF, ExpectNotLink),
- std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
-INSTANTIATE_TEST_CASE_P(
- ParameterizedTests, ImportVariablesVisibility,
- ::testing::Combine(
- DefaultTestValuesForRunOptions,
- ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
- std::make_tuple(ExternV, StaticV, ExpectNotLink),
- std::make_tuple(ExternV, AnonV, ExpectNotLink),
- std::make_tuple(StaticV, ExternV, ExpectNotLink),
- std::make_tuple(StaticV, StaticV, ExpectNotLink),
- std::make_tuple(StaticV, AnonV, ExpectNotLink),
- std::make_tuple(AnonV, ExternV, ExpectNotLink),
- std::make_tuple(AnonV, StaticV, ExpectNotLink),
- std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
-
-} // namespace TypeAndValueParameterizedTests
-
TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
std::string Code = "static int v; static int v = 0;";
auto Pattern = varDecl(hasName("v"));
@@ -3983,574 +3490,6 @@ TEST_P(ImportClasses, ImportNestedProtot
EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
}
-// FIXME put these structs and the tests rely on them into their own separate
-// test file!
-struct Function {
- using DeclTy = FunctionDecl;
- static constexpr auto *Prototype = "void X();";
- static constexpr auto *Definition = "void X() {}";
- BindableMatcher<Decl> getPattern() {
- return functionDecl(hasName("X"), unless(isImplicit()));
- }
-};
-
-struct Class {
- using DeclTy = CXXRecordDecl;
- static constexpr auto *Prototype = "class X;";
- static constexpr auto *Definition = "class X {};";
- BindableMatcher<Decl> getPattern() {
- return cxxRecordDecl(hasName("X"), unless(isImplicit()));
- }
-};
-
-struct Variable {
- using DeclTy = VarDecl;
- static constexpr auto *Prototype = "extern int X;";
- static constexpr auto *Definition = "int X;";
- BindableMatcher<Decl> getPattern() {
- return varDecl(hasName("X"));
- }
-};
-
-struct FunctionTemplate {
- using DeclTy = FunctionTemplateDecl;
- static constexpr auto *Prototype = "template <class T> void X();";
- static constexpr auto *Definition =
- R"(
- template <class T> void X() {};
- // Explicit instantiation is a must because of -fdelayed-template-parsing:
- template void X<int>();
- )";
- BindableMatcher<Decl> getPattern() {
- return functionTemplateDecl(hasName("X"), unless(isImplicit()));
- }
-};
-
-struct ClassTemplate {
- using DeclTy = ClassTemplateDecl;
- static constexpr auto *Prototype = "template <class T> class X;";
- static constexpr auto *Definition = "template <class T> class X {};";
- BindableMatcher<Decl> getPattern() {
- return classTemplateDecl(hasName("X"), unless(isImplicit()));
- }
-};
-
-struct FunctionTemplateSpec {
- using DeclTy = FunctionDecl;
- static constexpr auto *Prototype =
- R"(
- // Proto of the primary template.
- template <class T>
- void X();
- // Proto of the specialization.
- template <>
- void X<int>();
- )";
- static constexpr auto *Definition =
- R"(
- // Proto of the primary template.
- template <class T>
- void X();
- // Specialization and definition.
- template <>
- void X<int>() {}
- )";
- BindableMatcher<Decl> getPattern() {
- return functionDecl(hasName("X"), isExplicitTemplateSpecialization());
- }
-};
-
-struct ClassTemplateSpec {
- using DeclTy = ClassTemplateSpecializationDecl;
- static constexpr auto *Prototype =
- R"(
- template <class T> class X;
- template <> class X<int>;
- )";
- static constexpr auto *Definition =
- R"(
- template <class T> class X;
- template <> class X<int> {};
- )";
- BindableMatcher<Decl> getPattern() {
- return classTemplateSpecializationDecl(hasName("X"), unless(isImplicit()));
- }
-};
-
-template <typename TypeParam>
-struct RedeclChain : ASTImporterOptionSpecificTestBase {
-
- using DeclTy = typename TypeParam::DeclTy;
- std::string getPrototype() { return TypeParam::Prototype; }
- std::string getDefinition() { return TypeParam::Definition; }
- BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); }
-
- void CheckPreviousDecl(Decl *Prev, Decl *Current) {
- ASSERT_NE(Prev, Current);
- ASSERT_EQ(&Prev->getASTContext(), &Current->getASTContext());
- EXPECT_EQ(Prev->getCanonicalDecl(), Current->getCanonicalDecl());
-
- // Templates.
- if (auto *PrevT = dyn_cast<TemplateDecl>(Prev)) {
- EXPECT_EQ(Current->getPreviousDecl(), Prev);
- auto *CurrentT = cast<TemplateDecl>(Current);
- ASSERT_TRUE(PrevT->getTemplatedDecl());
- ASSERT_TRUE(CurrentT->getTemplatedDecl());
- EXPECT_EQ(CurrentT->getTemplatedDecl()->getPreviousDecl(),
- PrevT->getTemplatedDecl());
- return;
- }
-
- // Specializations.
- if (auto *PrevF = dyn_cast<FunctionDecl>(Prev)) {
- if (PrevF->getTemplatedKind() ==
- FunctionDecl::TK_FunctionTemplateSpecialization) {
- // There may be a hidden fwd spec decl before a spec decl.
- // In that case the previous visible decl can be reached through that
- // invisible one.
- EXPECT_THAT(Prev, testing::AnyOf(
- Current->getPreviousDecl(),
- Current->getPreviousDecl()->getPreviousDecl()));
- auto *ToTU = Prev->getTranslationUnitDecl();
- auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
- ToTU, functionTemplateDecl());
- auto *FirstSpecD = *(TemplateD->spec_begin());
- EXPECT_EQ(FirstSpecD->getCanonicalDecl(), PrevF->getCanonicalDecl());
- return;
- }
- }
-
- // The rest: Classes, Functions, etc.
- EXPECT_EQ(Current->getPreviousDecl(), Prev);
- }
-
- void
- TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() {
- Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX);
- auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
- ASSERT_FALSE(FromD->isThisDeclarationADefinition());
-
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
- auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(ImportedD == ToD);
- EXPECT_FALSE(ToD->isThisDeclarationADefinition());
- if (auto *ToT = dyn_cast<TemplateDecl>(ToD)) {
- EXPECT_TRUE(ToT->getTemplatedDecl());
- }
- }
-
- void TypedTest_DefinitionShouldBeImportedAsADefinition() {
- Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
- auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
- ASSERT_TRUE(FromD->isThisDeclarationADefinition());
-
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
- auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(ToD->isThisDeclarationADefinition());
- if (auto *ToT = dyn_cast<TemplateDecl>(ToD)) {
- EXPECT_TRUE(ToT->getTemplatedDecl());
- }
- }
-
- void TypedTest_ImportPrototypeAfterImportedPrototype() {
- Decl *FromTU = getTuDecl(
- getPrototype() + getPrototype(), Lang_CXX);
- auto *From0 =
- FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
- auto *From1 = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
- ASSERT_FALSE(From0->isThisDeclarationADefinition());
- ASSERT_FALSE(From1->isThisDeclarationADefinition());
-
- Decl *Imported0 = Import(From0, Lang_CXX);
- Decl *Imported1 = Import(From1, Lang_CXX);
- Decl *ToTU = Imported0->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
- auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
- auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(Imported0 == To0);
- EXPECT_TRUE(Imported1 == To1);
- EXPECT_FALSE(To0->isThisDeclarationADefinition());
- EXPECT_FALSE(To1->isThisDeclarationADefinition());
-
- CheckPreviousDecl(To0, To1);
- }
-
- void TypedTest_ImportDefinitionAfterImportedPrototype() {
- Decl *FromTU = getTuDecl(
- getPrototype() + getDefinition(), Lang_CXX);
- auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
- auto *FromDef = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
- ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
- ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
-
- Decl *ImportedProto = Import(FromProto, Lang_CXX);
- Decl *ImportedDef = Import(FromDef, Lang_CXX);
- Decl *ToTU = ImportedProto->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
- auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
- auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(ImportedProto == ToProto);
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
-
- CheckPreviousDecl(ToProto, ToDef);
- }
-
- void TypedTest_ImportPrototypeAfterImportedDefinition() {
- Decl *FromTU = getTuDecl(
- getDefinition() + getPrototype(), Lang_CXX);
- auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
- auto *FromProto = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
- ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
- ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
-
- Decl *ImportedDef = Import(FromDef, Lang_CXX);
- Decl *ImportedProto = Import(FromProto, Lang_CXX);
- Decl *ToTU = ImportedDef->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
- auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
- auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ImportedProto == ToProto);
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
-
- CheckPreviousDecl(ToDef, ToProto);
- }
-
- void TypedTest_ImportPrototypes() {
- Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
- Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
- auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
- auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
- ASSERT_FALSE(From0->isThisDeclarationADefinition());
- ASSERT_FALSE(From1->isThisDeclarationADefinition());
-
- Decl *Imported0 = Import(From0, Lang_CXX);
- Decl *Imported1 = Import(From1, Lang_CXX);
- Decl *ToTU = Imported0->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
- auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
- auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(Imported0 == To0);
- EXPECT_TRUE(Imported1 == To1);
- EXPECT_FALSE(To0->isThisDeclarationADefinition());
- EXPECT_FALSE(To1->isThisDeclarationADefinition());
-
- CheckPreviousDecl(To0, To1);
- }
-
- void TypedTest_ImportDefinitions() {
- Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
- Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
- auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
- auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
- ASSERT_TRUE(From0->isThisDeclarationADefinition());
- ASSERT_TRUE(From1->isThisDeclarationADefinition());
-
- Decl *Imported0 = Import(From0, Lang_CXX);
- Decl *Imported1 = Import(From1, Lang_CXX);
- Decl *ToTU = Imported0->getTranslationUnitDecl();
-
- EXPECT_EQ(Imported0, Imported1);
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
- auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(Imported0 == To0);
- EXPECT_TRUE(To0->isThisDeclarationADefinition());
- if (auto *ToT0 = dyn_cast<TemplateDecl>(To0)) {
- EXPECT_TRUE(ToT0->getTemplatedDecl());
- }
- }
-
- void TypedTest_ImportDefinitionThenPrototype() {
- Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
- Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
- auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
- auto *FromProto =
- FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
- ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
- ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
-
- Decl *ImportedDef = Import(FromDef, Lang_CXX);
- Decl *ImportedProto = Import(FromProto, Lang_CXX);
- Decl *ToTU = ImportedDef->getTranslationUnitDecl();
-
- EXPECT_NE(ImportedDef, ImportedProto);
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
- auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
- auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ImportedProto == ToProto);
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
-
- CheckPreviousDecl(ToDef, ToProto);
- }
-
- void TypedTest_ImportPrototypeThenDefinition() {
- Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
- Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
- auto *FromProto =
- FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
- auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
- ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
- ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
-
- Decl *ImportedProto = Import(FromProto, Lang_CXX);
- Decl *ImportedDef = Import(FromDef, Lang_CXX);
- Decl *ToTU = ImportedDef->getTranslationUnitDecl();
-
- EXPECT_NE(ImportedDef, ImportedProto);
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
- auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
- auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ImportedProto == ToProto);
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
-
- CheckPreviousDecl(ToProto, ToDef);
- }
-
- void TypedTest_WholeRedeclChainIsImportedAtOnce() {
- Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
- auto *FromD = // Definition
- LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
- ASSERT_TRUE(FromD->isThisDeclarationADefinition());
-
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- // The whole redecl chain is imported at once.
- EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
- EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition());
- }
-
- void TypedTest_ImportPrototypeThenProtoAndDefinition() {
- {
- Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
- Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU =
- getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
- Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-
- ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u);
- DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_FALSE(ProtoD->isThisDeclarationADefinition());
-
- DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
- EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition());
-
- EXPECT_TRUE(DefinitionD->getPreviousDecl());
- EXPECT_FALSE(
- DefinitionD->getPreviousDecl()->isThisDeclarationADefinition());
-
- CheckPreviousDecl(ProtoD, DefinitionD->getPreviousDecl());
- }
-};
-
-#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \
- NamePrefix, TestCase) \
- using BaseTemplate##TypeParam = BaseTemplate<TypeParam>; \
- TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \
- TypedTest_##TestCase(); \
- }
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, Function, ,
- PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, Class, ,
- PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, Variable, ,
- PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, FunctionTemplate, ,
- PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, ClassTemplate, ,
- PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, FunctionTemplateSpec, ,
- PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, ClassTemplateSpec, ,
- PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, FunctionTemplate, ,
- DefinitionShouldBeImportedAsADefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, FunctionTemplateSpec, ,
- DefinitionShouldBeImportedAsADefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, ClassTemplateSpec, , DefinitionShouldBeImportedAsADefinition)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
- ImportPrototypeAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
- ImportPrototypeAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
- ImportPrototypeAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
- ImportPrototypeAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
- ImportPrototypeAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
- ImportPrototypeAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
- ImportPrototypeAfterImportedPrototype)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
- ImportDefinitionAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
- ImportDefinitionAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
- ImportDefinitionAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
- ImportDefinitionAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
- ImportDefinitionAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
- ImportDefinitionAfterImportedPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
- ImportDefinitionAfterImportedPrototype)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
- ImportPrototypeAfterImportedDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
- ImportPrototypeAfterImportedDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
- ImportPrototypeAfterImportedDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
- ImportPrototypeAfterImportedDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
- ImportPrototypeAfterImportedDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
- ImportPrototypeAfterImportedDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
- ImportPrototypeAfterImportedDefinition)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
- ImportPrototypes)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
- ImportPrototypes)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
- ImportPrototypes)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
- ImportPrototypes)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
- ImportPrototypes)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
- ImportPrototypes)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
- ImportDefinitions)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
- ImportDefinitions)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
- ImportDefinitions)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
- ImportDefinitions)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
- ImportDefinitions)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
- ImportDefinitions)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
- ImportDefinitions)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
- ImportDefinitionThenPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
- ImportDefinitionThenPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
- ImportDefinitionThenPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
- ImportDefinitionThenPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
- ImportDefinitionThenPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
- ImportDefinitionThenPrototype)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
- ImportDefinitionThenPrototype)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
- ImportPrototypeThenDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
- ImportPrototypeThenDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
- ImportPrototypeThenDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
- ImportPrototypeThenDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
- ImportPrototypeThenDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
- ImportPrototypeThenDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
- ImportPrototypeThenDefinition)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
- WholeRedeclChainIsImportedAtOnce)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
- WholeRedeclChainIsImportedAtOnce)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
- WholeRedeclChainIsImportedAtOnce)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
- WholeRedeclChainIsImportedAtOnce)
-
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
- ImportPrototypeThenProtoAndDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
- ImportPrototypeThenProtoAndDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
- ImportPrototypeThenProtoAndDefinition)
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
- ImportPrototypeThenProtoAndDefinition)
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction,
- DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass,
- DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable,
- DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
- DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
- DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
- DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplateSpec,
- DefaultTestValuesForRunOptions, );
-
-
struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Added: cfe/trunk/unittests/AST/ASTImporterVisibilityTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterVisibilityTest.cpp?rev=360572&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterVisibilityTest.cpp (added)
+++ cfe/trunk/unittests/AST/ASTImporterVisibilityTest.cpp Mon May 13 03:06:25 2019
@@ -0,0 +1,219 @@
+//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Type-parameterized tests for the correct import of Decls with different
+// visibility.
+//
+//===----------------------------------------------------------------------===//
+
+// Define this to have ::testing::Combine available.
+// FIXME: Better solution for this?
+#define GTEST_HAS_COMBINE 1
+
+#include "ASTImporterFixtures.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using internal::BindableMatcher;
+
+// Type parameters for type-parameterized test fixtures.
+struct GetFunPattern {
+ using DeclTy = FunctionDecl;
+ BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
+};
+struct GetVarPattern {
+ using DeclTy = VarDecl;
+ BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
+};
+
+// Values for the value-parameterized test fixtures.
+// FunctionDecl:
+const auto *ExternF = "void f();";
+const auto *StaticF = "static void f();";
+const auto *AnonF = "namespace { void f(); }";
+// VarDecl:
+const auto *ExternV = "extern int v;";
+const auto *StaticV = "static int v;";
+const auto *AnonV = "namespace { extern int v; }";
+
+// First value in tuple: Compile options.
+// Second value in tuple: Source code to be used in the test.
+using ImportVisibilityChainParams =
+ ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
+// Fixture to test the redecl chain of Decls with the same visibility. Gtest
+// makes it possible to have either value-parameterized or type-parameterized
+// fixtures. However, we cannot have both value- and type-parameterized test
+// fixtures. This is a value-parameterized test fixture in the gtest sense. We
+// intend to mimic gtest's type-parameters via the PatternFactory template
+// parameter. We manually instantiate the different tests with the each types.
+template <typename PatternFactory>
+class ImportVisibilityChain
+ : public ASTImporterTestBase, public ImportVisibilityChainParams {
+protected:
+ using DeclTy = typename PatternFactory::DeclTy;
+ ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
+ std::string getCode() const { return std::get<1>(GetParam()); }
+ BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
+
+ // Type-parameterized test.
+ void TypedTest_ImportChain() {
+ std::string Code = getCode() + getCode();
+ auto Pattern = getPattern();
+
+ TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
+
+ auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
+ auto *FromD1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
+
+ auto *ToD0 = Import(FromD0, Lang_CXX);
+ auto *ToD1 = Import(FromD1, Lang_CXX);
+
+ EXPECT_TRUE(ToD0);
+ ASSERT_TRUE(ToD1);
+ EXPECT_NE(ToD0, ToD1);
+ EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
+ }
+};
+
+// Manual instantiation of the fixture with each type.
+using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
+using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
+// Value-parameterized test for the first type.
+TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
+ TypedTest_ImportChain();
+}
+// Value-parameterized test for the second type.
+TEST_P(ImportVariablesVisibilityChain, ImportChain) {
+ TypedTest_ImportChain();
+}
+
+// Automatic instantiation of the value-parameterized tests.
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
+ ::testing::Combine(
+ DefaultTestValuesForRunOptions,
+ ::testing::Values(ExternF, StaticF, AnonF)), );
+INSTANTIATE_TEST_CASE_P(
+ ParameterizedTests, ImportVariablesVisibilityChain,
+ ::testing::Combine(
+ DefaultTestValuesForRunOptions,
+ // There is no point to instantiate with StaticV, because in C++ we can
+ // forward declare a variable only with the 'extern' keyword.
+ // Consequently, each fwd declared variable has external linkage. This
+ // is different in the C language where any declaration without an
+ // initializer is a tentative definition, subsequent definitions may be
+ // provided but they must have the same linkage. See also the test
+ // ImportVariableChainInC which test for this special C Lang case.
+ ::testing::Values(ExternV, AnonV)), );
+
+// First value in tuple: Compile options.
+// Second value in tuple: Tuple with informations for the test.
+// Code for first import (or initial code), code to import, whether the `f`
+// functions are expected to be linked in a declaration chain.
+// One value of this tuple is combined with every value of compile options.
+// The test can have a single tuple as parameter only.
+using ImportVisibilityParams = ::testing::WithParamInterface<
+ std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
+
+template <typename PatternFactory>
+class ImportVisibility
+ : public ASTImporterTestBase,
+ public ImportVisibilityParams {
+protected:
+ using DeclTy = typename PatternFactory::DeclTy;
+ ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
+ std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
+ std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
+ bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
+ BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
+
+ void TypedTest_ImportAfter() {
+ TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
+ TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
+
+ auto *ToD0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
+ auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
+
+ auto *ToD1 = Import(FromD1, Lang_CXX);
+
+ ASSERT_TRUE(ToD0);
+ ASSERT_TRUE(ToD1);
+ EXPECT_NE(ToD0, ToD1);
+
+ if (shouldBeLinked())
+ EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
+ else
+ EXPECT_FALSE(ToD1->getPreviousDecl());
+ }
+
+ void TypedTest_ImportAfterImport() {
+ TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
+ TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
+ auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
+ auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
+ auto *ToD0 = Import(FromD0, Lang_CXX);
+ auto *ToD1 = Import(FromD1, Lang_CXX);
+ ASSERT_TRUE(ToD0);
+ ASSERT_TRUE(ToD1);
+ EXPECT_NE(ToD0, ToD1);
+ if (shouldBeLinked())
+ EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
+ else
+ EXPECT_FALSE(ToD1->getPreviousDecl());
+ }
+};
+using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
+using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
+
+// FunctionDecl.
+TEST_P(ImportFunctionsVisibility, ImportAfter) {
+ TypedTest_ImportAfter();
+}
+TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
+ TypedTest_ImportAfterImport();
+}
+// VarDecl.
+TEST_P(ImportVariablesVisibility, ImportAfter) {
+ TypedTest_ImportAfter();
+}
+TEST_P(ImportVariablesVisibility, ImportAfterImport) {
+ TypedTest_ImportAfterImport();
+}
+
+const bool ExpectLink = true;
+const bool ExpectNotLink = false;
+
+INSTANTIATE_TEST_CASE_P(
+ ParameterizedTests, ImportFunctionsVisibility,
+ ::testing::Combine(
+ DefaultTestValuesForRunOptions,
+ ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
+ std::make_tuple(ExternF, StaticF, ExpectNotLink),
+ std::make_tuple(ExternF, AnonF, ExpectNotLink),
+ std::make_tuple(StaticF, ExternF, ExpectNotLink),
+ std::make_tuple(StaticF, StaticF, ExpectNotLink),
+ std::make_tuple(StaticF, AnonF, ExpectNotLink),
+ std::make_tuple(AnonF, ExternF, ExpectNotLink),
+ std::make_tuple(AnonF, StaticF, ExpectNotLink),
+ std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
+INSTANTIATE_TEST_CASE_P(
+ ParameterizedTests, ImportVariablesVisibility,
+ ::testing::Combine(
+ DefaultTestValuesForRunOptions,
+ ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
+ std::make_tuple(ExternV, StaticV, ExpectNotLink),
+ std::make_tuple(ExternV, AnonV, ExpectNotLink),
+ std::make_tuple(StaticV, ExternV, ExpectNotLink),
+ std::make_tuple(StaticV, StaticV, ExpectNotLink),
+ std::make_tuple(StaticV, AnonV, ExpectNotLink),
+ std::make_tuple(AnonV, ExternV, ExpectNotLink),
+ std::make_tuple(AnonV, StaticV, ExpectNotLink),
+ std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
+
+} // end namespace ast_matchers
+} // end namespace clang
Modified: cfe/trunk/unittests/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/CMakeLists.txt?rev=360572&r1=360571&r2=360572&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/CMakeLists.txt (original)
+++ cfe/trunk/unittests/AST/CMakeLists.txt Mon May 13 03:06:25 2019
@@ -8,7 +8,10 @@ endif()
add_clang_unittest(ASTTests
ASTContextParentMapTest.cpp
+ ASTImporterFixtures.cpp
ASTImporterTest.cpp
+ ASTImporterGenericRedeclTest.cpp
+ ASTImporterVisibilityTest.cpp
ASTTypeTraitsTest.cpp
ASTVectorTest.cpp
CommentLexer.cpp
More information about the cfe-commits
mailing list