summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/unittests/AST/ASTImporterTest.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
commitb64793999546ed8adebaeebd9d8345d18db8927d (patch)
tree4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/clang/unittests/AST/ASTImporterTest.cpp
parentAdd support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff)
downloadwireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz
wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/clang/unittests/AST/ASTImporterTest.cpp')
-rw-r--r--gnu/llvm/tools/clang/unittests/AST/ASTImporterTest.cpp4916
1 files changed, 0 insertions, 4916 deletions
diff --git a/gnu/llvm/tools/clang/unittests/AST/ASTImporterTest.cpp b/gnu/llvm/tools/clang/unittests/AST/ASTImporterTest.cpp
deleted file mode 100644
index c6acf573e58..00000000000
--- a/gnu/llvm/tools/clang/unittests/AST/ASTImporterTest.cpp
+++ /dev/null
@@ -1,4916 +0,0 @@
-//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Tests for the correct import of AST nodes from one AST context to another.
-//
-//===----------------------------------------------------------------------===//
-
-#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"
-
-namespace clang {
-namespace ast_matchers {
-
-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().get());
- 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.
-struct ParameterizedTestsFixture : ::testing::TestWithParam<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 = GetParam();
- for (const auto &Arg : ExtraArgs) {
- Args.push_back(Arg);
- }
- return Args;
- }
-
-};
-
-// Base class for those tests which use the family of `testImport` functions.
-class TestImportBase : public ParameterizedTestsFixture {
-
- template <typename NodeType>
- NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
- NodeType Node) {
- ASTContext &ToCtx = To->getASTContext();
-
- // Add 'From' file to virtual file system so importer can 'find' it
- // while importing SourceLocations. It is safe to add same file multiple
- // times - it just isn't replaced.
- StringRef FromFileName = From->getMainFileName();
- createVirtualFileIfNeeded(To, FromFileName,
- From->getBufferForFile(FromFileName));
-
- auto Imported = Importer.Import(Node);
-
- // This should dump source locations and assert if some source locations
- // were not imported.
- SmallString<1024> ImportChecker;
- llvm::raw_svector_ostream ToNothing(ImportChecker);
- ToCtx.getTranslationUnitDecl()->print(ToNothing);
-
- // This traverses the AST to catch certain bugs like poorly or not
- // implemented subtrees.
- Imported->dump(ToNothing);
-
- return Imported;
- }
-
- template <typename NodeType>
- testing::AssertionResult
- testImport(const std::string &FromCode, const ArgVector &FromArgs,
- const std::string &ToCode, const ArgVector &ToArgs,
- MatchVerifier<NodeType> &Verifier,
- const BindableMatcher<NodeType> &SearchMatcher,
- const BindableMatcher<NodeType> &VerificationMatcher) {
- const char *const InputFileName = "input.cc";
- const char *const OutputFileName = "output.cc";
-
- std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
- FromCode, FromArgs, InputFileName),
- ToAST = tooling::buildASTFromCodeWithArgs(
- ToCode, ToArgs, OutputFileName);
-
- ASTContext &FromCtx = FromAST->getASTContext(),
- &ToCtx = ToAST->getASTContext();
-
- ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
- FromAST->getFileManager(), false);
-
- auto FoundNodes = match(SearchMatcher, FromCtx);
- if (FoundNodes.size() != 1)
- return testing::AssertionFailure()
- << "Multiple potential nodes were found!";
-
- auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
- if (!ToImport)
- return testing::AssertionFailure() << "Node type mismatch!";
-
- // Sanity check: the node being imported should match in the same way as
- // the result node.
- BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
- EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
-
- auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
- if (!Imported)
- return testing::AssertionFailure() << "Import failed, nullptr returned!";
-
-
- return Verifier.match(Imported, WrapperMatcher);
- }
-
- template <typename NodeType>
- testing::AssertionResult
- testImport(const std::string &FromCode, const ArgVector &FromArgs,
- const std::string &ToCode, const ArgVector &ToArgs,
- MatchVerifier<NodeType> &Verifier,
- const BindableMatcher<NodeType> &VerificationMatcher) {
- return testImport(
- FromCode, FromArgs, ToCode, ToArgs, Verifier,
- translationUnitDecl(
- has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
- VerificationMatcher);
- }
-
-public:
-
- /// Test how AST node named "declToImport" located in the translation unit
- /// of "FromCode" virtual file is imported to "ToCode" virtual file.
- /// The verification is done by running AMatcher over the imported node.
- template <typename NodeType, typename MatcherType>
- void testImport(const std::string &FromCode, Language FromLang,
- const std::string &ToCode, Language ToLang,
- MatchVerifier<NodeType> &Verifier,
- const MatcherType &AMatcher) {
- ArgVector FromArgs = getArgVectorForLanguage(FromLang),
- ToArgs = getArgVectorForLanguage(ToLang);
- EXPECT_TRUE(
- testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
- }
-
- struct ImportAction {
- StringRef FromFilename;
- StringRef ToFilename;
- // FIXME: Generalize this to support other node kinds.
- BindableMatcher<Decl> ImportPredicate;
-
- ImportAction(StringRef FromFilename, StringRef ToFilename,
- DeclarationMatcher ImportPredicate)
- : FromFilename(FromFilename), ToFilename(ToFilename),
- ImportPredicate(ImportPredicate) {}
-
- ImportAction(StringRef FromFilename, StringRef ToFilename,
- const std::string &DeclName)
- : FromFilename(FromFilename), ToFilename(ToFilename),
- ImportPredicate(namedDecl(hasName(DeclName))) {}
- };
-
- using SingleASTUnit = std::unique_ptr<ASTUnit>;
- using AllASTUnits = StringMap<SingleASTUnit>;
-
- struct CodeEntry {
- std::string CodeSample;
- Language Lang;
- };
-
- using CodeFiles = StringMap<CodeEntry>;
-
- /// Builds an ASTUnit for one potential compile options set.
- SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
- ArgVector Args = getArgVectorForLanguage(CE.Lang);
- auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
- EXPECT_TRUE(AST.get());
- return AST;
- }
-
- /// Test an arbitrary sequence of imports for a set of given in-memory files.
- /// The verification is done by running VerificationMatcher against a
- /// specified AST node inside of one of given files.
- /// \param CodeSamples Map whose key is the file name and the value is the
- /// file content.
- /// \param ImportActions Sequence of imports. Each import in sequence
- /// specifies "from file" and "to file" and a matcher that is used for
- /// searching a declaration for import in "from file".
- /// \param FileForFinalCheck Name of virtual file for which the final check is
- /// applied.
- /// \param FinalSelectPredicate Matcher that specifies the AST node in the
- /// FileForFinalCheck for which the verification will be done.
- /// \param VerificationMatcher Matcher that will be used for verification
- /// after all imports in sequence are done.
- void testImportSequence(const CodeFiles &CodeSamples,
- const std::vector<ImportAction> &ImportActions,
- StringRef FileForFinalCheck,
- BindableMatcher<Decl> FinalSelectPredicate,
- BindableMatcher<Decl> VerificationMatcher) {
- AllASTUnits AllASTs;
- using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
- llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
-
- auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
- if (!AllASTs.count(Filename)) {
- auto Found = CodeSamples.find(Filename);
- assert(Found != CodeSamples.end() && "Wrong file for import!");
- AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
- }
- };
-
- for (const ImportAction &Action : ImportActions) {
- StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
- GenASTsIfNeeded(FromFile);
- GenASTsIfNeeded(ToFile);
-
- ASTUnit *From = AllASTs[FromFile].get();
- ASTUnit *To = AllASTs[ToFile].get();
-
- // Create a new importer if needed.
- std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
- if (!ImporterRef)
- ImporterRef.reset(new ASTImporter(
- To->getASTContext(), To->getFileManager(), From->getASTContext(),
- From->getFileManager(), false));
-
- // Find the declaration and import it.
- auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
- From->getASTContext());
- EXPECT_TRUE(FoundDecl.size() == 1);
- const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
- auto Imported = importNode(From, To, *ImporterRef, ToImport);
- EXPECT_TRUE(Imported);
- }
-
- // Find the declaration and import it.
- auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
- AllASTs[FileForFinalCheck]->getASTContext());
- EXPECT_TRUE(FoundDecl.size() == 1);
- const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
- MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
- }
-};
-
-template <typename T> RecordDecl *getRecordDecl(T *D) {
- auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
- 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 ParameterizedTestsFixture {
-
- const char *const InputFileName = "input.cc";
- const char *const OutputFileName = "output.cc";
-
- // 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;
- TU(StringRef Code, StringRef FileName, ArgVector Args)
- : Code(Code), FileName(FileName),
- Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
- this->FileName)),
- TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
- Unit->enableSourceFileDiagnostics();
- }
-
- void lazyInitImporter(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST) {
- assert(ToAST);
- if (!Importer) {
- Importer.reset(
- new ASTImporter(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);
- return Importer->Import(FromDecl);
- }
-
- QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
- QualType FromType) {
- lazyInitImporter(LookupTable, ToAST);
- return Importer->Import(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) {
- 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 = std::find_if(FromTUs.begin(), FromTUs.end(), [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);
- 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(
- std::find_if(FromTUs.begin(), FromTUs.end(), [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);
- }
-
- 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();
- }
- }
-};
-
-struct ImportExpr : TestImportBase {};
-struct ImportType : TestImportBase {};
-struct ImportDecl : TestImportBase {};
-
-struct CanonicalRedeclChain : ASTImporterTestBase {};
-
-TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- auto Redecls = getCanonicalForwardRedeclChain(D0);
- ASSERT_EQ(Redecls.size(), 1u);
- EXPECT_EQ(D0, Redecls[0]);
-}
-
-TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
- Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- FunctionDecl *D1 = D2->getPreviousDecl();
-
- auto Redecls = getCanonicalForwardRedeclChain(D0);
- ASSERT_EQ(Redecls.size(), 3u);
- EXPECT_EQ(D0, Redecls[0]);
- EXPECT_EQ(D1, Redecls[1]);
- EXPECT_EQ(D2, Redecls[2]);
-}
-
-TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
- Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- FunctionDecl *D1 = D2->getPreviousDecl();
-
- auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
- auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
- auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
-
- EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
- EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
-}
-
-TEST_P(ImportExpr, ImportStringLiteral) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)\"foo\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- stringLiteral(hasType(asString("const char [4]"))))));
- testImport(
- "void declToImport() { (void)L\"foo\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- stringLiteral(hasType(asString("const wchar_t [4]"))))));
- testImport(
- "void declToImport() { (void) \"foo\" \"bar\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- stringLiteral(hasType(asString("const char [7]"))))));
-}
-
-TEST_P(ImportExpr, ImportGNUNullExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)__null; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
-}
-
-TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)nullptr; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
-}
-
-
-TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)1.0; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- floatLiteral(equals(1.0), hasType(asString("double"))))));
- testImport(
- "void declToImport() { (void)1.0e-5f; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
-}
-
-TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)1.0i; }",
- Lang_CXX14, "", Lang_CXX14, Verifier,
- functionDecl(hasDescendant(imaginaryLiteral())));
-}
-
-TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() {"
- " struct s { int x; long y; unsigned z; }; "
- " (void)(struct s){ 42, 0L, 1U }; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- compoundLiteralExpr(
- hasType(asString("struct s")),
- has(initListExpr(
- hasType(asString("struct s")),
- has(integerLiteral(
- equals(42), hasType(asString("int")))),
- has(integerLiteral(
- equals(0), hasType(asString("long")))),
- has(integerLiteral(
- equals(1), hasType(asString("unsigned int"))))))))));
-}
-
-TEST_P(ImportExpr, ImportCXXThisExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "class declToImport { void f() { (void)this; } };",
- Lang_CXX, "", Lang_CXX, Verifier,
- cxxRecordDecl(
- hasMethod(
- hasDescendant(
- cxxThisExpr(
- hasType(
- asString("class declToImport *")))))));
-}
-
-TEST_P(ImportExpr, ImportAtomicExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- atomicExpr(
- has(ignoringParenImpCasts(
- declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
- hasType(asString("int *"))))),
- has(integerLiteral(equals(1), hasType(asString("int"))))))));
-}
-
-TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { loop: goto loop; (void)&&loop; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(
- hasDescendant(
- labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
- hasDescendant(
- addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
-}
-
-AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
- internal::Matcher<NamedDecl>, InnerMatcher) {
- const NamedDecl *Template = Node.getTemplatedDecl();
- return Template && InnerMatcher.matches(*Template, Finder, Builder);
-}
-
-TEST_P(ImportExpr, ImportParenListExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T> class dummy { void f() { dummy X(*this); } };"
- "typedef dummy<int> declToImport;"
- "template class dummy<int>;",
- Lang_CXX, "", Lang_CXX, Verifier,
- typedefDecl(hasType(templateSpecializationType(
- hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
- classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
- hasName("f"),
- hasBody(compoundStmt(has(declStmt(hasSingleDecl(
- varDecl(hasInitializer(parenListExpr(has(unaryOperator(
- hasOperatorName("*"),
- hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
-}
-
-TEST_P(ImportExpr, ImportSwitch) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { int b; switch (b) { case 1: break; } }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- switchStmt(has(compoundStmt(has(caseStmt())))))));
-}
-
-TEST_P(ImportExpr, ImportStmtExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- varDecl(
- hasName("C"),
- hasType(asString("int")),
- hasInitializer(
- stmtExpr(
- hasAnySubstatement(declStmt(hasSingleDecl(
- varDecl(
- hasName("X"),
- hasType(asString("int")),
- hasInitializer(
- integerLiteral(equals(4))))))),
- hasDescendant(
- implicitCastExpr())))))));
-}
-
-TEST_P(ImportExpr, ImportConditionalOperator) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)(true ? 1 : -5); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- conditionalOperator(
- hasCondition(cxxBoolLiteral(equals(true))),
- hasTrueExpression(integerLiteral(equals(1))),
- hasFalseExpression(
- unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
- )));
-}
-
-TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)(1 ?: -5); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- binaryConditionalOperator(
- hasCondition(
- implicitCastExpr(
- hasSourceExpression(opaqueValueExpr(
- hasSourceExpression(integerLiteral(equals(1))))),
- hasType(booleanType()))),
- hasTrueExpression(
- opaqueValueExpr(
- hasSourceExpression(integerLiteral(equals(1))))),
- hasFalseExpression(
- unaryOperator(
- hasOperatorName("-"),
- hasUnaryOperand(integerLiteral(equals(5)))))))));
-}
-
-TEST_P(ImportExpr, ImportDesignatedInitExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() {"
- " struct point { double x; double y; };"
- " struct point ptarray[10] = "
- "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- initListExpr(
- has(designatedInitExpr(
- designatorCountIs(2),
- hasDescendant(floatLiteral(equals(1.0))),
- hasDescendant(integerLiteral(equals(2))))),
- has(designatedInitExpr(
- designatorCountIs(2),
- hasDescendant(floatLiteral(equals(2.0))),
- hasDescendant(integerLiteral(equals(2))))),
- has(designatedInitExpr(
- designatorCountIs(2),
- hasDescendant(floatLiteral(equals(1.0))),
- hasDescendant(integerLiteral(equals(0)))))))));
-}
-
-TEST_P(ImportExpr, ImportPredefinedExpr) {
- MatchVerifier<Decl> Verifier;
- // __func__ expands as StringLiteral("declToImport")
- testImport(
- "void declToImport() { (void)__func__; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- predefinedExpr(
- hasType(
- asString("const char [13]")),
- has(stringLiteral(hasType(
- asString("const char [13]"))))))));
-}
-
-TEST_P(ImportExpr, ImportInitListExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() {"
- " struct point { double x; double y; };"
- " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
- " [0].x = 1.0 }; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- initListExpr(
- has(
- cxxConstructExpr(
- requiresZeroInitialization())),
- has(
- initListExpr(
- hasType(asString("struct point")),
- has(floatLiteral(equals(1.0))),
- has(implicitValueInitExpr(
- hasType(asString("double")))))),
- has(
- initListExpr(
- hasType(asString("struct point")),
- has(floatLiteral(equals(2.0))),
- has(floatLiteral(equals(1.0)))))))));
-}
-
-
-const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
-
-TEST_P(ImportExpr, ImportVAArgExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport(__builtin_va_list list, ...) {"
- " (void)__builtin_va_arg(list, int); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
-}
-
-TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "struct C {};"
- "void declToImport() { C c = C(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- exprWithCleanups(has(cxxConstructExpr(
- has(materializeTemporaryExpr(has(implicitCastExpr(
- has(cxxTemporaryObjectExpr())))))))))));
-}
-
-TEST_P(ImportType, ImportAtomicType) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { typedef _Atomic(int) a_int; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
-}
-
-TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T> void declToImport() { };",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl());
-}
-
-TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " (void)d.t;"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(
- cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
- testImport(
- "template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " (void)(&d)->t;"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(
- cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
-}
-
-TEST_P(ImportType, ImportTypeAliasTemplate) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <int K>"
- "struct dummy { static const int i = K; };"
- "template <int K> using dummy2 = dummy<K>;"
- "int declToImport() { return dummy2<3>::i; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasDescendant(implicitCastExpr(has(declRefExpr()))),
- unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
-}
-
-const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
- varTemplateSpecializationDecl;
-
-TEST_P(ImportDecl, ImportVarTemplate) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T>"
- "T pi = T(3.1415926535897932385L);"
- "void declToImport() { (void)pi<int>; }",
- Lang_CXX14, "", Lang_CXX14, Verifier,
- functionDecl(
- hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
- unless(hasAncestor(translationUnitDecl(has(varDecl(
- hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
-}
-
-TEST_P(ImportType, ImportPackExpansion) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename... Args>"
- "struct dummy {"
- " dummy(Args... args) {}"
- " static const int i = 4;"
- "};"
- "int declToImport() { return dummy<int>::i; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(hasDescendant(
- returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
-}
-
-const internal::VariadicDynCastAllOfMatcher<Type,
- DependentTemplateSpecializationType>
- dependentTemplateSpecializationType;
-
-TEST_P(ImportType, ImportDependentTemplateSpecialization) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T>"
- "struct A;"
- "template<typename T>"
- "struct declToImport {"
- " typename A<T>::template B<T> a;"
- "};",
- Lang_CXX, "", Lang_CXX, Verifier,
- classTemplateDecl(has(cxxRecordDecl(has(
- fieldDecl(hasType(dependentTemplateSpecializationType())))))));
-}
-
-const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
- sizeOfPackExpr;
-
-TEST_P(ImportExpr, ImportSizeOfPackExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename... Ts>"
- "void declToImport() {"
- " const int i = sizeof...(Ts);"
- "};"
- "void g() { declToImport<int>(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
- testImport(
- "template <typename... Ts>"
- "using X = int[sizeof...(Ts)];"
- "template <typename... Us>"
- "struct Y {"
- " X<Us..., int, double, int, Us...> f;"
- "};"
- "Y<float, int> declToImport;",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
- hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
-}
-
-/// \brief Matches __builtin_types_compatible_p:
-/// GNU extension to check equivalent types
-/// Given
-/// \code
-/// __builtin_types_compatible_p(int, int)
-/// \endcode
-// will generate TypeTraitExpr <...> 'int'
-const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
-
-TEST_P(ImportExpr, ImportTypeTraitExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { "
- " (void)__builtin_types_compatible_p(int, int);"
- "}",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
-}
-
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
-
-TEST_P(ImportExpr, ImportCXXTypeidExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "namespace std { class type_info {}; }"
- "void declToImport() {"
- " int x;"
- " auto a = typeid(int); auto b = typeid(x);"
- "}",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasDescendant(varDecl(
- hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
- hasDescendant(varDecl(
- hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
-}
-
-TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T> struct declToImport {"
- " void m() { (void)__is_pod(T); }"
- "};"
- "void f() { declToImport<int>().m(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- classTemplateDecl(has(cxxRecordDecl(has(
- functionDecl(hasDescendant(
- typeTraitExpr(hasType(booleanType())))))))));
-}
-
-TEST_P(ImportDecl, ImportRecordDeclInFunc) {
- MatchVerifier<Decl> Verifier;
- testImport("int declToImport() { "
- " struct data_t {int a;int b;};"
- " struct data_t d;"
- " return 0;"
- "}",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasBody(compoundStmt(
- has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
-}
-
-TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
- Decl *FromTU = getTuDecl("int declToImport() { "
- " struct data_t {int a;int b;};"
- " struct data_t d;"
- " return 0;"
- "}",
- Lang_C, "input.c");
- auto *FromVar =
- FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
- ASSERT_TRUE(FromVar);
- auto ToType =
- ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
- EXPECT_FALSE(ToType.isNull());
-}
-
-TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
- // This construct is not supported by ASTImporter.
- Decl *FromTU = getTuDecl(
- "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
- Lang_C, "input.c");
- auto *From = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("declToImport")));
- ASSERT_TRUE(From);
- auto *To = Import(From, Lang_C);
- EXPECT_EQ(To, nullptr);
-}
-
-TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncFromMacro) {
- Decl *FromTU = getTuDecl(
- "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
- "int declToImport(){ return NONAME_SIZEOF(int); }",
- Lang_C, "input.c");
- auto *From = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("declToImport")));
- ASSERT_TRUE(From);
- auto *To = Import(From, Lang_C);
- ASSERT_TRUE(To);
- EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
- To, functionDecl(hasName("declToImport"),
- hasDescendant(unaryExprOrTypeTraitExpr()))));
-}
-
-TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParamsFromMacro) {
- // This construct is not supported by ASTImporter.
- Decl *FromTU = getTuDecl(
- "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
- "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
- Lang_C, "input.c");
- auto *From = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("declToImport")));
- ASSERT_TRUE(From);
- auto *To = Import(From, Lang_C);
- EXPECT_EQ(To, nullptr);
-}
-
-const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
- cxxPseudoDestructorExpr;
-
-TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "typedef int T;"
- "void declToImport(int *p) {"
- " T t;"
- " p->T::~T();"
- "}",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- callExpr(has(cxxPseudoDestructorExpr())))));
-}
-
-TEST_P(ImportDecl, ImportUsingDecl) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "namespace foo { int bar; }"
- "void declToImport() { using foo::bar; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(usingDecl())));
-}
-
-/// \brief Matches shadow declarations introduced into a scope by a
-/// (resolved) using declaration.
-///
-/// Given
-/// \code
-/// namespace n { int f; }
-/// namespace declToImport { using n::f; }
-/// \endcode
-/// usingShadowDecl()
-/// matches \code f \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl,
- UsingShadowDecl> usingShadowDecl;
-
-TEST_P(ImportDecl, ImportUsingShadowDecl) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "namespace foo { int bar; }"
- "namespace declToImport { using foo::bar; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- namespaceDecl(has(usingShadowDecl())));
-}
-
-TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T> int foo();"
- "template <typename T> void declToImport() {"
- " (void)::foo<T>;"
- " (void)::template foo<T>;"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
-}
-
-TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " d.t = T();"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(
- binaryOperator(has(cxxUnresolvedConstructExpr())))));
- testImport(
- "template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " (&d)->t = T();"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(
- binaryOperator(has(cxxUnresolvedConstructExpr())))));
-}
-
-/// Check that function "declToImport()" (which is the templated function
-/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
-/// Same for class template declarations.
-TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T> void declToImport() { T a = 1; }"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasAncestor(translationUnitDecl(
- unless(has(functionDecl(hasName("declToImport"))))))));
- testImport(
- "template <typename T> struct declToImport { T t; };"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- classTemplateDecl(hasAncestor(translationUnitDecl(
- unless(has(cxxRecordDecl(hasName("declToImport"))))))));
-}
-
-TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
- MatchVerifier<Decl> Verifier;
- auto Code =
- R"s(
- struct declToImport {
- template <typename T0> struct X;
- template <typename T0> struct X<T0 *> {};
- };
- )s";
- testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
- recordDecl(has(classTemplateDecl()),
- has(classTemplateSpecializationDecl())));
-}
-
-TEST_P(ImportExpr, CXXOperatorCallExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "class declToImport {"
- " void f() { *this = declToImport(); }"
- "};",
- Lang_CXX, "", Lang_CXX, Verifier,
- cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
- cxxOperatorCallExpr())))));
-}
-
-TEST_P(ImportExpr, DependentSizedArrayType) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T, int Size> class declToImport {"
- " T data[Size];"
- "};",
- Lang_CXX, "", Lang_CXX, Verifier,
- classTemplateDecl(has(cxxRecordDecl(
- has(fieldDecl(hasType(dependentSizedArrayType())))))));
-}
-
-TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
- Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
- auto From =
- FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
- ASSERT_TRUE(From);
- auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
- ASSERT_TRUE(To);
- Decl *ToTemplated = To->getTemplatedDecl();
- Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
- EXPECT_TRUE(ToTemplated1);
- EXPECT_EQ(ToTemplated1, ToTemplated);
-}
-
-TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
- Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
- auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
- FromTU, functionTemplateDecl());
- ASSERT_TRUE(From);
- auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
- ASSERT_TRUE(To);
- Decl *ToTemplated = To->getTemplatedDecl();
- Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
- EXPECT_TRUE(ToTemplated1);
- EXPECT_EQ(ToTemplated1, ToTemplated);
-}
-
-TEST_P(ASTImporterTestBase,
- ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
- Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
- auto FromFT =
- FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
- ASSERT_TRUE(FromFT);
-
- auto ToTemplated =
- cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
- EXPECT_TRUE(ToTemplated);
- auto ToTU = ToTemplated->getTranslationUnitDecl();
- auto ToFT =
- FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
- EXPECT_TRUE(ToFT);
-}
-
-TEST_P(ASTImporterTestBase,
- ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
- Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
- auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
- FromTU, functionTemplateDecl());
- ASSERT_TRUE(FromFT);
-
- auto ToTemplated =
- cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
- EXPECT_TRUE(ToTemplated);
- auto ToTU = ToTemplated->getTranslationUnitDecl();
- auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
- ToTU, functionTemplateDecl());
- EXPECT_TRUE(ToFT);
-}
-
-TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
- auto Code =
- R"(
- namespace x {
- template<class X> struct S1{};
- template<class X> struct S2{};
- template<class X> struct S3{};
- }
- )";
- Decl *FromTU = getTuDecl(Code, Lang_CXX);
- auto FromNs =
- FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
- auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
- ASSERT_TRUE(ToNs);
- auto From =
- FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
- classTemplateDecl(
- hasName("S2")));
- auto To =
- FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
- classTemplateDecl(
- hasName("S2")));
- ASSERT_TRUE(From);
- ASSERT_TRUE(To);
- auto ToTemplated = To->getTemplatedDecl();
- auto ToTemplated1 =
- cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
- EXPECT_TRUE(ToTemplated1);
- ASSERT_EQ(ToTemplated1, ToTemplated);
-}
-
-TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template <typename T> struct X {};
-
- void declToImport(int y, X<int> &x) {}
-
- template <> struct X<int> {
- void g() {
- X<int> x;
- declToImport(0, x);
- }
- };
- )",
- Lang_CXX, "", Lang_CXX);
-
- MatchVerifier<Decl> Verifier;
- auto Matcher = functionDecl(hasName("declToImport"),
- parameterCountIs(2),
- hasParameter(0, hasName("y")),
- hasParameter(1, hasName("x")),
- hasParameter(1, hasType(asString("X<int> &"))));
- ASSERT_TRUE(Verifier.match(From, Matcher));
- EXPECT_TRUE(Verifier.match(To, Matcher));
-}
-
-TEST_P(ASTImporterTestBase,
- TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX);
-
- auto Check = [](Decl *D) -> bool {
- auto TU = D->getTranslationUnitDecl();
- for (auto Child : TU->decls()) {
- if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
- if (FD->getNameAsString() == "declToImport") {
- GTEST_NONFATAL_FAILURE_(
- "TU should not contain any FunctionDecl with name declToImport");
- return false;
- }
- }
- }
- return true;
- };
-
- ASSERT_TRUE(Check(From));
- EXPECT_TRUE(Check(To));
-}
-
-TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl("template <typename T> struct declToImport { T t; };"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX);
-
- auto Check = [](Decl *D) -> bool {
- auto TU = D->getTranslationUnitDecl();
- for (auto Child : TU->decls()) {
- if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
- if (RD->getNameAsString() == "declToImport") {
- GTEST_NONFATAL_FAILURE_(
- "TU should not contain any CXXRecordDecl with name declToImport");
- return false;
- }
- }
- }
- return true;
- };
-
- ASSERT_TRUE(Check(From));
- EXPECT_TRUE(Check(To));
-}
-
-TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl(
- "template <typename T> struct X {};"
- "template <typename T> using declToImport = X<T>;"
- "void instantiate() { declToImport<int> a; }",
- Lang_CXX11, "", Lang_CXX11);
-
- auto Check = [](Decl *D) -> bool {
- auto TU = D->getTranslationUnitDecl();
- for (auto Child : TU->decls()) {
- if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
- if (AD->getNameAsString() == "declToImport") {
- GTEST_NONFATAL_FAILURE_(
- "TU should not contain any TypeAliasDecl with name declToImport");
- return false;
- }
- }
- }
- return true;
- };
-
- ASSERT_TRUE(Check(From));
- EXPECT_TRUE(Check(To));
-}
-
-TEST_P(
- ASTImporterTestBase,
- TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
-
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template<class T>
- class Base {};
- class declToImport : public Base<declToImport> {};
- )",
- Lang_CXX, "", Lang_CXX);
-
- // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
- auto Pattern =
- translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
- ASSERT_TRUE(
- MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
- EXPECT_TRUE(
- MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
-
- // Check that the ClassTemplateSpecializationDecl is the child of the
- // ClassTemplateDecl.
- Pattern = translationUnitDecl(has(classTemplateDecl(
- hasName("Base"), has(classTemplateSpecializationDecl()))));
- ASSERT_TRUE(
- MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
- EXPECT_TRUE(
- MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
-}
-
-AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
- size_t Index = 0;
- for (FieldDecl *Field : Node.fields()) {
- if (Index == Order.size())
- return false;
- if (Field->getName() != Order[Index])
- return false;
- ++Index;
- }
- return Index == Order.size();
-}
-
-TEST_P(ASTImporterTestBase,
- TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- namespace NS {
- template<class T>
- class X {};
- template class X<int>;
- }
- )",
- Lang_CXX, "", Lang_CXX, "NS");
-
- // Check that the ClassTemplateSpecializationDecl is NOT the child of the
- // ClassTemplateDecl.
- auto Pattern = namespaceDecl(has(classTemplateDecl(
- hasName("X"), unless(has(classTemplateSpecializationDecl())))));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
-
- // Check that the ClassTemplateSpecializationDecl is the child of the
- // NamespaceDecl.
- Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
-}
-
-TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl(
- "struct declToImport { int a; int b; };",
- Lang_CXX11, "", Lang_CXX11);
-
- MatchVerifier<Decl> Verifier;
- ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
- EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
-}
-
-TEST_P(ASTImporterTestBase,
- DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- // The original recursive algorithm of ASTImporter first imports 'c' then
- // 'b' and lastly 'a'. Therefore we must restore the order somehow.
- R"s(
- struct declToImport {
- int a = c + b;
- int b = 1;
- int c = 2;
- };
- )s",
- Lang_CXX11, "", Lang_CXX11);
-
- MatchVerifier<Decl> Verifier;
- ASSERT_TRUE(
- Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
- EXPECT_TRUE(
- Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
-}
-
-TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- struct declToImport {
- };
- )",
- Lang_CXX, "", Lang_CXX);
-
- MatchVerifier<Decl> Verifier;
- // Match the implicit Decl.
- auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
- ASSERT_TRUE(Verifier.match(From, Matcher));
- EXPECT_TRUE(Verifier.match(To, Matcher));
-}
-
-TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template <typename U>
- struct declToImport {
- };
- )",
- Lang_CXX, "", Lang_CXX);
-
- MatchVerifier<Decl> Verifier;
- // Match the implicit Decl.
- auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
- ASSERT_TRUE(Verifier.match(From, Matcher));
- EXPECT_TRUE(Verifier.match(To, Matcher));
-}
-
-TEST_P(
- ASTImporterTestBase,
- ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template<class T>
- class Base {};
- class declToImport : public Base<declToImport> {};
- )",
- Lang_CXX, "", Lang_CXX);
-
- auto hasImplicitClass = has(cxxRecordDecl());
- auto Pattern = translationUnitDecl(has(classTemplateDecl(
- hasName("Base"),
- has(classTemplateSpecializationDecl(hasImplicitClass)))));
- ASSERT_TRUE(
- MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
- EXPECT_TRUE(
- MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
-}
-
-TEST_P(ASTImporterTestBase, IDNSOrdinary) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
-
- MatchVerifier<Decl> Verifier;
- auto Matcher = functionDecl();
- ASSERT_TRUE(Verifier.match(From, Matcher));
- EXPECT_TRUE(Verifier.match(To, Matcher));
- EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
-}
-
-TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
- Decl *FromTU = getTuDecl(
- R"(
- struct X {};
- void operator<<(int, X);
- )",
- Lang_CXX);
- Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
- const Decl *To = Import(From, Lang_CXX);
- EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
-}
-
-TEST_P(ASTImporterTestBase,
- ShouldImportMembersOfClassTemplateSpecializationDecl) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template<class T>
- class Base { int a; };
- class declToImport : Base<declToImport> {};
- )",
- Lang_CXX, "", Lang_CXX);
-
- auto Pattern = translationUnitDecl(has(classTemplateDecl(
- hasName("Base"),
- has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
- ASSERT_TRUE(
- MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
- EXPECT_TRUE(
- MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
-}
-
-TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
- {
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B;
- )",
- Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU, classTemplateDecl(hasName("B")));
-
- Import(FromD, Lang_CXX);
- }
-
- {
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B {
- void f();
- };
- )",
- Lang_CXX, "input1.cc");
- FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("f")));
- Import(FromD, Lang_CXX);
- auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU, classTemplateDecl(hasName("B")));
- auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
- EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
- }
-}
-
-TEST_P(ASTImporterTestBase,
- ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
- Decl *ToTU = getToTuDecl(
- R"(
- template <typename T>
- struct B {
- void f();
- };
-
- template <typename T>
- struct B;
- )",
- Lang_CXX);
- ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
- [](const ClassTemplateDecl *T) {
- return T->isThisDeclarationADefinition();
- })
- .match(ToTU, classTemplateDecl()));
-
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B {
- void f();
- };
- )",
- Lang_CXX, "input1.cc");
- ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU, classTemplateDecl(hasName("B")));
-
- Import(FromD, Lang_CXX);
-
- // We should have only one definition.
- EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
- [](const ClassTemplateDecl *T) {
- return T->isThisDeclarationADefinition();
- })
- .match(ToTU, classTemplateDecl()));
-}
-
-TEST_P(ASTImporterTestBase,
- ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
- Decl *ToTU = getToTuDecl(
- R"(
- struct B {
- void f();
- };
-
- struct B;
- )",
- Lang_CXX);
- ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
- ToTU, cxxRecordDecl(unless(isImplicit()))));
-
- Decl *FromTU = getTuDecl(
- R"(
- struct B {
- void f();
- };
- )",
- Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("B")));
-
- Import(FromD, Lang_CXX);
-
- EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
- ToTU, cxxRecordDecl(unless(isImplicit()))));
-}
-
-static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
- EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
- EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
- EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
- EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
-}
-static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
- SourceManager &SM1, SourceManager &SM2) {
- CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
- FullSourceLoc{ Range2.getBegin(), SM2 });
- CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
- FullSourceLoc{ Range2.getEnd(), SM2 });
-}
-TEST_P(ASTImporterTestBase, ImportSourceLocs) {
- Decl *FromTU = getTuDecl(
- R"(
- #define MFOO(arg) arg = arg + 1
-
- void foo() {
- int a = 5;
- MFOO(a);
- }
- )",
- Lang_CXX);
- auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
- auto ToD = Import(FromD, Lang_CXX);
-
- auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
- auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
- auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
- auto FromRHS =
- LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
-
- SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
- SourceManager &FromSM = FromD->getASTContext().getSourceManager();
- CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
- FromSM);
- CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
- FromSM);
- CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
- FromSM);
-}
-
-TEST_P(ASTImporterTestBase, ImportNestedMacro) {
- Decl *FromTU = getTuDecl(
- R"(
- #define FUNC_INT void declToImport
- #define FUNC FUNC_INT
- FUNC(int a);
- )",
- Lang_CXX);
- auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
- auto ToD = Import(FromD, Lang_CXX);
-
- SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
- SourceManager &FromSM = FromD->getASTContext().getSourceManager();
- CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
- FromSM);
-}
-
-TEST_P(
- ASTImporterTestBase,
- ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
-{
- Decl *ToTU = getToTuDecl(
- R"(
- template <typename T>
- struct B;
-
- template <>
- struct B<int> {};
-
- template <>
- struct B<int>;
- )",
- Lang_CXX);
- // We should have only one definition.
- ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
- [](const ClassTemplateSpecializationDecl *T) {
- return T->isThisDeclarationADefinition();
- })
- .match(ToTU, classTemplateSpecializationDecl()));
-
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B;
-
- template <>
- struct B<int> {};
- )",
- Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, classTemplateSpecializationDecl(hasName("B")));
-
- Import(FromD, Lang_CXX);
-
- // We should have only one definition.
- EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
- [](const ClassTemplateSpecializationDecl *T) {
- return T->isThisDeclarationADefinition();
- })
- .match(ToTU, classTemplateSpecializationDecl()));
-}
-
-TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
- Decl *FromTU = getTuDecl(
- R"(
- struct { int a; int b; } object0 = { 2, 3 };
- struct { int x; int y; int z; } object1;
- )",
- Lang_CXX, "input0.cc");
-
- auto *Obj0 =
- FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
- auto *From0 = getRecordDecl(Obj0);
- auto *Obj1 =
- FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
- auto *From1 = getRecordDecl(Obj1);
-
- auto *To0 = Import(From0, Lang_CXX);
- auto *To1 = Import(From1, Lang_CXX);
-
- EXPECT_TRUE(To0);
- EXPECT_TRUE(To1);
- EXPECT_NE(To0, To1);
- EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
-}
-
-TEST_P(ASTImporterTestBase, AnonymousRecords) {
- auto *Code =
- R"(
- struct X {
- struct { int a; };
- struct { int b; };
- };
- )";
- Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
-
- Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
-
- auto *X0 =
- FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
- auto *X1 =
- FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
- Import(X0, Lang_C);
- Import(X1, Lang_C);
-
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- // We expect no (ODR) warning during the import.
- EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
- EXPECT_EQ(1u,
- DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
-}
-
-TEST_P(ASTImporterTestBase, AnonymousRecordsReversed) {
- Decl *FromTU0 = getTuDecl(
- R"(
- struct X {
- struct { int a; };
- struct { int b; };
- };
- )",
- Lang_C, "input0.c");
-
- Decl *FromTU1 = getTuDecl(
- R"(
- struct X { // reversed order
- struct { int b; };
- struct { int a; };
- };
- )",
- Lang_C, "input1.c");
-
- auto *X0 =
- FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
- auto *X1 =
- FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
- Import(X0, Lang_C);
- Import(X1, Lang_C);
-
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- // We expect one (ODR) warning during the import.
- EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
- EXPECT_EQ(2u,
- DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
-}
-
-TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
- auto Pattern = varDecl(hasName("x"));
- VarDecl *Imported1;
- {
- Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
- Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
- }
- VarDecl *Imported2;
- {
- Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
- Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
- }
- EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
- EXPECT_FALSE(Imported2->isUsed(false));
- {
- Decl *FromTU =
- getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("f")));
- Import(FromD, Lang_CXX);
- }
- EXPECT_TRUE(Imported2->isUsed(false));
-}
-
-TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag2) {
- auto Pattern = varDecl(hasName("x"));
- VarDecl *ExistingD;
- {
- Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
- ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
- }
- EXPECT_FALSE(ExistingD->isUsed(false));
- {
- Decl *FromTU = getTuDecl(
- "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("f")));
- Import(FromD, Lang_CXX);
- }
- EXPECT_TRUE(ExistingD->isUsed(false));
-}
-
-TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag3) {
- auto Pattern = varDecl(hasName("a"));
- VarDecl *ExistingD;
- {
- Decl *ToTU = getToTuDecl(
- R"(
- struct A {
- static const int a = 1;
- };
- )", Lang_CXX);
- ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
- }
- EXPECT_FALSE(ExistingD->isUsed(false));
- {
- Decl *FromTU = getTuDecl(
- R"(
- struct A {
- static const int a = 1;
- };
- const int *f() { return &A::a; } // requires storage,
- // thus used flag will be set
- )", Lang_CXX, "input1.cc");
- auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("f")));
- auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
- ASSERT_TRUE(FromD->isUsed(false));
- Import(FromFunD, Lang_CXX);
- }
- EXPECT_TRUE(ExistingD->isUsed(false));
-}
-
-TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
- auto Pattern = varDecl(hasName("x"));
-
- Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
-
- auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
-
- ASSERT_FALSE(Imported1->isUsed(false));
-
- FromD->setIsUsed();
- auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
-
- EXPECT_EQ(Imported1, Imported2);
- EXPECT_TRUE(Imported2->isUsed(false));
-}
-
-struct ImportFunctions : ASTImporterTestBase {};
-
-TEST_P(ImportFunctions,
- DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
- Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- FunctionDecl *FromD = // Definition
- LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
-}
-
-TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
- Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- FunctionDecl *FromD =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
- EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
-}
-
-TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
- Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *From =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
-
- Decl *ImportedD = Import(From, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
-}
-
-TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
- Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *From =
- LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
-
- Decl *ImportedD = Import(From, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To1);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
-}
-
-TEST_P(ImportFunctions, ImportPrototypes) {
- auto Pattern = functionDecl(hasName("f"));
-
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
-}
-
-TEST_P(ImportFunctions, ImportDefinitions) {
- auto Pattern = functionDecl(hasName("f"));
-
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
-}
-
-TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
- auto Pattern = functionDecl(hasName("f"));
-
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
-}
-
-TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
- auto Pattern = functionDecl(hasName("f"));
-
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
- FunctionDecl *FromD =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
- FunctionDecl *FromD =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
- FunctionDecl *DefinitionD =
- LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
- EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
-}
-
-TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
- auto Pattern = functionDecl(hasName("f"));
-
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
- FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
-
- FunctionDecl *DefinitionD =
- LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
-
- EXPECT_TRUE(DefinitionD->getPreviousDecl());
- EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
- EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
-}
-
-TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
- auto Code =
- R"(
- struct B { virtual void f(); };
- void B::f() {}
- struct D : B { void f(); };
- )";
- auto Pattern =
- cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
- Decl *FromTU = getTuDecl(Code, Lang_CXX);
- CXXMethodDecl *Proto =
- FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
-
- ASSERT_EQ(Proto->size_overridden_methods(), 1u);
- CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
- EXPECT_EQ(To->size_overridden_methods(), 1u);
-}
-
-TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
- auto Code =
- R"(
- struct B { virtual void f(); };
- void B::f() {}
- )";
- auto Pattern =
- cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
- Decl *FromTU = getTuDecl(Code, Lang_CXX);
- CXXMethodDecl *Proto =
- FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
- CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
-
- ASSERT_TRUE(Proto->isVirtual());
- ASSERT_TRUE(Def->isVirtual());
- CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
- EXPECT_TRUE(To->isVirtual());
-}
-
-TEST_P(ImportFunctions,
- ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
- Decl *ToTU = getToTuDecl(
- R"(
- void f() {}
- void f();
- )",
- Lang_CXX);
- ASSERT_EQ(1u,
- DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
- return FD->doesThisDeclarationHaveABody();
- }).match(ToTU, functionDecl()));
-
- Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
-
- Import(FromD, Lang_CXX);
-
- EXPECT_EQ(1u,
- DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
- return FD->doesThisDeclarationHaveABody();
- }).match(ToTU, functionDecl()));
-}
-
-struct ImportFriendFunctions : ImportFunctions {};
-
-TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
- auto Pattern = functionDecl(hasName("f"));
-
- Decl *FromTU = getTuDecl("struct X { friend void f(); };"
- "void f();",
- Lang_CXX,
- "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
- auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
-}
-
-TEST_P(ImportFriendFunctions,
- ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
- auto Pattern = functionDecl(hasName("f"));
-
- Decl *FromTU = getTuDecl("void f();"
- "struct X { friend void f(); };",
- Lang_CXX, "input0.cc");
- auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
- auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
-}
-
-TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
- auto Pattern = functionDecl(hasName("f"));
-
- Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
- "void f();",
- Lang_CXX,
- "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
- auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
-}
-
-TEST_P(ImportFriendFunctions,
- ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
- auto Pattern = functionDecl(hasName("f"));
-
- Decl *FromTU = getTuDecl("struct X { friend void f(); };"
- "void f(){}",
- Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
- auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
-}
-
-// Disabled temporarily, because the new structural equivalence check
-// (https://reviews.llvm.org/D48628) breaks it.
-// PreviousDecl is not set because there is no structural match.
-// FIXME Enable!
-TEST_P(ImportFriendFunctions,
- DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
- auto Pattern = functionDecl(hasName("f"));
-
- Decl *FromTU = getTuDecl(
- R"(
- class X;
- void f(X *x){}
- class X{
- friend void f(X *x);
- };
- )",
- Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
- auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
- .match(ToTU, friendDecl())
- ->getFriendDecl());
- EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
- // The parameters must refer the same type
- EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
- (*ImportedD->param_begin())->getOriginalType());
-}
-
-// Disabled temporarily, because the new structural equivalence check
-// (https://reviews.llvm.org/D48628) breaks it.
-// PreviousDecl is not set because there is no structural match.
-// FIXME Enable!
-TEST_P(ImportFriendFunctions,
- DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
- auto Pattern = functionDecl(hasName("f"));
-
- Decl *FromTU = getTuDecl(
- R"(
- class X;
- void f(X *x){}
- class X{
- friend void f(X *x);
- };
- )",
- Lang_CXX, "input0.cc");
- auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
- auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
- ToTU, functionDecl(unless(hasParent(friendDecl()))));
-
- EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
- // The parameters must refer the same type
- EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
- (*ImportedD->param_begin())->getOriginalType());
-}
-
-TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
- auto Pattern = functionDecl(hasName("f"));
-
- FunctionDecl *ImportedD;
- {
- Decl *FromTU =
- getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- }
- FunctionDecl *ImportedD1;
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- }
-
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
- EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
- EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
-}
-
-TEST_P(ImportFriendFunctions, Lookup) {
- auto FunctionPattern = functionDecl(hasName("f"));
- auto ClassPattern = cxxRecordDecl(hasName("X"));
-
- TranslationUnitDecl *FromTU =
- getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
- ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- {
- auto FromName = FromD->getDeclName();
- auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
- auto LookupRes = Class->noload_lookup(FromName);
- ASSERT_EQ(LookupRes.size(), 0u);
- LookupRes = FromTU->noload_lookup(FromName);
- ASSERT_EQ(LookupRes.size(), 1u);
- }
-
- auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- auto ToName = ToD->getDeclName();
-
- TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
- auto LookupRes = Class->noload_lookup(ToName);
- EXPECT_EQ(LookupRes.size(), 0u);
- LookupRes = ToTU->noload_lookup(ToName);
- EXPECT_EQ(LookupRes.size(), 1u);
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
- EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
-}
-
-TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
- auto FunctionPattern = functionDecl(hasName("f"));
- auto ClassPattern = cxxRecordDecl(hasName("X"));
-
- TranslationUnitDecl *FromTU = getTuDecl(
- "struct X { friend void f(); };"
- // This proto decl makes f available to normal
- // lookup, otherwise it is hidden.
- // Normal C++ lookup (implemented in
- // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
- // returns the found `NamedDecl` only if the set IDNS is matched
- "void f();",
- Lang_CXX, "input0.cc");
- auto *FromFriend =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
- auto *FromNormal =
- LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
- ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
-
- auto FromName = FromFriend->getDeclName();
- auto *FromClass =
- FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
- auto LookupRes = FromClass->noload_lookup(FromName);
- ASSERT_EQ(LookupRes.size(), 0u);
- LookupRes = FromTU->noload_lookup(FromName);
- ASSERT_EQ(LookupRes.size(), 1u);
-
- auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
- auto ToName = ToFriend->getDeclName();
-
- TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
- LookupRes = ToClass->noload_lookup(ToName);
- EXPECT_EQ(LookupRes.size(), 0u);
- LookupRes = ToTU->noload_lookup(ToName);
- // Test is disabled because this result is 2.
- EXPECT_EQ(LookupRes.size(), 1u);
-
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
- ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
- auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
- EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
-}
-
-TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
- auto FunctionPattern = functionDecl(hasName("f"));
- auto ClassPattern = cxxRecordDecl(hasName("X"));
-
- TranslationUnitDecl *FromTU = getTuDecl(
- "void f();"
- "struct X { friend void f(); };",
- Lang_CXX, "input0.cc");
- auto *FromNormal =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
- auto *FromFriend =
- LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
- ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
-
- auto FromName = FromNormal->getDeclName();
- auto *FromClass =
- FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
- auto LookupRes = FromClass->noload_lookup(FromName);
- ASSERT_EQ(LookupRes.size(), 0u);
- LookupRes = FromTU->noload_lookup(FromName);
- ASSERT_EQ(LookupRes.size(), 1u);
-
- auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
- auto ToName = ToNormal->getDeclName();
- TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-
- auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
- LookupRes = ToClass->noload_lookup(ToName);
- EXPECT_EQ(LookupRes.size(), 0u);
- LookupRes = ToTU->noload_lookup(ToName);
- EXPECT_EQ(LookupRes.size(), 1u);
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
- ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
- auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
- EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
-}
-
-TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
- auto Pattern = functionDecl(hasName("f"));
-
- TranslationUnitDecl *FromNormalTU =
- getTuDecl("void f();", Lang_CXX, "input0.cc");
- auto *FromNormalF =
- FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
- TranslationUnitDecl *FromFriendTU =
- getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
- auto *FromFriendF =
- FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
- auto FromNormalName = FromNormalF->getDeclName();
- auto FromFriendName = FromFriendF->getDeclName();
-
- ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
- ASSERT_EQ(LookupRes.size(), 1u);
- LookupRes = FromFriendTU->noload_lookup(FromFriendName);
- ASSERT_EQ(LookupRes.size(), 1u);
-
- auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
- TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- auto ToName = ToNormalF->getDeclName();
- EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
- LookupRes = ToTU->noload_lookup(ToName);
- EXPECT_EQ(LookupRes.size(), 1u);
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
-
- auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
- LookupRes = ToTU->noload_lookup(ToName);
- EXPECT_EQ(LookupRes.size(), 1u);
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
-
- EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
-
- EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
- EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
-}
-
-TEST_P(ImportFriendFunctions, ImportFriendList) {
- TranslationUnitDecl *FromTU = getTuDecl(
- "struct X { friend void f(); };"
- "void f();",
- Lang_CXX, "input0.cc");
- auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("f")));
-
- auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("X")));
- auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
- auto FromFriends = FromClass->friends();
- unsigned int FrN = 0;
- for (auto Fr : FromFriends) {
- ASSERT_EQ(Fr, FromFriend);
- ++FrN;
- }
- ASSERT_EQ(FrN, 1u);
-
- Import(FromFriendF, Lang_CXX);
- TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
- ToTU, cxxRecordDecl(hasName("X")));
- auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
- auto ToFriends = ToClass->friends();
- FrN = 0;
- for (auto Fr : ToFriends) {
- EXPECT_EQ(Fr, ToFriend);
- ++FrN;
- }
- EXPECT_EQ(FrN, 1u);
-}
-
-AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
- InnerMatcher) {
- if (auto *Typedef = Node.getTypedefNameForAnonDecl())
- return InnerMatcher.matches(*Typedef, Finder, Builder);
- return false;
-}
-
-TEST_P(ImportDecl, ImportEnumSequential) {
- CodeFiles Samples{{"main.c",
- {"void foo();"
- "void moo();"
- "int main() { foo(); moo(); }",
- Lang_C}},
-
- {"foo.c",
- {"typedef enum { THING_VALUE } thing_t;"
- "void conflict(thing_t type);"
- "void foo() { (void)THING_VALUE; }"
- "void conflict(thing_t type) {}",
- Lang_C}},
-
- {"moo.c",
- {"typedef enum { THING_VALUE } thing_t;"
- "void conflict(thing_t type);"
- "void moo() { conflict(THING_VALUE); }",
- Lang_C}}};
-
- auto VerificationMatcher =
- enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
- hasTypedefForAnonDecl(hasName("thing_t")));
-
- ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
- ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
-
- testImportSequence(
- Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
- // Just check that there is only one enum decl in the result AST.
- "main.c", enumDecl(), VerificationMatcher);
-
- // For different import order, result should be the same.
- testImportSequence(
- Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
- // Check that there is only one enum decl in the result AST.
- "main.c", enumDecl(), VerificationMatcher);
-}
-
-const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
- dependentScopeDeclRefExpr;
-
-TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
- MatchVerifier<Decl> Verifier;
- testImport("template <typename T> struct S { static T foo; };"
- "template <typename T> void declToImport() {"
- " (void) S<T>::foo;"
- "}"
- "void instantiate() { declToImport<int>(); }"
- "template <typename T> T S<T>::foo;",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionTemplateDecl(has(functionDecl(has(compoundStmt(
- has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
-
- testImport("template <typename T> struct S {"
- "template<typename S> static void foo(){};"
- "};"
- "template <typename T> void declToImport() {"
- " S<T>::template foo<T>();"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionTemplateDecl(has(functionDecl(has(compoundStmt(
- has(callExpr(has(dependentScopeDeclRefExpr())))))))));
-}
-
-const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
- dependentNameType;
-
-TEST_P(ImportExpr, DependentNameType) {
- MatchVerifier<Decl> Verifier;
- testImport("template <typename T> struct declToImport {"
- " typedef typename T::type dependent_name;"
- "};",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- classTemplateDecl(has(
- cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
-}
-
-TEST_P(ImportExpr, UnresolvedMemberExpr) {
- MatchVerifier<Decl> Verifier;
- testImport("struct S { template <typename T> void mem(); };"
- "template <typename U> void declToImport() {"
- " S s;"
- " s.mem<U>();"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionTemplateDecl(has(functionDecl(has(
- compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
-}
-
-class ImportImplicitMethods : public ASTImporterTestBase {
-public:
- static constexpr auto DefaultCode = R"(
- struct A { int x; };
- void f() {
- A a;
- A a1(a);
- A a2(A{});
- a = a1;
- a = A{};
- a.~A();
- })";
-
- template <typename MatcherType>
- void testImportOf(
- const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
- test(MethodMatcher, Code, /*ExpectedCount=*/1u);
- }
-
- template <typename MatcherType>
- void testNoImportOf(
- const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
- test(MethodMatcher, Code, /*ExpectedCount=*/0u);
- }
-
-private:
- template <typename MatcherType>
- void test(const MatcherType &MethodMatcher,
- const char *Code, unsigned int ExpectedCount) {
- auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
-
- Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
- auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
- ToTU, ClassMatcher);
-
- ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
-
- {
- CXXMethodDecl *Method =
- FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
- ToClass->removeDecl(Method);
- LookupTablePtr->remove(Method);
- }
-
- ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
-
- Decl *ImportedClass = nullptr;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
- auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, ClassMatcher);
- ImportedClass = Import(FromClass, Lang_CXX11);
- }
-
- EXPECT_EQ(ToClass, ImportedClass);
- EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
- ExpectedCount);
- }
-};
-
-TEST_P(ImportImplicitMethods, DefaultConstructor) {
- testImportOf(cxxConstructorDecl(isDefaultConstructor()));
-}
-
-TEST_P(ImportImplicitMethods, CopyConstructor) {
- testImportOf(cxxConstructorDecl(isCopyConstructor()));
-}
-
-TEST_P(ImportImplicitMethods, MoveConstructor) {
- testImportOf(cxxConstructorDecl(isMoveConstructor()));
-}
-
-TEST_P(ImportImplicitMethods, Destructor) {
- testImportOf(cxxDestructorDecl());
-}
-
-TEST_P(ImportImplicitMethods, CopyAssignment) {
- testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
-}
-
-TEST_P(ImportImplicitMethods, MoveAssignment) {
- testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
-}
-
-TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
- auto Code = R"(
- struct A { A() { int x; } };
- )";
- testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
-}
-
-TEST_P(ImportImplicitMethods, DoNotImportDefault) {
- auto Code = R"(
- struct A { A() = default; };
- )";
- testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
-}
-
-TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
- auto Code = R"(
- struct A { A() = delete; };
- )";
- testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
-}
-
-TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
- auto Code = R"(
- struct A { void f() { } };
- )";
- testNoImportOf(cxxMethodDecl(hasName("f")), Code);
-}
-
-TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
- Decl *ToR1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { };", Lang_CXX, "input0.cc");
- auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("A")));
-
- ToR1 = Import(FromR, Lang_CXX);
- }
-
- Decl *ToR2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { };", Lang_CXX, "input1.cc");
- auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("A")));
-
- ToR2 = Import(FromR, Lang_CXX);
- }
-
- EXPECT_EQ(ToR1, ToR2);
-}
-
-TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
- Decl *ToR1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { int x; };", Lang_CXX, "input0.cc");
- auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("A")));
- ToR1 = Import(FromR, Lang_CXX);
- }
- Decl *ToR2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { unsigned x; };", Lang_CXX, "input1.cc");
- auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("A")));
- ToR2 = Import(FromR, Lang_CXX);
- }
- EXPECT_NE(ToR1, ToR2);
-}
-
-TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
- Decl *ToF1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { int x; };", Lang_CXX, "input0.cc");
- auto *FromF = FirstDeclMatcher<FieldDecl>().match(
- FromTU, fieldDecl(hasName("x")));
- ToF1 = Import(FromF, Lang_CXX);
- }
- Decl *ToF2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { int x; };", Lang_CXX, "input1.cc");
- auto *FromF = FirstDeclMatcher<FieldDecl>().match(
- FromTU, fieldDecl(hasName("x")));
- ToF2 = Import(FromF, Lang_CXX);
- }
- EXPECT_EQ(ToF1, ToF2);
-}
-
-TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
- Decl *ToF1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { int x; };", Lang_CXX, "input0.cc");
- auto *FromF = FirstDeclMatcher<FieldDecl>().match(
- FromTU, fieldDecl(hasName("x")));
- ToF1 = Import(FromF, Lang_CXX);
- }
- Decl *ToF2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { unsigned x; };", Lang_CXX, "input1.cc");
- auto *FromF = FirstDeclMatcher<FieldDecl>().match(
- FromTU, fieldDecl(hasName("x")));
- ToF2 = Import(FromF, Lang_CXX);
- }
- EXPECT_NE(ToF1, ToF2);
-}
-
-TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
- Decl *ToM1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
- auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("x"), isDefinition()));
- ToM1 = Import(FromM, Lang_CXX);
- }
- Decl *ToM2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
- auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("x"), isDefinition()));
- ToM2 = Import(FromM, Lang_CXX);
- }
- EXPECT_EQ(ToM1, ToM2);
-}
-
-TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
- Decl *ToM1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { void x(); }; void A::x() { }",
- Lang_CXX, "input0.cc");
- auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("x"), isDefinition()));
- ToM1 = Import(FromM, Lang_CXX);
- }
- Decl *ToM2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { void x() const; }; void A::x() const { }",
- Lang_CXX, "input1.cc");
- auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("x"), isDefinition()));
- ToM2 = Import(FromM, Lang_CXX);
- }
- EXPECT_NE(ToM1, ToM2);
-}
-
-TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
- Decl *FromTU = getTuDecl(
- R"(
- struct A {
- struct {
- struct A *next;
- } entry0;
- struct {
- struct A *next;
- } entry1;
- };
- )",
- Lang_C, "input0.cc");
- auto *From =
- FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
-
- Import(From, Lang_C);
-
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- auto *Entry0 =
- FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
- auto *Entry1 =
- FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
- auto *R0 = getRecordDecl(Entry0);
- auto *R1 = getRecordDecl(Entry1);
- EXPECT_NE(R0, R1);
- EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
- R0, recordDecl(has(fieldDecl(hasName("next"))))));
- EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
- R1, recordDecl(has(fieldDecl(hasName("next"))))));
-}
-
-TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
- Decl *FromTU = getTuDecl(
- R"(
- void f(int X, int Y, bool Z) {
- (void)[X, Y, Z] { (void)Z; };
- }
- )",
- Lang_CXX11, "input0.cc");
- auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("f")));
- auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
- EXPECT_TRUE(ToF);
-
- CXXRecordDecl *FromLambda =
- cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
- FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
-
- auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
- EXPECT_TRUE(ToLambda);
-
- // Check if the fields of the lambda class are imported in correct order.
- unsigned FromIndex = 0u;
- for (auto *FromField : FromLambda->fields()) {
- ASSERT_FALSE(FromField->getDeclName());
- auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
- EXPECT_TRUE(ToField);
- Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
- EXPECT_TRUE(ToIndex);
- EXPECT_EQ(*ToIndex, FromIndex);
- ++FromIndex;
- }
-
- EXPECT_EQ(FromIndex, 3u);
-}
-
-TEST_P(ASTImporterTestBase, MergeFieldDeclsOfClassTemplateSpecialization) {
- std::string ClassTemplate =
- R"(
- template <typename T>
- struct X {
- int a{0}; // FieldDecl with InitListExpr
- X(char) : a(3) {} // (1)
- X(int) {} // (2)
- };
- )";
- Decl *ToTU = getToTuDecl(ClassTemplate +
- R"(
- void foo() {
- // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
- X<char> xc('c');
- }
- )", Lang_CXX11);
- auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- ToTU, classTemplateSpecializationDecl(hasName("X")));
- // FieldDecl without InitlistExpr:
- auto *ToField = *ToSpec->field_begin();
- ASSERT_TRUE(ToField);
- ASSERT_FALSE(ToField->getInClassInitializer());
- Decl *FromTU = getTuDecl(ClassTemplate +
- R"(
- void bar() {
- // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
- X<char> xc(1);
- }
- )", Lang_CXX11);
- auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, classTemplateSpecializationDecl(hasName("X")));
- // FieldDecl with InitlistExpr:
- auto *FromField = *FromSpec->field_begin();
- ASSERT_TRUE(FromField);
- ASSERT_TRUE(FromField->getInClassInitializer());
-
- auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
- ASSERT_TRUE(ImportedSpec);
- EXPECT_EQ(ImportedSpec, ToSpec);
- // After the import, the FieldDecl has to be merged, thus it should have the
- // InitListExpr.
- EXPECT_TRUE(ToField->getInClassInitializer());
-}
-
-TEST_P(ASTImporterTestBase, MergeFunctionOfClassTemplateSpecialization) {
- std::string ClassTemplate =
- R"(
- template <typename T>
- struct X {
- void f() {}
- void g() {}
- };
- )";
- Decl *ToTU = getToTuDecl(ClassTemplate +
- R"(
- void foo() {
- X<char> x;
- x.f();
- }
- )", Lang_CXX11);
- Decl *FromTU = getTuDecl(ClassTemplate +
- R"(
- void bar() {
- X<char> x;
- x.g();
- }
- )", Lang_CXX11);
- auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, classTemplateSpecializationDecl(hasName("X")));
- auto FunPattern = functionDecl(hasName("g"),
- hasParent(classTemplateSpecializationDecl()));
- auto *FromFun =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
- auto *ToFun =
- FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
- ASSERT_TRUE(FromFun->hasBody());
- ASSERT_FALSE(ToFun->hasBody());
- auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
- ASSERT_TRUE(ImportedSpec);
- auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- ToTU, classTemplateSpecializationDecl(hasName("X")));
- EXPECT_EQ(ImportedSpec, ToSpec);
- EXPECT_TRUE(ToFun->hasBody());
-}
-
-TEST_P(ASTImporterTestBase,
- ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
- std::string ClassTemplate =
- R"(
- template <typename T>
- struct X {};
- )";
- Decl *ToTU = getToTuDecl(ClassTemplate +
- R"(
- template <>
- struct X<char> {
- int a;
- };
- void foo() {
- X<char> x;
- }
- )",
- Lang_CXX11);
- Decl *FromTU = getTuDecl(ClassTemplate +
- R"(
- template <>
- struct X<char> {
- int b;
- };
- void foo() {
- X<char> x;
- }
- )",
- Lang_CXX11);
- auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, classTemplateSpecializationDecl(hasName("X")));
- auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
-
- // We expect one (ODR) warning during the import.
- EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
-
- // The second specialization is different from the first, thus it violates
- // ODR, consequently we expect to keep the first specialization only, which is
- // already in the "To" context.
- EXPECT_TRUE(ImportedSpec);
- auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- ToTU, classTemplateSpecializationDecl(hasName("X")));
- EXPECT_EQ(ImportedSpec, ToSpec);
- EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
- ToTU, classTemplateSpecializationDecl()));
-}
-
-TEST_P(ASTImporterTestBase, MergeCtorOfClassTemplateSpecialization) {
- std::string ClassTemplate =
- R"(
- template <typename T>
- struct X {
- X(char) {}
- X(int) {}
- };
- )";
- Decl *ToTU = getToTuDecl(ClassTemplate +
- R"(
- void foo() {
- X<char> x('c');
- }
- )", Lang_CXX11);
- Decl *FromTU = getTuDecl(ClassTemplate +
- R"(
- void bar() {
- X<char> x(1);
- }
- )", Lang_CXX11);
- auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, classTemplateSpecializationDecl(hasName("X")));
- // Match the void(int) ctor.
- auto CtorPattern =
- cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
- hasParent(classTemplateSpecializationDecl()));
- auto *FromCtor =
- FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
- auto *ToCtor =
- FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
- ASSERT_TRUE(FromCtor->hasBody());
- ASSERT_FALSE(ToCtor->hasBody());
- auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
- ASSERT_TRUE(ImportedSpec);
- auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- ToTU, classTemplateSpecializationDecl(hasName("X")));
- EXPECT_EQ(ImportedSpec, ToSpec);
- EXPECT_TRUE(ToCtor->hasBody());
-}
-
-TEST_P(ASTImporterTestBase,
- ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
- auto Code =
- R"(
- // primary template
- template<class T1, class T2, int I>
- class A {};
-
- // partial specialization
- template<class T, int I>
- class A<T, T*, I> {};
- )";
- Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
- Decl *FromTU = getTuDecl(Code, Lang_CXX11);
- auto *FromSpec =
- FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
- FromTU, classTemplatePartialSpecializationDecl());
- auto *ToSpec =
- FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
- ToTU, classTemplatePartialSpecializationDecl());
-
- auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
- EXPECT_EQ(ImportedSpec, ToSpec);
- EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
- ToTU, classTemplatePartialSpecializationDecl()));
-}
-
-TEST_P(ASTImporterTestBase, ClassTemplateSpecializationsShouldNotBeDuplicated) {
- auto Code =
- R"(
- // primary template
- template<class T1, class T2, int I>
- class A {};
-
- // full specialization
- template<>
- class A<int, int, 1> {};
- )";
- Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
- Decl *FromTU = getTuDecl(Code, Lang_CXX11);
- auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, classTemplateSpecializationDecl());
- auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- ToTU, classTemplateSpecializationDecl());
-
- auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
- EXPECT_EQ(ImportedSpec, ToSpec);
- EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
- ToTU, classTemplateSpecializationDecl()));
-}
-
-TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
- std::string PrimaryTemplate =
- R"(
- template<class T1, class T2, int I>
- class A {};
- )";
- auto PartialSpec =
- R"(
- template<class T, int I>
- class A<T, T*, I> {};
- )";
- auto FullSpec =
- R"(
- template<>
- class A<int, int, 1> {};
- )";
- Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
- Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
- auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, classTemplateSpecializationDecl());
-
- auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
- EXPECT_TRUE(ImportedSpec);
- // Check the number of partial specializations.
- EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
- ToTU, classTemplatePartialSpecializationDecl()));
- // Check the number of full specializations.
- EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
- ToTU, classTemplateSpecializationDecl(
- unless(classTemplatePartialSpecializationDecl()))));
-}
-
-TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
- Decl *TU = getTuDecl(
- R"(
- const int &init();
- void foo() { const int &a{init()}; }
- )", Lang_CXX11, "input0.cc");
- auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
- ASSERT_TRUE(FromD->getAnyInitializer());
- auto *InitExpr = FromD->getAnyInitializer();
- ASSERT_TRUE(InitExpr);
- ASSERT_TRUE(InitExpr->isGLValue());
-
- auto *ToD = Import(FromD, Lang_CXX11);
- EXPECT_TRUE(ToD);
- auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
- EXPECT_TRUE(ToInitExpr);
- EXPECT_TRUE(ToInitExpr->isGLValue());
-}
-
-struct ImportVariables : ASTImporterTestBase {};
-
-TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
- Decl *FromTU = getTuDecl(
- R"(
- struct A {
- static const int a = 1 + 2;
- };
- const int A::a;
- )", Lang_CXX, "input1.cc");
-
- auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
- FromTU, varDecl(hasName("a"))); // Decl with init
- auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
- FromTU, varDecl(hasName("a"))); // Decl with definition
- ASSERT_NE(FromDWithInit, FromDWithDef);
- ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
-
- auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
- auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
- ASSERT_TRUE(ToD0);
- ASSERT_TRUE(ToD1);
- EXPECT_NE(ToD0, ToD1);
- EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
-}
-
-TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
- auto StructA =
- R"(
- struct A {
- static const int a = 1 + 2;
- };
- )";
- Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
- Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
- "input1.cc");
-
- auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
- FromTU, varDecl(hasName("a"))); // Decl with init
- auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
- FromTU, varDecl(hasName("a"))); // Decl with definition
- ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
- ASSERT_TRUE(FromDWithInit->getInit());
- ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
- ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
- ASSERT_FALSE(FromDWithDef->getInit());
-
- auto *ToD = FirstDeclMatcher<VarDecl>().match(
- ToTU, varDecl(hasName("a"))); // Decl with init
- ASSERT_TRUE(ToD->getInit());
- ASSERT_FALSE(ToD->getDefinition());
-
- auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
- EXPECT_TRUE(ImportedD->getAnyInitializer());
- EXPECT_TRUE(ImportedD->getDefinition());
-}
-
-TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
- auto StructA =
- R"(
- struct A {
- static const int a;
- };
- )";
- Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
- Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
- Lang_CXX, "input1.cc");
-
- auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
- FromTU, varDecl(hasName("a")));
- auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
- FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
- ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
- ASSERT_FALSE(FromDDeclarationOnly->getInit());
- ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
- ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
- ASSERT_TRUE(FromDWithDef->getInit());
-
- auto *ToD = FirstDeclMatcher<VarDecl>().match(
- ToTU, varDecl(hasName("a")));
- ASSERT_FALSE(ToD->getInit());
- ASSERT_FALSE(ToD->getDefinition());
-
- auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
- EXPECT_TRUE(ImportedD->getAnyInitializer());
- EXPECT_TRUE(ImportedD->getDefinition());
-}
-
-struct ImportClasses : ASTImporterTestBase {};
-
-TEST_P(ImportClasses,
- PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
- Decl *FromTU = getTuDecl("class X;", Lang_CXX);
- auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
- auto FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
-
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
- auto ToD = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == ToD);
- EXPECT_FALSE(ToD->isThisDeclarationADefinition());
-}
-
-TEST_P(ImportClasses, ImportPrototypeAfterImportedPrototype) {
- Decl *FromTU = getTuDecl("class X; class X;", Lang_CXX);
- auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
- auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
- auto From1 = LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
-
- Decl *Imported0 = Import(From0, Lang_CXX);
- Decl *Imported1 = Import(From1, Lang_CXX);
- Decl *ToTU = Imported0->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
- auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(Imported0 == To0);
- EXPECT_TRUE(Imported1 == To1);
- EXPECT_FALSE(To0->isThisDeclarationADefinition());
- EXPECT_FALSE(To1->isThisDeclarationADefinition());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
-}
-
-TEST_P(ImportClasses, DefinitionShouldBeImportedAsADefinition) {
- Decl *FromTU = getTuDecl("class X {};", Lang_CXX);
- auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
- auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
-
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
- EXPECT_TRUE(cast<CXXRecordDecl>(ImportedD)->isThisDeclarationADefinition());
-}
-
-TEST_P(ImportClasses, ImportPrototypeFromDifferentTUAfterImportedPrototype) {
- Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
- Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
- auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
- auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
- auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
-
- Decl *Imported0 = Import(From0, Lang_CXX);
- Decl *Imported1 = Import(From1, Lang_CXX);
- Decl *ToTU = Imported0->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
- auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(Imported0 == To0);
- EXPECT_TRUE(Imported1 == To1);
- EXPECT_FALSE(To0->isThisDeclarationADefinition());
- EXPECT_FALSE(To1->isThisDeclarationADefinition());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
-}
-
-TEST_P(ImportClasses, ImportDefinitions) {
- Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
- Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
- auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
- auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
- auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
-
- Decl *Imported0 = Import(From0, Lang_CXX);
- Decl *Imported1 = Import(From1, Lang_CXX);
- Decl *ToTU = Imported0->getTranslationUnitDecl();
-
- EXPECT_EQ(Imported0, Imported1);
- EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
- auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(Imported0 == To0);
- EXPECT_TRUE(To0->isThisDeclarationADefinition());
-}
-
-TEST_P(ImportClasses, ImportDefinitionThenPrototype) {
- Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
- Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
- auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
- auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
- auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
-
- Decl *ImportedDef = Import(FromDef, Lang_CXX);
- Decl *ImportedProto = Import(FromProto, Lang_CXX);
- Decl *ToTU = ImportedDef->getTranslationUnitDecl();
-
- EXPECT_NE(ImportedDef, ImportedProto);
- EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
- auto ToDef = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- auto ToProto = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ImportedProto == ToProto);
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
- EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
-}
-
-TEST_P(ImportClasses, ImportPrototypeThenDefinition) {
- Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
- Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
- auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
- auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
- auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
-
- Decl *ImportedProto = Import(FromProto, Lang_CXX);
- Decl *ImportedDef = Import(FromDef, Lang_CXX);
- Decl *ToTU = ImportedDef->getTranslationUnitDecl();
-
- EXPECT_NE(ImportedDef, ImportedProto);
- EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
- auto ToProto = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- auto ToDef = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ImportedProto == ToProto);
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
- EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
-}
-
-TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInToContext) {
- Decl *ToTU = getToTuDecl("struct X;", Lang_C);
- Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
- auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
- auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
- auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
-
- Decl *ImportedDef = Import(FromDef, Lang_C);
-
- EXPECT_NE(ImportedDef, ToProto);
- EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
- auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
- EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
-}
-
-TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
- Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
- Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
- auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
- auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
- auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
-
- Decl *ImportedDef = Import(FromDef, Lang_C);
-
- EXPECT_NE(ImportedDef, ToProto);
- EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
- auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
- EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
-}
-
-TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
- Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
- Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
- auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
- auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
- auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
-
- Decl *ImportedDef = Import(FromDef, Lang_CXX);
-
- EXPECT_NE(ImportedDef, ToProto);
- EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
- auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
- EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
-}
-
-TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
- Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
- Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
- auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
- auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
- auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
-
- Decl *ImportedProto = Import(FromProto, Lang_C);
- Decl *ImportedDef = Import(FromDef, Lang_C);
- Decl *ToTU = ImportedDef->getTranslationUnitDecl();
-
- EXPECT_NE(ImportedDef, ImportedProto);
- EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
- auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
- auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ImportedProto == ToProto);
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
- EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
-}
-
-struct ImportClassTemplates : ASTImporterTestBase {};
-
-TEST_P(ImportClassTemplates,
- PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
- Decl *FromTU = getTuDecl("template <class T> class X;", Lang_CXX);
- auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
- auto FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
-
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
- auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == ToD);
- ASSERT_TRUE(ToD->getTemplatedDecl());
- EXPECT_FALSE(ToD->isThisDeclarationADefinition());
-}
-
-TEST_P(ImportClassTemplates, ImportPrototypeAfterImportedPrototype) {
- Decl *FromTU = getTuDecl(
- "template <class T> class X; template <class T> class X;", Lang_CXX);
- auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
- auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
- auto From1 = LastDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
-
- Decl *Imported0 = Import(From0, Lang_CXX);
- Decl *Imported1 = Import(From1, Lang_CXX);
- Decl *ToTU = Imported0->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
- auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(Imported0 == To0);
- EXPECT_TRUE(Imported1 == To1);
- ASSERT_TRUE(To0->getTemplatedDecl());
- ASSERT_TRUE(To1->getTemplatedDecl());
- EXPECT_FALSE(To0->isThisDeclarationADefinition());
- EXPECT_FALSE(To1->isThisDeclarationADefinition());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
- EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
- To0->getTemplatedDecl());
-}
-
-TEST_P(ImportClassTemplates, DefinitionShouldBeImportedAsADefinition) {
- Decl *FromTU = getTuDecl("template <class T> class X {};", Lang_CXX);
- auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
- auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
-
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
- auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- ASSERT_TRUE(ToD->getTemplatedDecl());
- EXPECT_TRUE(ToD->isThisDeclarationADefinition());
-}
-
-TEST_P(ImportClassTemplates,
- ImportPrototypeFromDifferentTUAfterImportedPrototype) {
- Decl *FromTU0 =
- getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
- Decl *FromTU1 =
- getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
- auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
- auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
- auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
-
- Decl *Imported0 = Import(From0, Lang_CXX);
- Decl *Imported1 = Import(From1, Lang_CXX);
- Decl *ToTU = Imported0->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
- auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(Imported0 == To0);
- EXPECT_TRUE(Imported1 == To1);
- ASSERT_TRUE(To0->getTemplatedDecl());
- ASSERT_TRUE(To1->getTemplatedDecl());
- EXPECT_FALSE(To0->isThisDeclarationADefinition());
- EXPECT_FALSE(To1->isThisDeclarationADefinition());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
- EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
- To0->getTemplatedDecl());
-}
-
-TEST_P(ImportClassTemplates, ImportDefinitions) {
- Decl *FromTU0 =
- getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
- Decl *FromTU1 =
- getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
- auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
- auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
- auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
-
- Decl *Imported0 = Import(From0, Lang_CXX);
- Decl *Imported1 = Import(From1, Lang_CXX);
- Decl *ToTU = Imported0->getTranslationUnitDecl();
-
- EXPECT_EQ(Imported0, Imported1);
- EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
- auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(Imported0 == To0);
- ASSERT_TRUE(To0->getTemplatedDecl());
- EXPECT_TRUE(To0->isThisDeclarationADefinition());
-}
-
-TEST_P(ImportClassTemplates, ImportDefinitionThenPrototype) {
- Decl *FromTU0 =
- getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
- Decl *FromTU1 =
- getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
- auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
- auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
- auto FromProto =
- FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
-
- Decl *ImportedDef = Import(FromDef, Lang_CXX);
- Decl *ImportedProto = Import(FromProto, Lang_CXX);
- Decl *ToTU = ImportedDef->getTranslationUnitDecl();
-
- EXPECT_NE(ImportedDef, ImportedProto);
- EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
- auto ToDef = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- auto ToProto = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ImportedProto == ToProto);
- ASSERT_TRUE(ToDef->getTemplatedDecl());
- ASSERT_TRUE(ToProto->getTemplatedDecl());
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
- EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
- EXPECT_EQ(ToProto->getTemplatedDecl()->getPreviousDecl(),
- ToDef->getTemplatedDecl());
-}
-
-TEST_P(ImportClassTemplates, ImportPrototypeThenDefinition) {
- Decl *FromTU0 =
- getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
- Decl *FromTU1 =
- getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
- auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
- auto FromProto =
- FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
- auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
-
- Decl *ImportedProto = Import(FromProto, Lang_CXX);
- Decl *ImportedDef = Import(FromDef, Lang_CXX);
- Decl *ToTU = ImportedDef->getTranslationUnitDecl();
-
- EXPECT_NE(ImportedDef, ImportedProto);
- EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
- auto ToProto = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- auto ToDef = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedDef == ToDef);
- EXPECT_TRUE(ImportedProto == ToProto);
- ASSERT_TRUE(ToProto->getTemplatedDecl());
- ASSERT_TRUE(ToDef->getTemplatedDecl());
- EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
- EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
- EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
- EXPECT_EQ(ToDef->getTemplatedDecl()->getPreviousDecl(),
- ToProto->getTemplatedDecl());
-}
-
-struct ImportFriendClasses : ASTImporterTestBase {};
-
-TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
- Decl *FromTU = getTuDecl(
- R"(
- class A {
- template <int I> class F {};
- class X {
- template <int I> friend class F;
- };
- };
- )",
- Lang_CXX, "input0.cc");
-
- auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
- auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("F")));
-
- ASSERT_TRUE(FromClass);
- ASSERT_TRUE(FromFriendClass);
- ASSERT_NE(FromClass, FromFriendClass);
- ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
- ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
- ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
- FromClass->getDescribedClassTemplate());
-
- auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
- auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
-
- EXPECT_TRUE(ToClass);
- EXPECT_TRUE(ToFriendClass);
- EXPECT_NE(ToClass, ToFriendClass);
- EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
- EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
- EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
- ToClass->getDescribedClassTemplate());
-}
-
-TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
- Decl *FromTu = getTuDecl(
- R"(
- class declToImport {
- friend class declToImport;
- };
- )",
- Lang_CXX, "input.cc");
-
- auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTu, cxxRecordDecl(hasName("declToImport")));
- auto *ToD = Import(FromD, Lang_CXX);
- auto Pattern = cxxRecordDecl(has(friendDecl()));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
-}
-
-TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
- Decl *FromTu = getTuDecl(
- R"(
- template<class A> class declToImport {
- template<class A1> friend class declToImport;
- };
- )",
- Lang_CXX, "input.cc");
-
- auto *FromD =
- FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
- auto *ToD = Import(FromD, Lang_CXX);
-
- auto Pattern = classTemplateDecl(
- has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
-
- auto *Class =
- FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
- auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
- EXPECT_NE(Friend->getFriendDecl(), Class);
- EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
-}
-
-TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
- auto Pattern = classTemplateSpecializationDecl(hasName("X"));
-
- ClassTemplateSpecializationDecl *Imported1;
- {
- Decl *FromTU = getTuDecl("template<class T> class X;"
- "struct Y { friend class X<int>; };",
- Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, Pattern);
-
- Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
- }
- ClassTemplateSpecializationDecl *Imported2;
- {
- Decl *FromTU = getTuDecl("template<class T> class X;"
- "template<> class X<int>{};"
- "struct Z { friend class X<int>; };",
- Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, Pattern);
-
- Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
- }
-
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
- 2u);
- ASSERT_TRUE(Imported2->getPreviousDecl());
- EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
-}
-
-TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
- Decl *FromTU0 = getTuDecl(
- R"(
- class X {
- class Y;
- };
- class X::Y {
- template <typename T>
- friend class F; // The decl context of F is the global namespace.
- };
- )",
- Lang_CXX, "input0.cc");
- auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU0, classTemplateDecl(hasName("F")));
- auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
- Decl *FromTU1 = getTuDecl(
- R"(
- template <typename T>
- class F {};
- )",
- Lang_CXX, "input1.cc");
- auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU1, classTemplateDecl(hasName("F")));
- auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
- EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
- Imported1->getTemplatedDecl()->getTypeForDecl());
-}
-
-TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl("class declToImport {};", Lang_CXX,
- "class Y { friend class declToImport; };", Lang_CXX);
- auto *Imported = cast<CXXRecordDecl>(To);
-
- EXPECT_TRUE(Imported->getPreviousDecl());
-}
-
-TEST_P(ImportFriendClasses,
- ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
- Decl *ToTU = getToTuDecl(
- R"(
- class X {
- class Y;
- };
- class X::Y {
- template <typename T>
- friend class F; // The decl context of F is the global namespace.
- };
- )",
- Lang_CXX);
- auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
- ToTU, classTemplateDecl(hasName("F")));
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- class F {};
- )",
- Lang_CXX, "input0.cc");
- auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU, classTemplateDecl(hasName("F")));
- auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
- EXPECT_TRUE(ImportedDef->getPreviousDecl());
- EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
- EXPECT_EQ(ToDecl->getTemplatedDecl(),
- ImportedDef->getTemplatedDecl()->getPreviousDecl());
-}
-
-TEST_P(ImportFriendClasses,
- ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
- Decl *FromTU0 = getTuDecl(
- R"(
- class X {
- class Y;
- };
- class X::Y {
- template <typename T>
- friend class F; // The decl context of F is the global namespace.
- };
- )",
- Lang_CXX, "input0.cc");
- auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU0, classTemplateDecl(hasName("F")));
- auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
- Decl *FromTU1 = getTuDecl(
- R"(
- template <typename T>
- class F {};
- )",
- Lang_CXX, "input1.cc");
- auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU1, classTemplateDecl(hasName("F")));
- auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
- EXPECT_TRUE(ImportedDef->getPreviousDecl());
- EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
- EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
- ImportedDef->getTemplatedDecl()->getPreviousDecl());
-}
-
-TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
- Decl *FromTU0 = getTuDecl(
- R"(
- class X {
- class Y;
- };
- class X::Y {
- friend class F; // The decl context of F is the global namespace.
- };
- )",
- Lang_CXX, "input0.cc");
- auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
- QualType FT = Friend->getFriendType()->getType();
- FT = FromTU0->getASTContext().getCanonicalType(FT);
- auto *Fwd = cast<TagType>(FT)->getDecl();
- auto *ImportedFwd = Import(Fwd, Lang_CXX);
- Decl *FromTU1 = getTuDecl(
- R"(
- class F {};
- )",
- Lang_CXX, "input1.cc");
- auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU1, cxxRecordDecl(hasName("F")));
- auto *ImportedDef = Import(Definition, Lang_CXX);
- EXPECT_TRUE(ImportedDef->getPreviousDecl());
- EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
-}
-
-TEST_P(ASTImporterTestBase, FriendFunInClassTemplate) {
- auto *Code = R"(
- template <class T>
- struct X {
- friend void foo(){}
- };
- )";
- TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
- auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
- ToTU, functionDecl(hasName("foo")));
-
- TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
- auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("foo")));
- auto *ImportedFoo = Import(FromFoo, Lang_CXX);
- EXPECT_EQ(ImportedFoo, ToFoo);
-}
-
-struct DeclContextTest : ASTImporterTestBase {};
-
-TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
- Decl *TU = getTuDecl(
- R"(
- namespace NS {
-
- template <typename T>
- struct S {};
- template struct S<int>;
-
- inline namespace INS {
- template <typename T>
- struct S {};
- template struct S<int>;
- }
-
- }
- )", Lang_CXX11, "input0.cc");
- auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
- TU, namespaceDecl());
- auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- TU, classTemplateSpecializationDecl());
- ASSERT_TRUE(NS->containsDecl(Spec));
-
- NS->removeDecl(Spec);
- EXPECT_FALSE(NS->containsDecl(Spec));
-}
-
-TEST_P(DeclContextTest,
- removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
- Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
- auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
- auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
-
- // Investigate the list.
- auto *DC = A0->getDeclContext();
- ASSERT_TRUE(DC->containsDecl(A0));
- ASSERT_TRUE(DC->containsDecl(A1));
-
- // Investigate the lookup table.
- auto *Map = DC->getLookupPtr();
- ASSERT_TRUE(Map);
- auto I = Map->find(A0->getDeclName());
- ASSERT_NE(I, Map->end());
- StoredDeclsList &L = I->second;
- // The lookup table contains the most recent decl of A.
- ASSERT_NE(L.getAsDecl(), A0);
- ASSERT_EQ(L.getAsDecl(), A1);
-
- ASSERT_TRUE(L.getAsDecl());
- // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
- // The point here is to have a Vec with only one element, which is not the
- // one we are going to delete from the DC later.
- L.setHasExternalDecls();
- ASSERT_TRUE(L.getAsVector());
- ASSERT_EQ(1u, L.getAsVector()->size());
-
- // This asserts in the old implementation.
- DC->removeDecl(A0);
- EXPECT_FALSE(DC->containsDecl(A0));
-}
-
-struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
-
-TEST_P(ImportFunctionTemplateSpecializations,
- TUshouldNotContainFunctionTemplateImplicitInstantiation) {
-
- Decl *FromTU = getTuDecl(
- R"(
- template<class T>
- int f() { return 0; }
- void foo() { f<int>(); }
- )",
- Lang_CXX, "input0.cc");
-
- // Check that the function template instantiation is NOT the child of the TU.
- auto Pattern = translationUnitDecl(
- unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
-
- auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("foo")));
- ASSERT_TRUE(Import(Foo, Lang_CXX));
-
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
-}
-
-TEST_P(ImportFunctionTemplateSpecializations,
- TUshouldNotContainFunctionTemplateExplicitInstantiation) {
-
- Decl *FromTU = getTuDecl(
- R"(
- template<class T>
- int f() { return 0; }
- template int f<int>();
- )",
- Lang_CXX, "input0.cc");
-
- // Check that the function template instantiation is NOT the child of the TU.
- auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
- auto Pattern = translationUnitDecl(unless(has(Instantiation)));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
-
- ASSERT_TRUE(
- Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
-
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
-}
-
-TEST_P(ImportFunctionTemplateSpecializations,
- TUshouldContainFunctionTemplateSpecialization) {
-
- Decl *FromTU = getTuDecl(
- R"(
- template<class T>
- int f() { return 0; }
- template <> int f<int>() { return 4; }
- )",
- Lang_CXX, "input0.cc");
-
- // Check that the function template specialization is the child of the TU.
- auto Specialization =
- functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Pattern = translationUnitDecl(has(Specialization));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
-
- ASSERT_TRUE(
- Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
-
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
-}
-
-TEST_P(ImportFunctionTemplateSpecializations,
- FunctionTemplateSpecializationRedeclChain) {
-
- Decl *FromTU = getTuDecl(
- R"(
- template<class T>
- int f() { return 0; }
- template <> int f<int>() { return 4; }
- )",
- Lang_CXX, "input0.cc");
-
- auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
- hasParent(translationUnitDecl()));
- auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
- {
- auto *TU = FromTU;
- auto *SpecD = FromSpecD;
- auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
- TU, functionTemplateDecl());
- auto *FirstSpecD = *(TemplateD->spec_begin());
- ASSERT_EQ(SpecD, FirstSpecD);
- ASSERT_TRUE(SpecD->getPreviousDecl());
- ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
- ->doesThisDeclarationHaveABody());
- }
-
- ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
-
- {
- auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
- auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
- auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
- TU, functionTemplateDecl());
- auto *FirstSpecD = *(TemplateD->spec_begin());
- EXPECT_EQ(SpecD, FirstSpecD);
- ASSERT_TRUE(SpecD->getPreviousDecl());
- EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
- ->doesThisDeclarationHaveABody());
- }
-}
-
-TEST_P(ImportFunctionTemplateSpecializations,
- MatchNumberOfFunctionTemplateSpecializations) {
-
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T> constexpr int f() { return 0; }
- template <> constexpr int f<int>() { return 4; }
- void foo() {
- static_assert(f<char>() == 0, "");
- static_assert(f<int>() == 4, "");
- }
- )",
- Lang_CXX11, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("foo")));
-
- Import(FromD, Lang_CXX11);
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_EQ(
- DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
- DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
-}
-
-TEST_P(ImportFunctionTemplateSpecializations,
- ImportPrototypes) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Proto of the specialization.
- template <>
- void f<int>();
- )";
-
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
- auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(ImportedD != To1);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- // Check that they are part of the same redecl chain.
- EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
-}
-
-TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Specialization and definition.
- template <>
- void f<int>() {}
- )";
-
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
-
- auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
- ToTU, functionTemplateDecl());
- auto *FirstSpecD = *(TemplateD->spec_begin());
- EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
-}
-
-TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Specialization proto.
- template <>
- void f<int>();
- // Specialization proto.
- template <>
- void f<int>();
- )";
-
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(ImportedD != To1);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
-}
-
-TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Specialization proto.
- template <>
- void f<int>();
- // Specialization definition.
- template <>
- void f<int>() {}
- )";
-
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(ImportedD != To1);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
-}
-
-TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Specialization definition.
- template <>
- void f<int>() {}
- // Specialization proto.
- template <>
- void f<int>();
- )";
-
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
-
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(ImportedD != To1);
- EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
-}
-
-TEST_P(ASTImporterTestBase,
- ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
- {
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B;
- )",
- Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU, classTemplateDecl(hasName("B")));
-
- Import(FromD, Lang_CXX);
- }
-
- {
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B {
- void f();
- B* b;
- };
- )",
- Lang_CXX, "input1.cc");
- FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("f")));
- Import(FromD, Lang_CXX);
- auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU, classTemplateDecl(hasName("B")));
- auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
- EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
-
- // We expect no (ODR) warning during the import.
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
- }
-}
-
-TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
- // We already have an incomplete underlying type in the "To" context.
- auto Code =
- R"(
- template <typename T>
- struct S {
- void foo();
- };
- using U = S<int>;
- )";
- Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
- auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
- typedefNameDecl(hasName("U")));
- ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
-
- // The "From" context has the same typedef, but the underlying type is
- // complete this time.
- Decl *FromTU = getTuDecl(std::string(Code) +
- R"(
- void foo(U* u) {
- u->foo();
- }
- )", Lang_CXX11);
- auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
- typedefNameDecl(hasName("U")));
- ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
-
- // The imported type should be complete.
- auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
- EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
-}
-
-struct ASTImporterLookupTableTest : ASTImporterTestBase {};
-
-TEST_P(ASTImporterLookupTableTest, OneDecl) {
- auto *ToTU = getToTuDecl("int a;", Lang_CXX);
- auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
- ASTImporterLookupTable LT(*ToTU);
- auto Res = LT.lookup(ToTU, D->getDeclName());
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), D);
-}
-
-static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
- for (Decl *D : DC->decls()) {
- if (auto *ND = dyn_cast<NamedDecl>(D))
- if (ND->getDeclName() == Name)
- return ND;
- }
- return nullptr;
-}
-
-TEST_P(ASTImporterLookupTableTest,
- FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
- auto *Code = R"(
- template <class T>
- struct X {
- friend void foo(){}
- };
- )";
- TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
- auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
- ToTU, classTemplateDecl(hasName("X")));
- auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
- ToTU, functionDecl(hasName("foo")));
- DeclContext *FooDC = Foo->getDeclContext();
- DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
- ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
- ASSERT_EQ(cast<Decl>(FooDC), ToTU);
- DeclarationName FooName = Foo->getDeclName();
-
- // Cannot find in the LookupTable of its DC (TUDecl)
- SmallVector<NamedDecl *, 2> FoundDecls;
- FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
- EXPECT_EQ(FoundDecls.size(), 0u);
-
- // Cannot find in the LookupTable of its LexicalDC (X)
- FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
- EXPECT_EQ(FoundDecls.size(), 0u);
-
- // Can't find in the list of Decls of the DC.
- EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
-
- // Can't find in the list of Decls of the LexicalDC
- EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
-
- // ASTImporter specific lookup finds it.
- ASTImporterLookupTable LT(*ToTU);
- auto Res = LT.lookup(FooDC, Foo->getDeclName());
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), Foo);
-}
-
-TEST_P(ASTImporterLookupTableTest,
- FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
- TranslationUnitDecl *ToTU =
- getToTuDecl("struct A { struct Foo *p; };", Lang_C);
- auto *Foo =
- FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
- auto *A =
- FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
- DeclContext *FooDC = Foo->getDeclContext();
- DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
- ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
- ASSERT_EQ(cast<Decl>(FooDC), ToTU);
- DeclarationName FooName = Foo->getDeclName();
-
- // Cannot find in the LookupTable of its DC (TUDecl).
- SmallVector<NamedDecl *, 2> FoundDecls;
- FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
- EXPECT_EQ(FoundDecls.size(), 0u);
-
- // Cannot find in the LookupTable of its LexicalDC (A).
- FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
- EXPECT_EQ(FoundDecls.size(), 0u);
-
- // Can't find in the list of Decls of the DC.
- EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
-
- // Can find in the list of Decls of the LexicalDC.
- EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
-
- // ASTImporter specific lookup finds it.
- ASTImporterLookupTable LT(*ToTU);
- auto Res = LT.lookup(FooDC, Foo->getDeclName());
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), Foo);
-}
-
-TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
- TranslationUnitDecl *ToTU =
- getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
- DeclarationName VName = FirstDeclMatcher<VarDecl>()
- .match(ToTU, varDecl(hasName("V")))
- ->getDeclName();
- auto *A =
- FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
- auto *B =
- FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
-
- ASTImporterLookupTable LT(*ToTU);
-
- auto Res = LT.lookup(cast<DeclContext>(A), VName);
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
- ToTU, fieldDecl(hasName("V"),
- hasParent(recordDecl(hasName("A"))))));
- Res = LT.lookup(cast<DeclContext>(B), VName);
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
- ToTU, fieldDecl(hasName("V"),
- hasParent(recordDecl(hasName("B"))))));
- Res = LT.lookup(ToTU, VName);
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
- ToTU, varDecl(hasName("V"),
- hasParent(translationUnitDecl()))));
-}
-
-TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- void foo();
- void foo(int);
- void foo(int, int);
- )",
- Lang_CXX);
-
- ASTImporterLookupTable LT(*ToTU);
- auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
- auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
- DeclarationName Name = F0->getDeclName();
- auto Res = LT.lookup(ToTU, Name);
- EXPECT_EQ(Res.size(), 3u);
- EXPECT_EQ(Res.count(F0), 1u);
- EXPECT_EQ(Res.count(F2), 1u);
-}
-
-static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
- QualType Ty = FD->getFriendType()->getType();
- QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
- return cast<RecordType>(NamedTy)->getDecl();
-}
-
-TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- class Y { friend class F; };
- )",
- Lang_CXX);
-
- // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
- // So we must dig up the underlying CXXRecordDecl.
- ASTImporterLookupTable LT(*ToTU);
- auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
- const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
- auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
- ToTU, cxxRecordDecl(hasName("Y")));
-
- DeclarationName Name = RD->getDeclName();
- auto Res = LT.lookup(ToTU, Name);
- EXPECT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), RD);
-
- Res = LT.lookup(Y, Name);
- EXPECT_EQ(Res.size(), 0u);
-}
-
-TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- class Y { template <class T> friend class F; };
- )",
- Lang_CXX);
-
- ASTImporterLookupTable LT(*ToTU);
- auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
- ToTU, classTemplateDecl(hasName("F")));
- DeclarationName Name = F->getDeclName();
- auto Res = LT.lookup(ToTU, Name);
- EXPECT_EQ(Res.size(), 2u);
- EXPECT_EQ(Res.count(F), 1u);
- EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
-}
-
-TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- template <typename T>
- class F;
-
- template <typename T>
- class Y {
- friend class F<T>;
- };
- )",
- Lang_CXX);
-
- ASTImporterLookupTable LT(*ToTU);
- auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
- ToTU, classTemplateDecl(hasName("F")));
- DeclarationName Name = F->getDeclName();
- auto Res = LT.lookup(ToTU, Name);
- EXPECT_EQ(Res.size(), 2u);
- EXPECT_EQ(Res.count(F), 1u);
- EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
-}
-
-TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- template <typename T>
- class F;
-
- class Y {
- friend class F<int>;
- };
- )",
- Lang_CXX);
-
- ASTImporterLookupTable LT(*ToTU);
- auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
- ToTU, classTemplateDecl(hasName("F")));
- DeclarationName Name = F->getDeclName();
- auto Res = LT.lookup(ToTU, Name);
- ASSERT_EQ(Res.size(), 3u);
- EXPECT_EQ(Res.count(F), 1u);
- EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
- EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
-}
-
-TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- class Y { friend void F(); };
- )",
- Lang_CXX);
-
- ASTImporterLookupTable LT(*ToTU);
- auto *F =
- FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
- DeclarationName Name = F->getDeclName();
- auto Res = LT.lookup(ToTU, Name);
- EXPECT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), F);
-}
-
-TEST_P(ASTImporterLookupTableTest,
- LookupFindsDeclsInClassTemplateSpecialization) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- template <typename T>
- struct X {
- int F;
- };
- void foo() {
- X<char> xc;
- }
- )",
- Lang_CXX);
-
- ASTImporterLookupTable LT(*ToTU);
-
- auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
- ToTU, classTemplateDecl(hasName("X")));
- auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
- ToTU,
- fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
-
- auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- ToTU, classTemplateSpecializationDecl(hasName("X")));
- FieldDecl *FieldInSpec = *Spec->field_begin();
- ASSERT_TRUE(FieldInSpec);
-
- DeclarationName Name = FieldInSpec->getDeclName();
- auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
-
- SmallVector<NamedDecl *, 2> FoundDecls;
- TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- EXPECT_EQ(FoundDecls.size(), 1u);
- EXPECT_EQ(FoundDecls[0], FieldInTemplate);
-
- auto Res = LT.lookup(TemplateDC, Name);
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), FieldInTemplate);
-
- cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
- FoundDecls);
- EXPECT_EQ(FoundDecls.size(), 1u);
- EXPECT_EQ(FoundDecls[0], FieldInSpec);
-
- Res = LT.lookup(cast<DeclContext>(Spec), Name);
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), FieldInSpec);
-}
-
-TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- class Y { template <class T> friend void F(); };
- )",
- Lang_CXX);
-
- ASTImporterLookupTable LT(*ToTU);
- auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
- ToTU, functionTemplateDecl(hasName("F")));
- DeclarationName Name = F->getDeclName();
- auto Res = LT.lookup(ToTU, Name);
- EXPECT_EQ(Res.size(), 2u);
- EXPECT_EQ(Res.count(F), 1u);
- EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
-}
-
-TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- struct X;
- struct A {
- friend struct X;
- };
- struct B {
- friend struct X;
- };
- )",
- Lang_CXX);
-
- ASTImporterLookupTable LT(*ToTU);
- auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
- ToTU, cxxRecordDecl(hasName("X")));
- auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
- auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
- const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
- const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
- ASSERT_EQ(RD0, RD1);
- ASSERT_EQ(RD1, X);
-
- DeclarationName Name = X->getDeclName();
- auto Res = LT.lookup(ToTU, Name);
- EXPECT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), X);
-}
-
-TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- enum E {
- A,
- B
- };
- )",
- Lang_C);
-
- ASTImporterLookupTable LT(*ToTU);
- auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
- auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
- ToTU, enumConstantDecl(hasName("A")));
-
- DeclarationName Name = A->getDeclName();
- // Redecl context is the TU.
- ASSERT_EQ(E->getRedeclContext(), ToTU);
-
- SmallVector<NamedDecl *, 2> FoundDecls;
- // Normal lookup finds in the DC.
- E->localUncachedLookup(Name, FoundDecls);
- EXPECT_EQ(FoundDecls.size(), 1u);
-
- // Normal lookup finds in the Redecl context.
- ToTU->localUncachedLookup(Name, FoundDecls);
- EXPECT_EQ(FoundDecls.size(), 1u);
-
- // Import specific lookup finds in the DC.
- auto Res = LT.lookup(E, Name);
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), A);
-
- // Import specific lookup finds in the Redecl context.
- Res = LT.lookup(ToTU, Name);
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), A);
-}
-
-TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
- TranslationUnitDecl *ToTU = getToTuDecl(
- R"(
- namespace N {
- int A;
- }
- namespace N {
- }
- )",
- Lang_CXX);
- auto *N1 =
- LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
- auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
- DeclarationName Name = A->getDeclName();
-
- ASTImporterLookupTable LT(*ToTU);
- auto Res = LT.lookup(N1, Name);
- ASSERT_EQ(Res.size(), 1u);
- EXPECT_EQ(*Res.begin(), A);
-}
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
- ::testing::Values(ArgVector()), );
-
-INSTANTIATE_TEST_CASE_P(
- ParameterizedTests, CanonicalRedeclChain,
- ::testing::Values(ArgVector()),);
-
-auto DefaultTestValuesForRunOptions = ::testing::Values(
- ArgVector(),
- ArgVector{"-fdelayed-template-parsing"},
- ArgVector{"-fms-compatibility"},
- ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplates,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests,
- ImportFunctionTemplateSpecializations,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
- DefaultTestValuesForRunOptions, );
-
-} // end namespace ast_matchers
-} // end namespace clang