blob: 64a1d8100810fc5669173ec175a767b563bfc15a [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Tests for the correct import of AST nodes from one AST context to another.
10//
11//===----------------------------------------------------------------------===//
12
Gabor Marton7df342a2018-12-17 12:42:12 +000013#include "clang/AST/ASTImporter.h"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +000014#include "MatchVerifier.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000015#include "clang/AST/ASTContext.h"
Gabor Marton7df342a2018-12-17 12:42:12 +000016#include "clang/AST/DeclContextInternals.h"
Gabor Marton54058b52018-12-17 13:53:12 +000017#include "clang/AST/ASTImporter.h"
18#include "clang/AST/ASTImporterLookupTable.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000019#include "clang/ASTMatchers/ASTMatchFinder.h"
20#include "clang/ASTMatchers/ASTMatchers.h"
21#include "clang/Tooling/Tooling.h"
Peter Szecsidedda6f2018-03-30 22:03:29 +000022
23#include "DeclMatcher.h"
Gabor Marton1f667532018-05-24 08:41:07 +000024#include "Language.h"
Gabor Marton5254e642018-06-27 13:32:50 +000025#include "gmock/gmock.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000026#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000027
28namespace clang {
29namespace ast_matchers {
30
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000031using internal::Matcher;
32using internal::BindableMatcher;
33using llvm::StringMap;
34
Peter Szecsidedda6f2018-03-30 22:03:29 +000035// Creates a virtual file and assigns that to the context of given AST. If the
36// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000037static void
38createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
39 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000040 assert(ToAST);
41 ASTContext &ToCtx = ToAST->getASTContext();
Jonas Devliegherefc514902018-10-10 13:27:25 +000042 auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
Peter Szecsidedda6f2018-03-30 22:03:29 +000043 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
Jonas Devliegherefc514902018-10-10 13:27:25 +000044 auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
45 OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000046 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000047}
48
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000049static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
50 StringRef Code) {
51 return createVirtualFileIfNeeded(ToAST, FileName,
52 llvm::MemoryBuffer::getMemBuffer(Code));
53}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000054
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000055const StringRef DeclToImportID = "declToImport";
56const StringRef DeclToVerifyID = "declToVerify";
57
Gabor Marton19f4f392018-06-25 13:04:37 +000058// Common base for the different families of ASTImporter tests that are
59// parameterized on the compiler options which may result a different AST. E.g.
60// -fms-compatibility or -fdelayed-template-parsing.
61struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000062
Gabor Marton19f4f392018-06-25 13:04:37 +000063 // Returns the argument vector used for a specific language option, this set
64 // can be tweaked by the test parameters.
65 ArgVector getArgVectorForLanguage(Language Lang) const {
66 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
67 ArgVector ExtraArgs = GetParam();
68 for (const auto &Arg : ExtraArgs) {
69 Args.push_back(Arg);
70 }
71 return Args;
72 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000073
Gabor Marton19f4f392018-06-25 13:04:37 +000074};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000075
Gabor Marton19f4f392018-06-25 13:04:37 +000076// Base class for those tests which use the family of `testImport` functions.
77class TestImportBase : public ParameterizedTestsFixture {
Adam Baloghe4192a82018-06-15 06:45:39 +000078
Gabor Marton19f4f392018-06-25 13:04:37 +000079 template <typename NodeType>
80 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
81 NodeType Node) {
82 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000083
Gabor Marton19f4f392018-06-25 13:04:37 +000084 // Add 'From' file to virtual file system so importer can 'find' it
85 // while importing SourceLocations. It is safe to add same file multiple
86 // times - it just isn't replaced.
87 StringRef FromFileName = From->getMainFileName();
88 createVirtualFileIfNeeded(To, FromFileName,
89 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000090
Gabor Marton19f4f392018-06-25 13:04:37 +000091 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000092
Gabor Marton19f4f392018-06-25 13:04:37 +000093 // This should dump source locations and assert if some source locations
94 // were not imported.
95 SmallString<1024> ImportChecker;
96 llvm::raw_svector_ostream ToNothing(ImportChecker);
97 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000098
Gabor Marton19f4f392018-06-25 13:04:37 +000099 // This traverses the AST to catch certain bugs like poorly or not
100 // implemented subtrees.
101 Imported->dump(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000102
Gabor Marton19f4f392018-06-25 13:04:37 +0000103 return Imported;
104 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000105
Gabor Marton19f4f392018-06-25 13:04:37 +0000106 template <typename NodeType>
107 testing::AssertionResult
108 testImport(const std::string &FromCode, const ArgVector &FromArgs,
109 const std::string &ToCode, const ArgVector &ToArgs,
110 MatchVerifier<NodeType> &Verifier,
111 const BindableMatcher<NodeType> &SearchMatcher,
112 const BindableMatcher<NodeType> &VerificationMatcher) {
113 const char *const InputFileName = "input.cc";
114 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000115
Gabor Marton19f4f392018-06-25 13:04:37 +0000116 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
117 FromCode, FromArgs, InputFileName),
118 ToAST = tooling::buildASTFromCodeWithArgs(
119 ToCode, ToArgs, OutputFileName);
120
121 ASTContext &FromCtx = FromAST->getASTContext(),
122 &ToCtx = ToAST->getASTContext();
123
124 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
125 FromAST->getFileManager(), false);
126
127 auto FoundNodes = match(SearchMatcher, FromCtx);
128 if (FoundNodes.size() != 1)
129 return testing::AssertionFailure()
130 << "Multiple potential nodes were found!";
131
132 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
133 if (!ToImport)
134 return testing::AssertionFailure() << "Node type mismatch!";
135
136 // Sanity check: the node being imported should match in the same way as
137 // the result node.
138 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
139 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
140
141 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
142 if (!Imported)
143 return testing::AssertionFailure() << "Import failed, nullptr returned!";
144
Bill Wendling8003edc2018-11-09 00:41:36 +0000145
Gabor Marton19f4f392018-06-25 13:04:37 +0000146 return Verifier.match(Imported, WrapperMatcher);
147 }
148
149 template <typename NodeType>
150 testing::AssertionResult
151 testImport(const std::string &FromCode, const ArgVector &FromArgs,
152 const std::string &ToCode, const ArgVector &ToArgs,
153 MatchVerifier<NodeType> &Verifier,
154 const BindableMatcher<NodeType> &VerificationMatcher) {
155 return testImport(
156 FromCode, FromArgs, ToCode, ToArgs, Verifier,
157 translationUnitDecl(
158 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
159 VerificationMatcher);
160 }
161
162public:
163
164 /// Test how AST node named "declToImport" located in the translation unit
165 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
166 /// The verification is done by running AMatcher over the imported node.
167 template <typename NodeType, typename MatcherType>
168 void testImport(const std::string &FromCode, Language FromLang,
169 const std::string &ToCode, Language ToLang,
170 MatchVerifier<NodeType> &Verifier,
171 const MatcherType &AMatcher) {
172 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
173 ToArgs = getArgVectorForLanguage(ToLang);
174 EXPECT_TRUE(
175 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
176 }
177
178 struct ImportAction {
179 StringRef FromFilename;
180 StringRef ToFilename;
181 // FIXME: Generalize this to support other node kinds.
182 BindableMatcher<Decl> ImportPredicate;
183
184 ImportAction(StringRef FromFilename, StringRef ToFilename,
185 DeclarationMatcher ImportPredicate)
186 : FromFilename(FromFilename), ToFilename(ToFilename),
187 ImportPredicate(ImportPredicate) {}
188
189 ImportAction(StringRef FromFilename, StringRef ToFilename,
190 const std::string &DeclName)
191 : FromFilename(FromFilename), ToFilename(ToFilename),
192 ImportPredicate(namedDecl(hasName(DeclName))) {}
193 };
194
195 using SingleASTUnit = std::unique_ptr<ASTUnit>;
196 using AllASTUnits = StringMap<SingleASTUnit>;
197
198 struct CodeEntry {
199 std::string CodeSample;
200 Language Lang;
201 };
202
203 using CodeFiles = StringMap<CodeEntry>;
204
205 /// Builds an ASTUnit for one potential compile options set.
206 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
207 ArgVector Args = getArgVectorForLanguage(CE.Lang);
208 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
209 EXPECT_TRUE(AST.get());
210 return AST;
211 }
212
213 /// Test an arbitrary sequence of imports for a set of given in-memory files.
214 /// The verification is done by running VerificationMatcher against a
215 /// specified AST node inside of one of given files.
216 /// \param CodeSamples Map whose key is the file name and the value is the
217 /// file content.
218 /// \param ImportActions Sequence of imports. Each import in sequence
219 /// specifies "from file" and "to file" and a matcher that is used for
220 /// searching a declaration for import in "from file".
221 /// \param FileForFinalCheck Name of virtual file for which the final check is
222 /// applied.
223 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
224 /// FileForFinalCheck for which the verification will be done.
225 /// \param VerificationMatcher Matcher that will be used for verification
226 /// after all imports in sequence are done.
227 void testImportSequence(const CodeFiles &CodeSamples,
228 const std::vector<ImportAction> &ImportActions,
229 StringRef FileForFinalCheck,
230 BindableMatcher<Decl> FinalSelectPredicate,
231 BindableMatcher<Decl> VerificationMatcher) {
232 AllASTUnits AllASTs;
233 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
234 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
235
236 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
237 if (!AllASTs.count(Filename)) {
238 auto Found = CodeSamples.find(Filename);
239 assert(Found != CodeSamples.end() && "Wrong file for import!");
240 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
241 }
242 };
243
244 for (const ImportAction &Action : ImportActions) {
245 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
246 GenASTsIfNeeded(FromFile);
247 GenASTsIfNeeded(ToFile);
248
249 ASTUnit *From = AllASTs[FromFile].get();
250 ASTUnit *To = AllASTs[ToFile].get();
251
252 // Create a new importer if needed.
253 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
254 if (!ImporterRef)
255 ImporterRef.reset(new ASTImporter(
256 To->getASTContext(), To->getFileManager(), From->getASTContext(),
257 From->getFileManager(), false));
258
259 // Find the declaration and import it.
260 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
261 From->getASTContext());
262 EXPECT_TRUE(FoundDecl.size() == 1);
263 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
264 auto Imported = importNode(From, To, *ImporterRef, ToImport);
265 EXPECT_TRUE(Imported);
266 }
267
268 // Find the declaration and import it.
269 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
270 AllASTs[FileForFinalCheck]->getASTContext());
271 EXPECT_TRUE(FoundDecl.size() == 1);
272 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
273 MatchVerifier<Decl> Verifier;
274 EXPECT_TRUE(
275 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
276 }
277};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000278
Gabor Martonf086fa82018-07-17 12:06:36 +0000279template <typename T> RecordDecl *getRecordDecl(T *D) {
280 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
281 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000282}
Gabor Martonf086fa82018-07-17 12:06:36 +0000283
Peter Szecsidedda6f2018-03-30 22:03:29 +0000284// This class provides generic methods to write tests which can check internal
Balazs Keri21f938c2018-07-02 14:14:07 +0000285// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000286// this fixture makes it possible to import from several "From" contexts.
Gabor Marton19f4f392018-06-25 13:04:37 +0000287class ASTImporterTestBase : public ParameterizedTestsFixture {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000288
289 const char *const InputFileName = "input.cc";
290 const char *const OutputFileName = "output.cc";
291
292 // Buffer for the To context, must live in the test scope.
293 std::string ToCode;
294
Gabor Marton26f72a92018-07-12 09:42:05 +0000295 // Represents a "From" translation unit and holds an importer object which we
296 // use to import from this translation unit.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000297 struct TU {
298 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000299 std::string Code;
300 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000301 std::unique_ptr<ASTUnit> Unit;
302 TranslationUnitDecl *TUDecl = nullptr;
Gabor Marton26f72a92018-07-12 09:42:05 +0000303 std::unique_ptr<ASTImporter> Importer;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000304 TU(StringRef Code, StringRef FileName, ArgVector Args)
305 : Code(Code), FileName(FileName),
306 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
307 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000308 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
309 Unit->enableSourceFileDiagnostics();
310 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000311
Gabor Marton54058b52018-12-17 13:53:12 +0000312 void lazyInitImporter(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST) {
Gabor Marton26f72a92018-07-12 09:42:05 +0000313 assert(ToAST);
314 if (!Importer) {
Gabor Marton54058b52018-12-17 13:53:12 +0000315 Importer.reset(
316 new ASTImporter(ToAST->getASTContext(), ToAST->getFileManager(),
317 Unit->getASTContext(), Unit->getFileManager(),
318 false, &LookupTable));
Gabor Marton26f72a92018-07-12 09:42:05 +0000319 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000320 assert(&ToAST->getASTContext() == &Importer->getToContext());
321 createVirtualFileIfNeeded(ToAST, FileName, Code);
322 }
323
Gabor Marton54058b52018-12-17 13:53:12 +0000324 Decl *import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
325 Decl *FromDecl) {
326 lazyInitImporter(LookupTable, ToAST);
Gabor Marton26f72a92018-07-12 09:42:05 +0000327 return Importer->Import(FromDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000328 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000329
Gabor Marton54058b52018-12-17 13:53:12 +0000330 QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
331 QualType FromType) {
332 lazyInitImporter(LookupTable, ToAST);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000333 return Importer->Import(FromType);
Gabor Marton26f72a92018-07-12 09:42:05 +0000334 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000335 };
336
337 // We may have several From contexts and related translation units. In each
338 // AST, the buffers for the source are handled via references and are set
339 // during the creation of the AST. These references must point to a valid
340 // buffer until the AST is alive. Thus, we must use a list in order to avoid
341 // moving of the stored objects because that would mean breaking the
342 // references in the AST. By using a vector a move could happen when the
343 // vector is expanding, with the list we won't have these issues.
344 std::list<TU> FromTUs;
345
Gabor Marton54058b52018-12-17 13:53:12 +0000346 // Initialize the lookup table if not initialized already.
347 void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
348 assert(ToTU);
349 if (!LookupTablePtr)
350 LookupTablePtr = llvm::make_unique<ASTImporterLookupTable>(*ToTU);
351 }
352
353 void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000354 if (ToAST)
355 return;
356 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton54058b52018-12-17 13:53:12 +0000357 // Source code must be a valid live buffer through the tests lifetime.
358 ToCode = ToSrcCode;
Gabor Marton6e1510c2018-07-12 11:50:21 +0000359 // Build the AST from an empty file.
Gabor Marton54058b52018-12-17 13:53:12 +0000360 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000361 ToAST->enableSourceFileDiagnostics();
Gabor Marton54058b52018-12-17 13:53:12 +0000362 lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
Gabor Marton6e1510c2018-07-12 11:50:21 +0000363 }
364
365 TU *findFromTU(Decl *From) {
366 // Create a virtual file in the To Ctx which corresponds to the file from
367 // which we want to import the `From` Decl. Without this source locations
368 // will be invalid in the ToCtx.
369 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
370 return E.TUDecl == From->getTranslationUnitDecl();
371 });
372 assert(It != FromTUs.end());
373 return &*It;
374 }
375
Gabor Marton54058b52018-12-17 13:53:12 +0000376protected:
377
378 std::unique_ptr<ASTImporterLookupTable> LookupTablePtr;
379
Peter Szecsidedda6f2018-03-30 22:03:29 +0000380public:
381 // We may have several From context but only one To context.
382 std::unique_ptr<ASTUnit> ToAST;
383
Peter Szecsidedda6f2018-03-30 22:03:29 +0000384 // Creates an AST both for the From and To source code and imports the Decl
385 // of the identifier into the To context.
386 // Must not be called more than once within the same test.
387 std::tuple<Decl *, Decl *>
388 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
389 Language ToLang, StringRef Identifier = DeclToImportID) {
390 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
391 ToArgs = getArgVectorForLanguage(ToLang);
392
393 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
394 TU &FromTU = FromTUs.back();
395
Peter Szecsidedda6f2018-03-30 22:03:29 +0000396 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000397 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000398
Gabor Marton26f72a92018-07-12 09:42:05 +0000399 ASTContext &FromCtx = FromTU.Unit->getASTContext();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000400
Peter Szecsidedda6f2018-03-30 22:03:29 +0000401 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
402 assert(ImportedII && "Declaration with the given identifier "
403 "should be specified in test!");
404 DeclarationName ImportDeclName(ImportedII);
Gabor Marton54058b52018-12-17 13:53:12 +0000405 SmallVector<NamedDecl *, 1> FoundDecls;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000406 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
407 FoundDecls);
408
409 assert(FoundDecls.size() == 1);
410
Gabor Marton54058b52018-12-17 13:53:12 +0000411 Decl *Imported =
412 FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
Gabor Marton26f72a92018-07-12 09:42:05 +0000413
Peter Szecsidedda6f2018-03-30 22:03:29 +0000414 assert(Imported);
415 return std::make_tuple(*FoundDecls.begin(), Imported);
416 }
417
Gabor Marton9581c332018-05-23 13:53:36 +0000418 // Creates a TU decl for the given source code which can be used as a From
419 // context. May be called several times in a given test (with different file
420 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000421 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
422 StringRef FileName = "input.cc") {
423 assert(
424 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
425 return E.FileName == FileName;
426 }) == FromTUs.end());
427
428 ArgVector Args = getArgVectorForLanguage(Lang);
429 FromTUs.emplace_back(SrcCode, FileName, Args);
430 TU &Tu = FromTUs.back();
431
432 return Tu.TUDecl;
433 }
434
Gabor Marton9581c332018-05-23 13:53:36 +0000435 // Creates the To context with the given source code and returns the TU decl.
436 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
437 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton9581c332018-05-23 13:53:36 +0000438 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000439 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Gabor Marton9581c332018-05-23 13:53:36 +0000440 return ToAST->getASTContext().getTranslationUnitDecl();
441 }
442
Peter Szecsidedda6f2018-03-30 22:03:29 +0000443 // Import the given Decl into the ToCtx.
444 // May be called several times in a given test.
445 // The different instances of the param From may have different ASTContext.
446 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000447 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000448 TU *FromTU = findFromTU(From);
Gabor Marton54058b52018-12-17 13:53:12 +0000449 assert(LookupTablePtr);
450 return FromTU->import(*LookupTablePtr, ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000451 }
452
Gabor Marton6e1510c2018-07-12 11:50:21 +0000453 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000454 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000455 TU *FromTU = findFromTU(TUDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000456 assert(LookupTablePtr);
457 return FromTU->import(*LookupTablePtr, ToAST.get(), FromType);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000458 }
459
Peter Szecsidedda6f2018-03-30 22:03:29 +0000460 ~ASTImporterTestBase() {
461 if (!::testing::Test::HasFailure()) return;
462
463 for (auto &Tu : FromTUs) {
464 assert(Tu.Unit);
465 llvm::errs() << "FromAST:\n";
466 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
467 llvm::errs() << "\n";
468 }
469 if (ToAST) {
470 llvm::errs() << "ToAST:\n";
471 ToAST->getASTContext().getTranslationUnitDecl()->dump();
472 }
473 }
474};
475
Gabor Marton19f4f392018-06-25 13:04:37 +0000476struct ImportExpr : TestImportBase {};
477struct ImportType : TestImportBase {};
478struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000479
Gabor Marton5254e642018-06-27 13:32:50 +0000480struct CanonicalRedeclChain : ASTImporterTestBase {};
481
482TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
483 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
484 auto Pattern = functionDecl(hasName("f"));
485 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
486
487 auto Redecls = getCanonicalForwardRedeclChain(D0);
488 ASSERT_EQ(Redecls.size(), 1u);
489 EXPECT_EQ(D0, Redecls[0]);
490}
491
492TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
493 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
494 auto Pattern = functionDecl(hasName("f"));
495 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
496 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
497 FunctionDecl *D1 = D2->getPreviousDecl();
498
499 auto Redecls = getCanonicalForwardRedeclChain(D0);
500 ASSERT_EQ(Redecls.size(), 3u);
501 EXPECT_EQ(D0, Redecls[0]);
502 EXPECT_EQ(D1, Redecls[1]);
503 EXPECT_EQ(D2, Redecls[2]);
504}
505
506TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
507 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
508 auto Pattern = functionDecl(hasName("f"));
509 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
510 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
511 FunctionDecl *D1 = D2->getPreviousDecl();
512
513 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
514 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
515 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
516
517 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
518 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
519}
520
Gabor Marton19f4f392018-06-25 13:04:37 +0000521TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000522 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000523 testImport(
524 "void declToImport() { (void)\"foo\"; }",
525 Lang_CXX, "", Lang_CXX, Verifier,
526 functionDecl(hasDescendant(
527 stringLiteral(hasType(asString("const char [4]"))))));
528 testImport(
529 "void declToImport() { (void)L\"foo\"; }",
530 Lang_CXX, "", Lang_CXX, Verifier,
531 functionDecl(hasDescendant(
532 stringLiteral(hasType(asString("const wchar_t [4]"))))));
533 testImport(
534 "void declToImport() { (void) \"foo\" \"bar\"; }",
535 Lang_CXX, "", Lang_CXX, Verifier,
536 functionDecl(hasDescendant(
537 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000538}
539
Gabor Marton19f4f392018-06-25 13:04:37 +0000540TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000541 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000542 testImport(
543 "void declToImport() { (void)__null; }",
544 Lang_CXX, "", Lang_CXX, Verifier,
545 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000546}
547
Gabor Marton19f4f392018-06-25 13:04:37 +0000548TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000549 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000550 testImport(
551 "void declToImport() { (void)nullptr; }",
552 Lang_CXX11, "", Lang_CXX11, Verifier,
553 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000554}
555
556
Gabor Marton19f4f392018-06-25 13:04:37 +0000557TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000558 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000559 testImport(
560 "void declToImport() { (void)1.0; }",
561 Lang_C, "", Lang_C, Verifier,
562 functionDecl(hasDescendant(
563 floatLiteral(equals(1.0), hasType(asString("double"))))));
564 testImport(
565 "void declToImport() { (void)1.0e-5f; }",
566 Lang_C, "", Lang_C, Verifier,
567 functionDecl(hasDescendant(
568 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000569}
570
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000571TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
572 MatchVerifier<Decl> Verifier;
573 testImport(
574 "void declToImport() { (void)1.0i; }",
575 Lang_CXX14, "", Lang_CXX14, Verifier,
576 functionDecl(hasDescendant(imaginaryLiteral())));
577}
578
Gabor Marton19f4f392018-06-25 13:04:37 +0000579TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000580 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000581 testImport(
582 "void declToImport() {"
583 " struct s { int x; long y; unsigned z; }; "
584 " (void)(struct s){ 42, 0L, 1U }; }",
585 Lang_CXX, "", Lang_CXX, Verifier,
586 functionDecl(hasDescendant(
587 compoundLiteralExpr(
588 hasType(asString("struct s")),
589 has(initListExpr(
590 hasType(asString("struct s")),
591 has(integerLiteral(
592 equals(42), hasType(asString("int")))),
593 has(integerLiteral(
594 equals(0), hasType(asString("long")))),
595 has(integerLiteral(
596 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000597}
598
Gabor Marton19f4f392018-06-25 13:04:37 +0000599TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000600 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000601 testImport(
602 "class declToImport { void f() { (void)this; } };",
603 Lang_CXX, "", Lang_CXX, Verifier,
604 cxxRecordDecl(
605 hasMethod(
606 hasDescendant(
607 cxxThisExpr(
608 hasType(
609 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000610}
611
Gabor Marton19f4f392018-06-25 13:04:37 +0000612TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000613 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000614 testImport(
615 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
616 Lang_C, "", Lang_C, Verifier,
617 functionDecl(hasDescendant(
618 atomicExpr(
619 has(ignoringParenImpCasts(
620 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
621 hasType(asString("int *"))))),
622 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000623}
624
Gabor Marton19f4f392018-06-25 13:04:37 +0000625TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000626 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000627 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000628 "void declToImport() { loop: goto loop; (void)&&loop; }",
629 Lang_C, "", Lang_C, Verifier,
630 functionDecl(
631 hasDescendant(
632 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
633 hasDescendant(
634 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000635}
636
637AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
638 internal::Matcher<NamedDecl>, InnerMatcher) {
639 const NamedDecl *Template = Node.getTemplatedDecl();
640 return Template && InnerMatcher.matches(*Template, Finder, Builder);
641}
642
Gabor Marton19f4f392018-06-25 13:04:37 +0000643TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000644 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000645 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000646 "template<typename T> class dummy { void f() { dummy X(*this); } };"
647 "typedef dummy<int> declToImport;"
648 "template class dummy<int>;",
649 Lang_CXX, "", Lang_CXX, Verifier,
650 typedefDecl(hasType(templateSpecializationType(
651 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
652 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
653 hasName("f"),
654 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
655 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
656 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000657 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000658}
659
Gabor Marton19f4f392018-06-25 13:04:37 +0000660TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000661 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000662 testImport(
663 "void declToImport() { int b; switch (b) { case 1: break; } }",
664 Lang_C, "", Lang_C, Verifier,
665 functionDecl(hasDescendant(
666 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000667}
668
Gabor Marton19f4f392018-06-25 13:04:37 +0000669TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000670 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000671 testImport(
672 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
673 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000674 functionDecl(hasDescendant(
675 varDecl(
676 hasName("C"),
677 hasType(asString("int")),
678 hasInitializer(
679 stmtExpr(
680 hasAnySubstatement(declStmt(hasSingleDecl(
681 varDecl(
682 hasName("X"),
683 hasType(asString("int")),
684 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000685 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000686 hasDescendant(
687 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000688}
689
Gabor Marton19f4f392018-06-25 13:04:37 +0000690TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000691 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000692 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000693 "void declToImport() { (void)(true ? 1 : -5); }",
694 Lang_CXX, "", Lang_CXX, Verifier,
695 functionDecl(hasDescendant(
696 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000697 hasCondition(cxxBoolLiteral(equals(true))),
698 hasTrueExpression(integerLiteral(equals(1))),
699 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000700 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
701 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000702}
703
Gabor Marton19f4f392018-06-25 13:04:37 +0000704TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000705 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000706 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000707 "void declToImport() { (void)(1 ?: -5); }",
708 Lang_CXX, "", Lang_CXX, Verifier,
709 functionDecl(hasDescendant(
710 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000711 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000712 implicitCastExpr(
713 hasSourceExpression(opaqueValueExpr(
714 hasSourceExpression(integerLiteral(equals(1))))),
715 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000716 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000717 opaqueValueExpr(
718 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000719 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000720 unaryOperator(
721 hasOperatorName("-"),
722 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000723}
724
Gabor Marton19f4f392018-06-25 13:04:37 +0000725TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000726 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000727 testImport(
728 "void declToImport() {"
729 " struct point { double x; double y; };"
730 " struct point ptarray[10] = "
731 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
732 Lang_C, "", Lang_C, Verifier,
733 functionDecl(hasDescendant(
734 initListExpr(
735 has(designatedInitExpr(
736 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000737 hasDescendant(floatLiteral(equals(1.0))),
738 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000739 has(designatedInitExpr(
740 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000741 hasDescendant(floatLiteral(equals(2.0))),
742 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000743 has(designatedInitExpr(
744 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000745 hasDescendant(floatLiteral(equals(1.0))),
746 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000747}
748
Gabor Marton19f4f392018-06-25 13:04:37 +0000749TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000750 MatchVerifier<Decl> Verifier;
751 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000752 testImport(
753 "void declToImport() { (void)__func__; }",
754 Lang_CXX, "", Lang_CXX, Verifier,
755 functionDecl(hasDescendant(
756 predefinedExpr(
757 hasType(
758 asString("const char [13]")),
759 has(stringLiteral(hasType(
760 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000761}
762
Gabor Marton19f4f392018-06-25 13:04:37 +0000763TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000764 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000765 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000766 "void declToImport() {"
767 " struct point { double x; double y; };"
768 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
769 " [0].x = 1.0 }; }",
770 Lang_CXX, "", Lang_CXX, Verifier,
771 functionDecl(hasDescendant(
772 initListExpr(
773 has(
774 cxxConstructExpr(
775 requiresZeroInitialization())),
776 has(
777 initListExpr(
778 hasType(asString("struct point")),
779 has(floatLiteral(equals(1.0))),
780 has(implicitValueInitExpr(
781 hasType(asString("double")))))),
782 has(
783 initListExpr(
784 hasType(asString("struct point")),
785 has(floatLiteral(equals(2.0))),
786 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000787}
788
789
Aleksei Sidorina693b372016-09-28 10:16:56 +0000790const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
791
Gabor Marton19f4f392018-06-25 13:04:37 +0000792TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000793 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000794 testImport(
795 "void declToImport(__builtin_va_list list, ...) {"
796 " (void)__builtin_va_arg(list, int); }",
797 Lang_CXX, "", Lang_CXX, Verifier,
798 functionDecl(hasDescendant(
799 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000800}
801
Gabor Marton19f4f392018-06-25 13:04:37 +0000802TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000803 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000804 testImport(
805 "struct C {};"
806 "void declToImport() { C c = C(); }",
807 Lang_CXX, "", Lang_CXX, Verifier,
808 functionDecl(hasDescendant(
809 exprWithCleanups(has(cxxConstructExpr(
810 has(materializeTemporaryExpr(has(implicitCastExpr(
811 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000812}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000813
Gabor Marton19f4f392018-06-25 13:04:37 +0000814TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000815 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000816 testImport(
817 "void declToImport() { typedef _Atomic(int) a_int; }",
818 Lang_CXX11, "", Lang_CXX11, Verifier,
819 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000820}
821
Gabor Marton19f4f392018-06-25 13:04:37 +0000822TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000823 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000824 testImport(
825 "template <typename T> void declToImport() { };",
826 Lang_CXX, "", Lang_CXX, Verifier,
827 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000828}
829
Gabor Marton19f4f392018-06-25 13:04:37 +0000830TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000831 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000832 testImport(
833 "template <typename T> struct C { T t; };"
834 "template <typename T> void declToImport() {"
835 " C<T> d;"
836 " (void)d.t;"
837 "}"
838 "void instantiate() { declToImport<int>(); }",
839 Lang_CXX, "", Lang_CXX, Verifier,
840 functionTemplateDecl(hasDescendant(
841 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
842 testImport(
843 "template <typename T> struct C { T t; };"
844 "template <typename T> void declToImport() {"
845 " C<T> d;"
846 " (void)(&d)->t;"
847 "}"
848 "void instantiate() { declToImport<int>(); }",
849 Lang_CXX, "", Lang_CXX, Verifier,
850 functionTemplateDecl(hasDescendant(
851 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000852}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000853
Gabor Marton19f4f392018-06-25 13:04:37 +0000854TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000855 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000856 testImport(
857 "template <int K>"
858 "struct dummy { static const int i = K; };"
859 "template <int K> using dummy2 = dummy<K>;"
860 "int declToImport() { return dummy2<3>::i; }",
861 Lang_CXX11, "", Lang_CXX11, Verifier,
862 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000863 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000864 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
865}
866
867const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
868 varTemplateSpecializationDecl;
869
Gabor Marton19f4f392018-06-25 13:04:37 +0000870TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000871 MatchVerifier<Decl> Verifier;
872 testImport(
873 "template <typename T>"
874 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000875 "void declToImport() { (void)pi<int>; }",
876 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000877 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000878 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000879 unless(hasAncestor(translationUnitDecl(has(varDecl(
880 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000881}
882
Gabor Marton19f4f392018-06-25 13:04:37 +0000883TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000884 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000885 testImport(
886 "template <typename... Args>"
887 "struct dummy {"
888 " dummy(Args... args) {}"
889 " static const int i = 4;"
890 "};"
891 "int declToImport() { return dummy<int>::i; }",
892 Lang_CXX11, "", Lang_CXX11, Verifier,
893 functionDecl(hasDescendant(
894 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000895}
896
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000897const internal::VariadicDynCastAllOfMatcher<Type,
898 DependentTemplateSpecializationType>
899 dependentTemplateSpecializationType;
900
Gabor Marton19f4f392018-06-25 13:04:37 +0000901TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000902 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000903 testImport(
904 "template<typename T>"
905 "struct A;"
906 "template<typename T>"
907 "struct declToImport {"
908 " typename A<T>::template B<T> a;"
909 "};",
910 Lang_CXX, "", Lang_CXX, Verifier,
911 classTemplateDecl(has(cxxRecordDecl(has(
912 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000913}
914
915const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
916 sizeOfPackExpr;
917
Gabor Marton19f4f392018-06-25 13:04:37 +0000918TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000919 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000920 testImport(
921 "template <typename... Ts>"
922 "void declToImport() {"
923 " const int i = sizeof...(Ts);"
924 "};"
925 "void g() { declToImport<int>(); }",
926 Lang_CXX11, "", Lang_CXX11, Verifier,
927 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000928 testImport(
929 "template <typename... Ts>"
930 "using X = int[sizeof...(Ts)];"
931 "template <typename... Us>"
932 "struct Y {"
933 " X<Us..., int, double, int, Us...> f;"
934 "};"
935 "Y<float, int> declToImport;",
936 Lang_CXX11, "", Lang_CXX11, Verifier,
937 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
938 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
939}
940
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000941/// \brief Matches __builtin_types_compatible_p:
942/// GNU extension to check equivalent types
943/// Given
944/// \code
945/// __builtin_types_compatible_p(int, int)
946/// \endcode
947// will generate TypeTraitExpr <...> 'int'
948const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
949
Gabor Marton19f4f392018-06-25 13:04:37 +0000950TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000951 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000952 testImport(
953 "void declToImport() { "
954 " (void)__builtin_types_compatible_p(int, int);"
955 "}",
956 Lang_C, "", Lang_C, Verifier,
957 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000958}
959
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000960const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
961
Gabor Marton19f4f392018-06-25 13:04:37 +0000962TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000963 MatchVerifier<Decl> Verifier;
964 testImport(
965 "namespace std { class type_info {}; }"
966 "void declToImport() {"
967 " int x;"
968 " auto a = typeid(int); auto b = typeid(x);"
969 "}",
970 Lang_CXX11, "", Lang_CXX11, Verifier,
971 functionDecl(
972 hasDescendant(varDecl(
973 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
974 hasDescendant(varDecl(
975 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
976}
977
Gabor Marton19f4f392018-06-25 13:04:37 +0000978TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000979 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000980 testImport(
981 "template<typename T> struct declToImport {"
982 " void m() { (void)__is_pod(T); }"
983 "};"
984 "void f() { declToImport<int>().m(); }",
985 Lang_CXX11, "", Lang_CXX11, Verifier,
986 classTemplateDecl(has(cxxRecordDecl(has(
987 functionDecl(hasDescendant(
988 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000989}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000990
Gabor Marton6e1510c2018-07-12 11:50:21 +0000991TEST_P(ImportDecl, ImportRecordDeclInFunc) {
992 MatchVerifier<Decl> Verifier;
993 testImport("int declToImport() { "
994 " struct data_t {int a;int b;};"
995 " struct data_t d;"
996 " return 0;"
997 "}",
998 Lang_C, "", Lang_C, Verifier,
999 functionDecl(hasBody(compoundStmt(
1000 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
1001}
1002
1003TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
1004 Decl *FromTU = getTuDecl("int declToImport() { "
1005 " struct data_t {int a;int b;};"
1006 " struct data_t d;"
1007 " return 0;"
1008 "}",
1009 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +00001010 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +00001011 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
1012 ASSERT_TRUE(FromVar);
1013 auto ToType =
1014 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
1015 EXPECT_FALSE(ToType.isNull());
1016}
1017
1018TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
1019 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +00001020 Decl *FromTU = getTuDecl(
1021 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1022 Lang_C, "input.c");
1023 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1024 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001025 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001026 auto *To = Import(From, Lang_C);
1027 EXPECT_EQ(To, nullptr);
1028}
1029
1030TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncFromMacro) {
1031 Decl *FromTU = getTuDecl(
1032 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1033 "int declToImport(){ return NONAME_SIZEOF(int); }",
1034 Lang_C, "input.c");
1035 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1036 FromTU, functionDecl(hasName("declToImport")));
1037 ASSERT_TRUE(From);
1038 auto *To = Import(From, Lang_C);
1039 ASSERT_TRUE(To);
1040 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1041 To, functionDecl(hasName("declToImport"),
1042 hasDescendant(unaryExprOrTypeTraitExpr()))));
1043}
1044
1045TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParamsFromMacro) {
1046 // This construct is not supported by ASTImporter.
1047 Decl *FromTU = getTuDecl(
1048 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1049 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1050 Lang_C, "input.c");
1051 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1052 FromTU, functionDecl(hasName("declToImport")));
1053 ASSERT_TRUE(From);
1054 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001055 EXPECT_EQ(To, nullptr);
1056}
1057
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001058const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1059 cxxPseudoDestructorExpr;
1060
Gabor Marton19f4f392018-06-25 13:04:37 +00001061TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001062 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001063 testImport(
1064 "typedef int T;"
1065 "void declToImport(int *p) {"
1066 " T t;"
1067 " p->T::~T();"
1068 "}",
1069 Lang_CXX, "", Lang_CXX, Verifier,
1070 functionDecl(hasDescendant(
1071 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001072}
1073
Gabor Marton19f4f392018-06-25 13:04:37 +00001074TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001075 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001076 testImport(
1077 "namespace foo { int bar; }"
1078 "void declToImport() { using foo::bar; }",
1079 Lang_CXX, "", Lang_CXX, Verifier,
1080 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001081}
1082
1083/// \brief Matches shadow declarations introduced into a scope by a
1084/// (resolved) using declaration.
1085///
1086/// Given
1087/// \code
1088/// namespace n { int f; }
1089/// namespace declToImport { using n::f; }
1090/// \endcode
1091/// usingShadowDecl()
1092/// matches \code f \endcode
1093const internal::VariadicDynCastAllOfMatcher<Decl,
1094 UsingShadowDecl> usingShadowDecl;
1095
Gabor Marton19f4f392018-06-25 13:04:37 +00001096TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001097 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001098 testImport(
1099 "namespace foo { int bar; }"
1100 "namespace declToImport { using foo::bar; }",
1101 Lang_CXX, "", Lang_CXX, Verifier,
1102 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001103}
1104
Gabor Marton19f4f392018-06-25 13:04:37 +00001105TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001106 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001107 testImport(
1108 "template<typename T> int foo();"
1109 "template <typename T> void declToImport() {"
1110 " (void)::foo<T>;"
1111 " (void)::template foo<T>;"
1112 "}"
1113 "void instantiate() { declToImport<int>(); }",
1114 Lang_CXX, "", Lang_CXX, Verifier,
1115 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001116}
1117
Gabor Marton19f4f392018-06-25 13:04:37 +00001118TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001119 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001120 testImport(
1121 "template <typename T> struct C { T t; };"
1122 "template <typename T> void declToImport() {"
1123 " C<T> d;"
1124 " d.t = T();"
1125 "}"
1126 "void instantiate() { declToImport<int>(); }",
1127 Lang_CXX, "", Lang_CXX, Verifier,
1128 functionTemplateDecl(hasDescendant(
1129 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1130 testImport(
1131 "template <typename T> struct C { T t; };"
1132 "template <typename T> void declToImport() {"
1133 " C<T> d;"
1134 " (&d)->t = T();"
1135 "}"
1136 "void instantiate() { declToImport<int>(); }",
1137 Lang_CXX, "", Lang_CXX, Verifier,
1138 functionTemplateDecl(hasDescendant(
1139 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001140}
1141
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001142/// Check that function "declToImport()" (which is the templated function
1143/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1144/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001145TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001146 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001147 testImport(
1148 "template <typename T> void declToImport() { T a = 1; }"
1149 "void instantiate() { declToImport<int>(); }",
1150 Lang_CXX, "", Lang_CXX, Verifier,
1151 functionTemplateDecl(hasAncestor(translationUnitDecl(
1152 unless(has(functionDecl(hasName("declToImport"))))))));
1153 testImport(
1154 "template <typename T> struct declToImport { T t; };"
1155 "void instantiate() { declToImport<int>(); }",
1156 Lang_CXX, "", Lang_CXX, Verifier,
1157 classTemplateDecl(hasAncestor(translationUnitDecl(
1158 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001159}
1160
Gabor Marton19f4f392018-06-25 13:04:37 +00001161TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001162 MatchVerifier<Decl> Verifier;
1163 auto Code =
1164 R"s(
1165 struct declToImport {
1166 template <typename T0> struct X;
1167 template <typename T0> struct X<T0 *> {};
1168 };
1169 )s";
1170 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1171 recordDecl(has(classTemplateDecl()),
1172 has(classTemplateSpecializationDecl())));
1173}
1174
Gabor Marton19f4f392018-06-25 13:04:37 +00001175TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001176 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001177 testImport(
1178 "class declToImport {"
1179 " void f() { *this = declToImport(); }"
1180 "};",
1181 Lang_CXX, "", Lang_CXX, Verifier,
1182 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1183 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001184}
1185
Gabor Marton19f4f392018-06-25 13:04:37 +00001186TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001187 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001188 testImport(
1189 "template<typename T, int Size> class declToImport {"
1190 " T data[Size];"
1191 "};",
1192 Lang_CXX, "", Lang_CXX, Verifier,
1193 classTemplateDecl(has(cxxRecordDecl(
1194 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001195}
1196
Gabor Martona0df7a92018-05-30 09:19:26 +00001197TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1198 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1199 auto From =
1200 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1201 ASSERT_TRUE(From);
1202 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1203 ASSERT_TRUE(To);
1204 Decl *ToTemplated = To->getTemplatedDecl();
1205 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1206 EXPECT_TRUE(ToTemplated1);
1207 EXPECT_EQ(ToTemplated1, ToTemplated);
1208}
1209
Gabor Marton26f72a92018-07-12 09:42:05 +00001210TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001211 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1212 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1213 FromTU, functionTemplateDecl());
1214 ASSERT_TRUE(From);
1215 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1216 ASSERT_TRUE(To);
1217 Decl *ToTemplated = To->getTemplatedDecl();
1218 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1219 EXPECT_TRUE(ToTemplated1);
1220 EXPECT_EQ(ToTemplated1, ToTemplated);
1221}
1222
1223TEST_P(ASTImporterTestBase,
1224 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1225 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1226 auto FromFT =
1227 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1228 ASSERT_TRUE(FromFT);
1229
1230 auto ToTemplated =
1231 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1232 EXPECT_TRUE(ToTemplated);
1233 auto ToTU = ToTemplated->getTranslationUnitDecl();
1234 auto ToFT =
1235 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1236 EXPECT_TRUE(ToFT);
1237}
1238
1239TEST_P(ASTImporterTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001240 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001241 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1242 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1243 FromTU, functionTemplateDecl());
1244 ASSERT_TRUE(FromFT);
1245
1246 auto ToTemplated =
1247 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1248 EXPECT_TRUE(ToTemplated);
1249 auto ToTU = ToTemplated->getTranslationUnitDecl();
1250 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1251 ToTU, functionTemplateDecl());
1252 EXPECT_TRUE(ToFT);
1253}
1254
Gabor Martona0df7a92018-05-30 09:19:26 +00001255TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1256 auto Code =
1257 R"(
1258 namespace x {
1259 template<class X> struct S1{};
1260 template<class X> struct S2{};
1261 template<class X> struct S3{};
1262 }
1263 )";
1264 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1265 auto FromNs =
1266 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1267 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1268 ASSERT_TRUE(ToNs);
1269 auto From =
1270 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1271 classTemplateDecl(
1272 hasName("S2")));
1273 auto To =
1274 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1275 classTemplateDecl(
1276 hasName("S2")));
1277 ASSERT_TRUE(From);
1278 ASSERT_TRUE(To);
1279 auto ToTemplated = To->getTemplatedDecl();
1280 auto ToTemplated1 =
1281 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1282 EXPECT_TRUE(ToTemplated1);
1283 ASSERT_EQ(ToTemplated1, ToTemplated);
1284}
1285
Gabor Marton26f72a92018-07-12 09:42:05 +00001286TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001287 Decl *From, *To;
1288 std::tie(From, To) = getImportedDecl(
1289 R"(
1290 template <typename T> struct X {};
1291
1292 void declToImport(int y, X<int> &x) {}
1293
1294 template <> struct X<int> {
1295 void g() {
1296 X<int> x;
1297 declToImport(0, x);
1298 }
1299 };
1300 )",
1301 Lang_CXX, "", Lang_CXX);
1302
1303 MatchVerifier<Decl> Verifier;
1304 auto Matcher = functionDecl(hasName("declToImport"),
1305 parameterCountIs(2),
1306 hasParameter(0, hasName("y")),
1307 hasParameter(1, hasName("x")),
1308 hasParameter(1, hasType(asString("X<int> &"))));
1309 ASSERT_TRUE(Verifier.match(From, Matcher));
1310 EXPECT_TRUE(Verifier.match(To, Matcher));
1311}
1312
1313TEST_P(ASTImporterTestBase,
1314 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1315 Decl *From, *To;
1316 std::tie(From, To) =
1317 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1318 "void instantiate() { declToImport<int>(); }",
1319 Lang_CXX, "", Lang_CXX);
1320
1321 auto Check = [](Decl *D) -> bool {
1322 auto TU = D->getTranslationUnitDecl();
1323 for (auto Child : TU->decls()) {
1324 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1325 if (FD->getNameAsString() == "declToImport") {
1326 GTEST_NONFATAL_FAILURE_(
1327 "TU should not contain any FunctionDecl with name declToImport");
1328 return false;
1329 }
1330 }
1331 }
1332 return true;
1333 };
1334
1335 ASSERT_TRUE(Check(From));
1336 EXPECT_TRUE(Check(To));
1337}
1338
1339TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1340 Decl *From, *To;
1341 std::tie(From, To) =
1342 getImportedDecl("template <typename T> struct declToImport { T t; };"
1343 "void instantiate() { declToImport<int>(); }",
1344 Lang_CXX, "", Lang_CXX);
1345
1346 auto Check = [](Decl *D) -> bool {
1347 auto TU = D->getTranslationUnitDecl();
1348 for (auto Child : TU->decls()) {
1349 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1350 if (RD->getNameAsString() == "declToImport") {
1351 GTEST_NONFATAL_FAILURE_(
1352 "TU should not contain any CXXRecordDecl with name declToImport");
1353 return false;
1354 }
1355 }
1356 }
1357 return true;
1358 };
1359
1360 ASSERT_TRUE(Check(From));
1361 EXPECT_TRUE(Check(To));
1362}
1363
1364TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1365 Decl *From, *To;
1366 std::tie(From, To) =
1367 getImportedDecl(
1368 "template <typename T> struct X {};"
1369 "template <typename T> using declToImport = X<T>;"
1370 "void instantiate() { declToImport<int> a; }",
1371 Lang_CXX11, "", Lang_CXX11);
1372
1373 auto Check = [](Decl *D) -> bool {
1374 auto TU = D->getTranslationUnitDecl();
1375 for (auto Child : TU->decls()) {
1376 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1377 if (AD->getNameAsString() == "declToImport") {
1378 GTEST_NONFATAL_FAILURE_(
1379 "TU should not contain any TypeAliasDecl with name declToImport");
1380 return false;
1381 }
1382 }
1383 }
1384 return true;
1385 };
1386
1387 ASSERT_TRUE(Check(From));
1388 EXPECT_TRUE(Check(To));
1389}
1390
1391TEST_P(
1392 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001393 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001394
1395 Decl *From, *To;
1396 std::tie(From, To) = getImportedDecl(
1397 R"(
1398 template<class T>
1399 class Base {};
1400 class declToImport : public Base<declToImport> {};
1401 )",
1402 Lang_CXX, "", Lang_CXX);
1403
1404 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1405 auto Pattern =
1406 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1407 ASSERT_TRUE(
1408 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1409 EXPECT_TRUE(
1410 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1411
1412 // Check that the ClassTemplateSpecializationDecl is the child of the
1413 // ClassTemplateDecl.
1414 Pattern = translationUnitDecl(has(classTemplateDecl(
1415 hasName("Base"), has(classTemplateSpecializationDecl()))));
1416 ASSERT_TRUE(
1417 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1418 EXPECT_TRUE(
1419 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1420}
1421
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001422AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1423 size_t Index = 0;
1424 for (FieldDecl *Field : Node.fields()) {
1425 if (Index == Order.size())
1426 return false;
1427 if (Field->getName() != Order[Index])
1428 return false;
1429 ++Index;
1430 }
1431 return Index == Order.size();
1432}
1433
Peter Szecsidedda6f2018-03-30 22:03:29 +00001434TEST_P(ASTImporterTestBase,
1435 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1436 Decl *From, *To;
1437 std::tie(From, To) = getImportedDecl(
1438 R"(
1439 namespace NS {
1440 template<class T>
1441 class X {};
1442 template class X<int>;
1443 }
1444 )",
1445 Lang_CXX, "", Lang_CXX, "NS");
1446
1447 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1448 // ClassTemplateDecl.
1449 auto Pattern = namespaceDecl(has(classTemplateDecl(
1450 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1451 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1452 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1453
1454 // Check that the ClassTemplateSpecializationDecl is the child of the
1455 // NamespaceDecl.
1456 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1457 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1458 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1459}
1460
1461TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1462 Decl *From, *To;
1463 std::tie(From, To) =
1464 getImportedDecl(
1465 "struct declToImport { int a; int b; };",
1466 Lang_CXX11, "", Lang_CXX11);
1467
1468 MatchVerifier<Decl> Verifier;
1469 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1470 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1471}
1472
1473TEST_P(ASTImporterTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001474 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001475 Decl *From, *To;
1476 std::tie(From, To) = getImportedDecl(
1477 // The original recursive algorithm of ASTImporter first imports 'c' then
1478 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1479 R"s(
1480 struct declToImport {
1481 int a = c + b;
1482 int b = 1;
1483 int c = 2;
1484 };
1485 )s",
1486 Lang_CXX11, "", Lang_CXX11);
1487
1488 MatchVerifier<Decl> Verifier;
1489 ASSERT_TRUE(
1490 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1491 EXPECT_TRUE(
1492 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1493}
1494
Gabor Martonde8bf262018-05-17 09:46:07 +00001495TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001496 Decl *From, *To;
1497 std::tie(From, To) = getImportedDecl(
1498 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001499 struct declToImport {
1500 };
1501 )",
1502 Lang_CXX, "", Lang_CXX);
1503
1504 MatchVerifier<Decl> Verifier;
1505 // Match the implicit Decl.
1506 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1507 ASSERT_TRUE(Verifier.match(From, Matcher));
1508 EXPECT_TRUE(Verifier.match(To, Matcher));
1509}
1510
1511TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1512 Decl *From, *To;
1513 std::tie(From, To) = getImportedDecl(
1514 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001515 template <typename U>
1516 struct declToImport {
1517 };
1518 )",
1519 Lang_CXX, "", Lang_CXX);
1520
1521 MatchVerifier<Decl> Verifier;
1522 // Match the implicit Decl.
1523 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1524 ASSERT_TRUE(Verifier.match(From, Matcher));
1525 EXPECT_TRUE(Verifier.match(To, Matcher));
1526}
1527
1528TEST_P(
1529 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001530 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001531 Decl *From, *To;
1532 std::tie(From, To) = getImportedDecl(
1533 R"(
1534 template<class T>
1535 class Base {};
1536 class declToImport : public Base<declToImport> {};
1537 )",
1538 Lang_CXX, "", Lang_CXX);
1539
1540 auto hasImplicitClass = has(cxxRecordDecl());
1541 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1542 hasName("Base"),
1543 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1544 ASSERT_TRUE(
1545 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1546 EXPECT_TRUE(
1547 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1548}
1549
1550TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1551 Decl *From, *To;
1552 std::tie(From, To) =
1553 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1554
1555 MatchVerifier<Decl> Verifier;
1556 auto Matcher = functionDecl();
1557 ASSERT_TRUE(Verifier.match(From, Matcher));
1558 EXPECT_TRUE(Verifier.match(To, Matcher));
1559 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1560}
1561
Gabor Marton2ae9da32018-05-18 15:46:18 +00001562TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001563 Decl *FromTU = getTuDecl(
1564 R"(
1565 struct X {};
1566 void operator<<(int, X);
1567 )",
1568 Lang_CXX);
1569 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1570 const Decl *To = Import(From, Lang_CXX);
1571 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1572}
1573
1574TEST_P(ASTImporterTestBase,
1575 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1576 Decl *From, *To;
1577 std::tie(From, To) = getImportedDecl(
1578 R"(
1579 template<class T>
1580 class Base { int a; };
1581 class declToImport : Base<declToImport> {};
1582 )",
1583 Lang_CXX, "", Lang_CXX);
1584
1585 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1586 hasName("Base"),
1587 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1588 ASSERT_TRUE(
1589 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1590 EXPECT_TRUE(
1591 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1592}
1593
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001594TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1595 {
1596 Decl *FromTU = getTuDecl(
1597 R"(
1598 template <typename T>
1599 struct B;
1600 )",
1601 Lang_CXX, "input0.cc");
1602 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1603 FromTU, classTemplateDecl(hasName("B")));
1604
1605 Import(FromD, Lang_CXX);
1606 }
1607
1608 {
1609 Decl *FromTU = getTuDecl(
1610 R"(
1611 template <typename T>
1612 struct B {
1613 void f();
1614 };
1615 )",
1616 Lang_CXX, "input1.cc");
1617 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1618 FromTU, functionDecl(hasName("f")));
1619 Import(FromD, Lang_CXX);
1620 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1621 FromTU, classTemplateDecl(hasName("B")));
1622 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1623 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1624 }
1625}
1626
Gabor Marton9581c332018-05-23 13:53:36 +00001627TEST_P(ASTImporterTestBase,
1628 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1629 Decl *ToTU = getToTuDecl(
1630 R"(
1631 template <typename T>
1632 struct B {
1633 void f();
1634 };
1635
1636 template <typename T>
1637 struct B;
1638 )",
1639 Lang_CXX);
1640 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1641 [](const ClassTemplateDecl *T) {
1642 return T->isThisDeclarationADefinition();
1643 })
1644 .match(ToTU, classTemplateDecl()));
1645
1646 Decl *FromTU = getTuDecl(
1647 R"(
1648 template <typename T>
1649 struct B {
1650 void f();
1651 };
1652 )",
1653 Lang_CXX, "input1.cc");
1654 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1655 FromTU, classTemplateDecl(hasName("B")));
1656
1657 Import(FromD, Lang_CXX);
1658
1659 // We should have only one definition.
1660 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1661 [](const ClassTemplateDecl *T) {
1662 return T->isThisDeclarationADefinition();
1663 })
1664 .match(ToTU, classTemplateDecl()));
1665}
1666
1667TEST_P(ASTImporterTestBase,
1668 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1669 Decl *ToTU = getToTuDecl(
1670 R"(
1671 struct B {
1672 void f();
1673 };
1674
1675 struct B;
1676 )",
1677 Lang_CXX);
1678 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001679 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001680
1681 Decl *FromTU = getTuDecl(
1682 R"(
1683 struct B {
1684 void f();
1685 };
1686 )",
1687 Lang_CXX, "input1.cc");
1688 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1689 FromTU, cxxRecordDecl(hasName("B")));
1690
1691 Import(FromD, Lang_CXX);
1692
1693 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001694 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001695}
1696
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001697static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1698 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1699 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1700 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1701 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1702}
1703static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1704 SourceManager &SM1, SourceManager &SM2) {
1705 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1706 FullSourceLoc{ Range2.getBegin(), SM2 });
1707 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1708 FullSourceLoc{ Range2.getEnd(), SM2 });
1709}
1710TEST_P(ASTImporterTestBase, ImportSourceLocs) {
1711 Decl *FromTU = getTuDecl(
1712 R"(
1713 #define MFOO(arg) arg = arg + 1
1714
1715 void foo() {
1716 int a = 5;
1717 MFOO(a);
1718 }
1719 )",
1720 Lang_CXX);
1721 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1722 auto ToD = Import(FromD, Lang_CXX);
1723
1724 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1725 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1726 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1727 auto FromRHS =
1728 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1729
1730 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1731 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1732 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1733 FromSM);
1734 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1735 FromSM);
1736 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1737 FromSM);
1738}
1739
Rafael Stahla0010472018-07-09 08:40:17 +00001740TEST_P(ASTImporterTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001741 Decl *FromTU = getTuDecl(
1742 R"(
1743 #define FUNC_INT void declToImport
1744 #define FUNC FUNC_INT
1745 FUNC(int a);
1746 )",
1747 Lang_CXX);
1748 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1749 auto ToD = Import(FromD, Lang_CXX);
1750
1751 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1752 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1753 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1754 FromSM);
1755}
1756
Gabor Marton9581c332018-05-23 13:53:36 +00001757TEST_P(
1758 ASTImporterTestBase,
1759 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1760{
1761 Decl *ToTU = getToTuDecl(
1762 R"(
1763 template <typename T>
1764 struct B;
1765
1766 template <>
1767 struct B<int> {};
1768
1769 template <>
1770 struct B<int>;
1771 )",
1772 Lang_CXX);
1773 // We should have only one definition.
1774 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1775 [](const ClassTemplateSpecializationDecl *T) {
1776 return T->isThisDeclarationADefinition();
1777 })
1778 .match(ToTU, classTemplateSpecializationDecl()));
1779
1780 Decl *FromTU = getTuDecl(
1781 R"(
1782 template <typename T>
1783 struct B;
1784
1785 template <>
1786 struct B<int> {};
1787 )",
1788 Lang_CXX, "input1.cc");
1789 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1790 FromTU, classTemplateSpecializationDecl(hasName("B")));
1791
1792 Import(FromD, Lang_CXX);
1793
1794 // We should have only one definition.
1795 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1796 [](const ClassTemplateSpecializationDecl *T) {
1797 return T->isThisDeclarationADefinition();
1798 })
1799 .match(ToTU, classTemplateSpecializationDecl()));
1800}
1801
Gabor Marton0bebf952018-07-05 09:51:13 +00001802TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
1803 Decl *FromTU = getTuDecl(
1804 R"(
1805 struct { int a; int b; } object0 = { 2, 3 };
1806 struct { int x; int y; int z; } object1;
1807 )",
1808 Lang_CXX, "input0.cc");
1809
Gabor Marton0bebf952018-07-05 09:51:13 +00001810 auto *Obj0 =
1811 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1812 auto *From0 = getRecordDecl(Obj0);
1813 auto *Obj1 =
1814 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1815 auto *From1 = getRecordDecl(Obj1);
1816
1817 auto *To0 = Import(From0, Lang_CXX);
1818 auto *To1 = Import(From1, Lang_CXX);
1819
1820 EXPECT_TRUE(To0);
1821 EXPECT_TRUE(To1);
1822 EXPECT_NE(To0, To1);
1823 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1824}
1825
Gabor Marton7df342a2018-12-17 12:42:12 +00001826TEST_P(ASTImporterTestBase, AnonymousRecords) {
1827 auto *Code =
1828 R"(
1829 struct X {
1830 struct { int a; };
1831 struct { int b; };
1832 };
1833 )";
1834 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1835
1836 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1837
1838 auto *X0 =
1839 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1840 auto *X1 =
1841 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1842 Import(X0, Lang_C);
1843 Import(X1, Lang_C);
1844
1845 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1846 // We expect no (ODR) warning during the import.
1847 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1848 EXPECT_EQ(1u,
1849 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1850}
1851
1852TEST_P(ASTImporterTestBase, AnonymousRecordsReversed) {
1853 Decl *FromTU0 = getTuDecl(
1854 R"(
1855 struct X {
1856 struct { int a; };
1857 struct { int b; };
1858 };
1859 )",
1860 Lang_C, "input0.c");
1861
1862 Decl *FromTU1 = getTuDecl(
1863 R"(
1864 struct X { // reversed order
1865 struct { int b; };
1866 struct { int a; };
1867 };
1868 )",
1869 Lang_C, "input1.c");
1870
1871 auto *X0 =
1872 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1873 auto *X1 =
1874 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1875 Import(X0, Lang_C);
1876 Import(X1, Lang_C);
1877
1878 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1879 // We expect one (ODR) warning during the import.
1880 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1881 EXPECT_EQ(2u,
1882 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1883}
1884
Gabor Marton26f72a92018-07-12 09:42:05 +00001885TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
1886 auto Pattern = varDecl(hasName("x"));
1887 VarDecl *Imported1;
1888 {
1889 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1890 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1891 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1892 }
1893 VarDecl *Imported2;
1894 {
1895 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1896 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1897 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1898 }
1899 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1900 EXPECT_FALSE(Imported2->isUsed(false));
1901 {
1902 Decl *FromTU =
1903 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001904 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1905 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001906 Import(FromD, Lang_CXX);
1907 }
1908 EXPECT_TRUE(Imported2->isUsed(false));
1909}
1910
Gabor Martonac3a5d62018-09-17 12:04:52 +00001911TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag2) {
1912 auto Pattern = varDecl(hasName("x"));
1913 VarDecl *ExistingD;
1914 {
1915 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1916 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1917 }
1918 EXPECT_FALSE(ExistingD->isUsed(false));
1919 {
1920 Decl *FromTU = getTuDecl(
1921 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1922 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1923 FromTU, functionDecl(hasName("f")));
1924 Import(FromD, Lang_CXX);
1925 }
1926 EXPECT_TRUE(ExistingD->isUsed(false));
1927}
1928
1929TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag3) {
1930 auto Pattern = varDecl(hasName("a"));
1931 VarDecl *ExistingD;
1932 {
1933 Decl *ToTU = getToTuDecl(
1934 R"(
1935 struct A {
1936 static const int a = 1;
1937 };
1938 )", Lang_CXX);
1939 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1940 }
1941 EXPECT_FALSE(ExistingD->isUsed(false));
1942 {
1943 Decl *FromTU = getTuDecl(
1944 R"(
1945 struct A {
1946 static const int a = 1;
1947 };
1948 const int *f() { return &A::a; } // requires storage,
1949 // thus used flag will be set
1950 )", Lang_CXX, "input1.cc");
1951 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1952 FromTU, functionDecl(hasName("f")));
1953 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1954 ASSERT_TRUE(FromD->isUsed(false));
1955 Import(FromFunD, Lang_CXX);
1956 }
1957 EXPECT_TRUE(ExistingD->isUsed(false));
1958}
1959
Gabor Marton26f72a92018-07-12 09:42:05 +00001960TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
1961 auto Pattern = varDecl(hasName("x"));
1962
1963 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1964 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1965
1966 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1967
1968 ASSERT_FALSE(Imported1->isUsed(false));
1969
1970 FromD->setIsUsed();
1971 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1972
1973 EXPECT_EQ(Imported1, Imported2);
1974 EXPECT_TRUE(Imported2->isUsed(false));
1975}
1976
Peter Szecsidedda6f2018-03-30 22:03:29 +00001977struct ImportFunctions : ASTImporterTestBase {};
1978
1979TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001980 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1981 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1982 auto Pattern = functionDecl(hasName("f"));
1983 FunctionDecl *FromD = // Definition
1984 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1985
1986 Decl *ImportedD = Import(FromD, Lang_CXX);
1987 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1988
Gabor Marton5254e642018-06-27 13:32:50 +00001989 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001990 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1991}
1992
1993TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1994 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1995 auto Pattern = functionDecl(hasName("f"));
1996 FunctionDecl *FromD =
1997 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1998
1999 Decl *ImportedD = Import(FromD, Lang_CXX);
2000 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2001
2002 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2003 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
2004}
2005
Gabor Marton5254e642018-06-27 13:32:50 +00002006TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002007 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2008 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002009 auto *From =
2010 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002011
Gabor Marton5254e642018-06-27 13:32:50 +00002012 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002013 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2014
Gabor Marton5254e642018-06-27 13:32:50 +00002015 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2016 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2017 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2018 EXPECT_TRUE(ImportedD == To0);
2019 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2020 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2021 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002022}
2023
2024TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2025 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2026 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002027 auto *From =
2028 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002029
Gabor Marton5254e642018-06-27 13:32:50 +00002030 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002031 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2032
Gabor Marton5254e642018-06-27 13:32:50 +00002033 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2034 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2035 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2036 EXPECT_TRUE(ImportedD == To1);
2037 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2038 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2039 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002040}
2041
2042TEST_P(ImportFunctions, ImportPrototypes) {
2043 auto Pattern = functionDecl(hasName("f"));
2044
2045 Decl *ImportedD;
2046 {
2047 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002048 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002049
2050 ImportedD = Import(FromD, Lang_CXX);
2051 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00002052 {
2053 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002054 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2055 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002056 }
2057
Gabor Marton5254e642018-06-27 13:32:50 +00002058 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2059
2060 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2061 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2062 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2063 EXPECT_TRUE(ImportedD == To0);
2064 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2065 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2066 EXPECT_EQ(To1->getPreviousDecl(), To0);
2067}
2068
2069TEST_P(ImportFunctions, ImportDefinitions) {
2070 auto Pattern = functionDecl(hasName("f"));
2071
2072 Decl *ImportedD;
2073 {
2074 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
2075 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2076 ImportedD = Import(FromD, Lang_CXX);
2077 }
2078 {
2079 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
2080 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2081 Import(FromD, Lang_CXX);
2082 }
2083
2084 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2085
Peter Szecsidedda6f2018-03-30 22:03:29 +00002086 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00002087 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2088 EXPECT_TRUE(ImportedD == To0);
2089 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002090}
2091
2092TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
2093 auto Pattern = functionDecl(hasName("f"));
2094
2095 Decl *ImportedD;
2096 {
2097 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002098 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002099 ImportedD = Import(FromD, Lang_CXX);
2100 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00002101 {
2102 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002103 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2104 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002105 }
2106
2107 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002108
2109 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2110 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2111 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2112 EXPECT_TRUE(ImportedD == To0);
2113 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2114 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2115 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002116}
2117
2118TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
2119 auto Pattern = functionDecl(hasName("f"));
2120
2121 {
2122 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
2123 FunctionDecl *FromD =
2124 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2125
2126 Import(FromD, Lang_CXX);
2127 }
2128 {
2129 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
2130 FunctionDecl *FromD =
2131 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2132 Import(FromD, Lang_CXX);
2133 }
2134
2135 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2136 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2137 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002138 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002139 FunctionDecl *DefinitionD =
2140 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2141 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
2142 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
2143}
2144
Gabor Marton5254e642018-06-27 13:32:50 +00002145TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002146 auto Pattern = functionDecl(hasName("f"));
2147
2148 {
2149 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002150 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002151 Import(FromD, Lang_CXX);
2152 }
2153 {
2154 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002155 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002156 Import(FromD, Lang_CXX);
2157 }
2158
2159 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002160
2161 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002162 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002163 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
2164
Peter Szecsidedda6f2018-03-30 22:03:29 +00002165 FunctionDecl *DefinitionD =
2166 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2167 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00002168
2169 EXPECT_TRUE(DefinitionD->getPreviousDecl());
2170 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
2171 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002172}
2173
2174TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2175 auto Code =
2176 R"(
2177 struct B { virtual void f(); };
2178 void B::f() {}
2179 struct D : B { void f(); };
2180 )";
2181 auto Pattern =
2182 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2183 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2184 CXXMethodDecl *Proto =
2185 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2186
2187 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2188 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2189 EXPECT_EQ(To->size_overridden_methods(), 1u);
2190}
2191
2192TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2193 auto Code =
2194 R"(
2195 struct B { virtual void f(); };
2196 void B::f() {}
2197 )";
2198 auto Pattern =
2199 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2200 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2201 CXXMethodDecl *Proto =
2202 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2203 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2204
2205 ASSERT_TRUE(Proto->isVirtual());
2206 ASSERT_TRUE(Def->isVirtual());
2207 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2208 EXPECT_TRUE(To->isVirtual());
2209}
2210
Gabor Marton5254e642018-06-27 13:32:50 +00002211TEST_P(ImportFunctions,
2212 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2213 Decl *ToTU = getToTuDecl(
2214 R"(
2215 void f() {}
2216 void f();
2217 )",
2218 Lang_CXX);
2219 ASSERT_EQ(1u,
2220 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2221 return FD->doesThisDeclarationHaveABody();
2222 }).match(ToTU, functionDecl()));
2223
2224 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2225 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2226
2227 Import(FromD, Lang_CXX);
2228
2229 EXPECT_EQ(1u,
2230 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2231 return FD->doesThisDeclarationHaveABody();
2232 }).match(ToTU, functionDecl()));
2233}
2234
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002235TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2236 auto Code =
2237 R"(
2238 struct B { virtual void f(); };
2239 struct D:B { void f(); };
2240 )";
2241 auto BFP =
2242 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2243 auto DFP =
2244 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2245
2246 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2247 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2248 Import(DF, Lang_CXX);
2249
2250 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2251 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2252 Import(BF, Lang_CXX);
2253
2254 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2255
2256 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2257 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2258}
2259
2260TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2261 auto CodeWithoutDef =
2262 R"(
2263 struct B { virtual void f(); };
2264 struct D:B { void f(); };
2265 )";
2266 auto CodeWithDef =
2267 R"(
2268 struct B { virtual void f(){}; };
2269 struct D:B { void f(){}; };
2270 )";
2271 auto BFP =
2272 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2273 auto DFP =
2274 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2275 auto BFDefP = cxxMethodDecl(
2276 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2277 auto DFDefP = cxxMethodDecl(
2278 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2279 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2280
2281 {
2282 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2283 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2284 Import(FromD, Lang_CXX);
2285 }
2286 {
2287 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2288 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2289 Import(FromB, Lang_CXX);
2290 }
2291
2292 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2293
2294 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2295 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2296 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2297 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2298 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2299}
2300
2301TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2302 auto Code =
2303 R"(
2304 struct B { virtual void f(); };
2305 struct D:B { void f(); };
2306 void B::f(){};
2307 )";
2308
2309 auto BFP =
2310 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2311 auto BFDefP = cxxMethodDecl(
2312 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2313 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2314 unless(isDefinition()));
2315
2316 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2317 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2318 Import(D, Lang_CXX);
2319
2320 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2321 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2322 Import(B, Lang_CXX);
2323
2324 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2325
2326 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2327 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2328
2329 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2330 ToTU, cxxRecordDecl(hasName("B")));
2331 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2332 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2333 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2334
2335 // The definition should be out-of-class.
2336 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2337 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2338 ToBFOutOfClass->getLexicalDeclContext());
2339 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2340 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2341
2342 // Check that the redecl chain is intact.
2343 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2344}
2345
2346TEST_P(ImportFunctions,
2347 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2348 auto CodeTU0 =
2349 R"(
2350 struct B { virtual void f(); };
2351 struct D:B { void f(); };
2352 )";
2353 auto CodeTU1 =
2354 R"(
2355 struct B { virtual void f(); };
2356 struct D:B { void f(); };
2357 void B::f(){}
2358 void D::f(){}
2359 void foo(B &b, D &d) { b.f(); d.f(); }
2360 )";
2361
2362 auto BFP =
2363 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2364 auto BFDefP = cxxMethodDecl(
2365 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2366 auto DFP =
2367 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2368 auto DFDefP = cxxMethodDecl(
2369 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2370 auto FooDef = functionDecl(hasName("foo"));
2371
2372 {
2373 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2374 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2375 Import(D, Lang_CXX);
2376 }
2377
2378 {
2379 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2380 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2381 Import(Foo, Lang_CXX);
2382 }
2383
2384 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2385
2386 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2387 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2388 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2389 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2390
2391 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2392 ToTU, cxxRecordDecl(hasName("B")));
2393 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2394 ToTU, cxxRecordDecl(hasName("D")));
2395 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2396 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2397 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2398 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2399 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2400 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2401
2402 // The definition should be out-of-class.
2403 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2404 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2405 ToBFOutOfClass->getLexicalDeclContext());
2406 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2407 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2408
2409 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2410 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2411 ToDFOutOfClass->getLexicalDeclContext());
2412 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2413 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2414
2415 // Check that the redecl chain is intact.
2416 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2417 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2418}
2419
Gabor Marton5254e642018-06-27 13:32:50 +00002420struct ImportFriendFunctions : ImportFunctions {};
2421
2422TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2423 auto Pattern = functionDecl(hasName("f"));
2424
2425 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2426 "void f();",
2427 Lang_CXX,
2428 "input0.cc");
2429 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2430
2431 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2432 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2433 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2434 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2435 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2436 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2437 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2438}
2439
2440TEST_P(ImportFriendFunctions,
2441 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2442 auto Pattern = functionDecl(hasName("f"));
2443
2444 Decl *FromTU = getTuDecl("void f();"
2445 "struct X { friend void f(); };",
2446 Lang_CXX, "input0.cc");
2447 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2448
2449 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2450 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2451 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2452 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2453 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2454 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2455 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2456}
2457
2458TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2459 auto Pattern = functionDecl(hasName("f"));
2460
2461 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2462 "void f();",
2463 Lang_CXX,
2464 "input0.cc");
2465 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2466
2467 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2468 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2469 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2470 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2471 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2472 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2473 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2474}
2475
2476TEST_P(ImportFriendFunctions,
2477 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2478 auto Pattern = functionDecl(hasName("f"));
2479
2480 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2481 "void f(){}",
2482 Lang_CXX, "input0.cc");
2483 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2484
2485 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2486 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2487 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2488 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2489 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2490 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2491 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2492}
2493
Gabor Marton26f72a92018-07-12 09:42:05 +00002494// Disabled temporarily, because the new structural equivalence check
2495// (https://reviews.llvm.org/D48628) breaks it.
2496// PreviousDecl is not set because there is no structural match.
2497// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002498TEST_P(ImportFriendFunctions,
2499 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2500 auto Pattern = functionDecl(hasName("f"));
2501
2502 Decl *FromTU = getTuDecl(
2503 R"(
2504 class X;
2505 void f(X *x){}
2506 class X{
2507 friend void f(X *x);
2508 };
2509 )",
2510 Lang_CXX, "input0.cc");
2511 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2512
2513 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2514 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2515 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2516 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2517 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2518 .match(ToTU, friendDecl())
2519 ->getFriendDecl());
2520 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2521 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2522 // The parameters must refer the same type
2523 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2524 (*ImportedD->param_begin())->getOriginalType());
2525}
2526
Gabor Marton26f72a92018-07-12 09:42:05 +00002527// Disabled temporarily, because the new structural equivalence check
2528// (https://reviews.llvm.org/D48628) breaks it.
2529// PreviousDecl is not set because there is no structural match.
2530// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002531TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002532 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002533 auto Pattern = functionDecl(hasName("f"));
2534
2535 Decl *FromTU = getTuDecl(
2536 R"(
2537 class X;
2538 void f(X *x){}
2539 class X{
2540 friend void f(X *x);
2541 };
2542 )",
2543 Lang_CXX, "input0.cc");
2544 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2545
2546 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2547 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2548 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2549 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2550 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2551 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2552
2553 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2554 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2555 // The parameters must refer the same type
2556 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2557 (*ImportedD->param_begin())->getOriginalType());
2558}
2559
2560TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2561 auto Pattern = functionDecl(hasName("f"));
2562
2563 FunctionDecl *ImportedD;
2564 {
2565 Decl *FromTU =
2566 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2567 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2568 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2569 }
2570 FunctionDecl *ImportedD1;
2571 {
2572 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2573 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2574 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2575 }
2576
2577 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2578 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2579 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2580 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2581 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2582}
2583
Balazs Keri89632b82018-08-21 14:32:21 +00002584TEST_P(ImportFriendFunctions, Lookup) {
2585 auto FunctionPattern = functionDecl(hasName("f"));
2586 auto ClassPattern = cxxRecordDecl(hasName("X"));
2587
2588 TranslationUnitDecl *FromTU =
2589 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2590 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2591 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2592 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2593 {
2594 auto FromName = FromD->getDeclName();
2595 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2596 auto LookupRes = Class->noload_lookup(FromName);
2597 ASSERT_EQ(LookupRes.size(), 0u);
2598 LookupRes = FromTU->noload_lookup(FromName);
2599 ASSERT_EQ(LookupRes.size(), 1u);
2600 }
2601
2602 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2603 auto ToName = ToD->getDeclName();
2604
2605 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2606 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2607 auto LookupRes = Class->noload_lookup(ToName);
2608 EXPECT_EQ(LookupRes.size(), 0u);
2609 LookupRes = ToTU->noload_lookup(ToName);
2610 EXPECT_EQ(LookupRes.size(), 1u);
2611
2612 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2613 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2614 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2615 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2616}
2617
2618TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2619 auto FunctionPattern = functionDecl(hasName("f"));
2620 auto ClassPattern = cxxRecordDecl(hasName("X"));
2621
2622 TranslationUnitDecl *FromTU = getTuDecl(
2623 "struct X { friend void f(); };"
2624 // This proto decl makes f available to normal
2625 // lookup, otherwise it is hidden.
2626 // Normal C++ lookup (implemented in
2627 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2628 // returns the found `NamedDecl` only if the set IDNS is matched
2629 "void f();",
2630 Lang_CXX, "input0.cc");
2631 auto *FromFriend =
2632 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2633 auto *FromNormal =
2634 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2635 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2636 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2637 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2638 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2639
2640 auto FromName = FromFriend->getDeclName();
2641 auto *FromClass =
2642 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2643 auto LookupRes = FromClass->noload_lookup(FromName);
2644 ASSERT_EQ(LookupRes.size(), 0u);
2645 LookupRes = FromTU->noload_lookup(FromName);
2646 ASSERT_EQ(LookupRes.size(), 1u);
2647
2648 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2649 auto ToName = ToFriend->getDeclName();
2650
2651 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2652 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2653 LookupRes = ToClass->noload_lookup(ToName);
2654 EXPECT_EQ(LookupRes.size(), 0u);
2655 LookupRes = ToTU->noload_lookup(ToName);
2656 // Test is disabled because this result is 2.
2657 EXPECT_EQ(LookupRes.size(), 1u);
2658
2659 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2660 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2661 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2662 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2663 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2664 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2665 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2666}
2667
2668TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2669 auto FunctionPattern = functionDecl(hasName("f"));
2670 auto ClassPattern = cxxRecordDecl(hasName("X"));
2671
2672 TranslationUnitDecl *FromTU = getTuDecl(
2673 "void f();"
2674 "struct X { friend void f(); };",
2675 Lang_CXX, "input0.cc");
2676 auto *FromNormal =
2677 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2678 auto *FromFriend =
2679 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2680 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2681 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2682 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2683 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2684
2685 auto FromName = FromNormal->getDeclName();
2686 auto *FromClass =
2687 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2688 auto LookupRes = FromClass->noload_lookup(FromName);
2689 ASSERT_EQ(LookupRes.size(), 0u);
2690 LookupRes = FromTU->noload_lookup(FromName);
2691 ASSERT_EQ(LookupRes.size(), 1u);
2692
2693 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2694 auto ToName = ToNormal->getDeclName();
2695 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2696
2697 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2698 LookupRes = ToClass->noload_lookup(ToName);
2699 EXPECT_EQ(LookupRes.size(), 0u);
2700 LookupRes = ToTU->noload_lookup(ToName);
2701 EXPECT_EQ(LookupRes.size(), 1u);
2702
2703 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2704 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2705 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2706 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2707 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2708 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2709 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2710}
2711
2712TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2713 auto Pattern = functionDecl(hasName("f"));
2714
2715 TranslationUnitDecl *FromNormalTU =
2716 getTuDecl("void f();", Lang_CXX, "input0.cc");
2717 auto *FromNormalF =
2718 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2719 TranslationUnitDecl *FromFriendTU =
2720 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2721 auto *FromFriendF =
2722 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2723 auto FromNormalName = FromNormalF->getDeclName();
2724 auto FromFriendName = FromFriendF->getDeclName();
2725
2726 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2727 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2728 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2729 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2730 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2731 ASSERT_EQ(LookupRes.size(), 1u);
2732 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2733 ASSERT_EQ(LookupRes.size(), 1u);
2734
2735 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2736 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2737 auto ToName = ToNormalF->getDeclName();
2738 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2739 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2740 LookupRes = ToTU->noload_lookup(ToName);
2741 EXPECT_EQ(LookupRes.size(), 1u);
2742 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002743
Balazs Keri89632b82018-08-21 14:32:21 +00002744 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2745 LookupRes = ToTU->noload_lookup(ToName);
2746 EXPECT_EQ(LookupRes.size(), 1u);
2747 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2748
2749 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2750 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2751
2752 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2753 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2754}
2755
2756TEST_P(ImportFriendFunctions, ImportFriendList) {
2757 TranslationUnitDecl *FromTU = getTuDecl(
2758 "struct X { friend void f(); };"
2759 "void f();",
2760 Lang_CXX, "input0.cc");
2761 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2762 FromTU, functionDecl(hasName("f")));
2763
2764 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2765 FromTU, cxxRecordDecl(hasName("X")));
2766 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2767 auto FromFriends = FromClass->friends();
2768 unsigned int FrN = 0;
2769 for (auto Fr : FromFriends) {
2770 ASSERT_EQ(Fr, FromFriend);
2771 ++FrN;
2772 }
2773 ASSERT_EQ(FrN, 1u);
2774
2775 Import(FromFriendF, Lang_CXX);
2776 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2777 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2778 ToTU, cxxRecordDecl(hasName("X")));
2779 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2780 auto ToFriends = ToClass->friends();
2781 FrN = 0;
2782 for (auto Fr : ToFriends) {
2783 EXPECT_EQ(Fr, ToFriend);
2784 ++FrN;
2785 }
2786 EXPECT_EQ(FrN, 1u);
2787}
2788
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002789AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2790 InnerMatcher) {
2791 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2792 return InnerMatcher.matches(*Typedef, Finder, Builder);
2793 return false;
2794}
2795
Gabor Marton19f4f392018-06-25 13:04:37 +00002796TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002797 CodeFiles Samples{{"main.c",
2798 {"void foo();"
2799 "void moo();"
2800 "int main() { foo(); moo(); }",
2801 Lang_C}},
2802
2803 {"foo.c",
2804 {"typedef enum { THING_VALUE } thing_t;"
2805 "void conflict(thing_t type);"
2806 "void foo() { (void)THING_VALUE; }"
2807 "void conflict(thing_t type) {}",
2808 Lang_C}},
2809
2810 {"moo.c",
2811 {"typedef enum { THING_VALUE } thing_t;"
2812 "void conflict(thing_t type);"
2813 "void moo() { conflict(THING_VALUE); }",
2814 Lang_C}}};
2815
2816 auto VerificationMatcher =
2817 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2818 hasTypedefForAnonDecl(hasName("thing_t")));
2819
2820 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2821 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2822
2823 testImportSequence(
2824 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2825 // Just check that there is only one enum decl in the result AST.
2826 "main.c", enumDecl(), VerificationMatcher);
2827
2828 // For different import order, result should be the same.
2829 testImportSequence(
2830 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2831 // Check that there is only one enum decl in the result AST.
2832 "main.c", enumDecl(), VerificationMatcher);
2833}
2834
Peter Szecsice7f3182018-05-07 12:08:27 +00002835const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2836 dependentScopeDeclRefExpr;
2837
Gabor Marton19f4f392018-06-25 13:04:37 +00002838TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002839 MatchVerifier<Decl> Verifier;
2840 testImport("template <typename T> struct S { static T foo; };"
2841 "template <typename T> void declToImport() {"
2842 " (void) S<T>::foo;"
2843 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002844 "void instantiate() { declToImport<int>(); }"
2845 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002846 Lang_CXX11, "", Lang_CXX11, Verifier,
2847 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2848 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2849
2850 testImport("template <typename T> struct S {"
2851 "template<typename S> static void foo(){};"
2852 "};"
2853 "template <typename T> void declToImport() {"
2854 " S<T>::template foo<T>();"
2855 "}"
2856 "void instantiate() { declToImport<int>(); }",
2857 Lang_CXX11, "", Lang_CXX11, Verifier,
2858 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2859 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2860}
2861
2862const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2863 dependentNameType;
2864
Gabor Marton19f4f392018-06-25 13:04:37 +00002865TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002866 MatchVerifier<Decl> Verifier;
2867 testImport("template <typename T> struct declToImport {"
2868 " typedef typename T::type dependent_name;"
2869 "};",
2870 Lang_CXX11, "", Lang_CXX11, Verifier,
2871 classTemplateDecl(has(
2872 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2873}
2874
Gabor Marton19f4f392018-06-25 13:04:37 +00002875TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002876 MatchVerifier<Decl> Verifier;
2877 testImport("struct S { template <typename T> void mem(); };"
2878 "template <typename U> void declToImport() {"
2879 " S s;"
2880 " s.mem<U>();"
2881 "}"
2882 "void instantiate() { declToImport<int>(); }",
2883 Lang_CXX11, "", Lang_CXX11, Verifier,
2884 functionTemplateDecl(has(functionDecl(has(
2885 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2886}
2887
Balazs Keri1d20cc22018-07-16 12:16:39 +00002888class ImportImplicitMethods : public ASTImporterTestBase {
2889public:
2890 static constexpr auto DefaultCode = R"(
2891 struct A { int x; };
2892 void f() {
2893 A a;
2894 A a1(a);
2895 A a2(A{});
2896 a = a1;
2897 a = A{};
2898 a.~A();
2899 })";
2900
2901 template <typename MatcherType>
2902 void testImportOf(
2903 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2904 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2905 }
2906
2907 template <typename MatcherType>
2908 void testNoImportOf(
2909 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2910 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2911 }
2912
2913private:
2914 template <typename MatcherType>
2915 void test(const MatcherType &MethodMatcher,
2916 const char *Code, unsigned int ExpectedCount) {
2917 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2918
2919 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2920 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2921 ToTU, ClassMatcher);
2922
Balazs Keri2f752ba2018-07-16 14:05:18 +00002923 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002924
2925 {
2926 CXXMethodDecl *Method =
2927 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2928 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00002929 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002930 }
2931
Balazs Keri2f752ba2018-07-16 14:05:18 +00002932 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002933
2934 Decl *ImportedClass = nullptr;
2935 {
2936 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2937 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2938 FromTU, ClassMatcher);
2939 ImportedClass = Import(FromClass, Lang_CXX11);
2940 }
2941
2942 EXPECT_EQ(ToClass, ImportedClass);
2943 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2944 ExpectedCount);
2945 }
2946};
2947
2948TEST_P(ImportImplicitMethods, DefaultConstructor) {
2949 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2950}
2951
2952TEST_P(ImportImplicitMethods, CopyConstructor) {
2953 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2954}
2955
2956TEST_P(ImportImplicitMethods, MoveConstructor) {
2957 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2958}
2959
2960TEST_P(ImportImplicitMethods, Destructor) {
2961 testImportOf(cxxDestructorDecl());
2962}
2963
2964TEST_P(ImportImplicitMethods, CopyAssignment) {
2965 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2966}
2967
2968TEST_P(ImportImplicitMethods, MoveAssignment) {
2969 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2970}
2971
2972TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2973 auto Code = R"(
2974 struct A { A() { int x; } };
2975 )";
2976 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2977}
2978
2979TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2980 auto Code = R"(
2981 struct A { A() = default; };
2982 )";
2983 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2984}
2985
2986TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2987 auto Code = R"(
2988 struct A { A() = delete; };
2989 )";
2990 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2991}
2992
2993TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2994 auto Code = R"(
2995 struct A { void f() { } };
2996 )";
2997 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2998}
2999
Balazs Keric7797c42018-07-11 09:37:24 +00003000TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
3001 Decl *ToR1;
3002 {
3003 Decl *FromTU = getTuDecl(
3004 "struct A { };", Lang_CXX, "input0.cc");
3005 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3006 FromTU, cxxRecordDecl(hasName("A")));
3007
3008 ToR1 = Import(FromR, Lang_CXX);
3009 }
3010
3011 Decl *ToR2;
3012 {
3013 Decl *FromTU = getTuDecl(
3014 "struct A { };", Lang_CXX, "input1.cc");
3015 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3016 FromTU, cxxRecordDecl(hasName("A")));
3017
3018 ToR2 = Import(FromR, Lang_CXX);
3019 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003020
Balazs Keric7797c42018-07-11 09:37:24 +00003021 EXPECT_EQ(ToR1, ToR2);
3022}
3023
3024TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
3025 Decl *ToR1;
3026 {
3027 Decl *FromTU = getTuDecl(
3028 "struct A { int x; };", Lang_CXX, "input0.cc");
3029 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3030 FromTU, cxxRecordDecl(hasName("A")));
3031 ToR1 = Import(FromR, Lang_CXX);
3032 }
3033 Decl *ToR2;
3034 {
3035 Decl *FromTU = getTuDecl(
3036 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3037 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3038 FromTU, cxxRecordDecl(hasName("A")));
3039 ToR2 = Import(FromR, Lang_CXX);
3040 }
3041 EXPECT_NE(ToR1, ToR2);
3042}
3043
3044TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
3045 Decl *ToF1;
3046 {
3047 Decl *FromTU = getTuDecl(
3048 "struct A { int x; };", Lang_CXX, "input0.cc");
3049 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3050 FromTU, fieldDecl(hasName("x")));
3051 ToF1 = Import(FromF, Lang_CXX);
3052 }
3053 Decl *ToF2;
3054 {
3055 Decl *FromTU = getTuDecl(
3056 "struct A { int x; };", Lang_CXX, "input1.cc");
3057 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3058 FromTU, fieldDecl(hasName("x")));
3059 ToF2 = Import(FromF, Lang_CXX);
3060 }
3061 EXPECT_EQ(ToF1, ToF2);
3062}
3063
3064TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
3065 Decl *ToF1;
3066 {
3067 Decl *FromTU = getTuDecl(
3068 "struct A { int x; };", Lang_CXX, "input0.cc");
3069 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3070 FromTU, fieldDecl(hasName("x")));
3071 ToF1 = Import(FromF, Lang_CXX);
3072 }
3073 Decl *ToF2;
3074 {
3075 Decl *FromTU = getTuDecl(
3076 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3077 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3078 FromTU, fieldDecl(hasName("x")));
3079 ToF2 = Import(FromF, Lang_CXX);
3080 }
3081 EXPECT_NE(ToF1, ToF2);
3082}
3083
3084TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
3085 Decl *ToM1;
3086 {
3087 Decl *FromTU = getTuDecl(
3088 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3089 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3090 FromTU, functionDecl(hasName("x"), isDefinition()));
3091 ToM1 = Import(FromM, Lang_CXX);
3092 }
3093 Decl *ToM2;
3094 {
3095 Decl *FromTU = getTuDecl(
3096 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3097 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3098 FromTU, functionDecl(hasName("x"), isDefinition()));
3099 ToM2 = Import(FromM, Lang_CXX);
3100 }
3101 EXPECT_EQ(ToM1, ToM2);
3102}
3103
3104TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
3105 Decl *ToM1;
3106 {
3107 Decl *FromTU = getTuDecl(
3108 "struct A { void x(); }; void A::x() { }",
3109 Lang_CXX, "input0.cc");
3110 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3111 FromTU, functionDecl(hasName("x"), isDefinition()));
3112 ToM1 = Import(FromM, Lang_CXX);
3113 }
3114 Decl *ToM2;
3115 {
3116 Decl *FromTU = getTuDecl(
3117 "struct A { void x() const; }; void A::x() const { }",
3118 Lang_CXX, "input1.cc");
3119 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3120 FromTU, functionDecl(hasName("x"), isDefinition()));
3121 ToM2 = Import(FromM, Lang_CXX);
3122 }
3123 EXPECT_NE(ToM1, ToM2);
3124}
3125
Gabor Martonf086fa82018-07-17 12:06:36 +00003126TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
3127 Decl *FromTU = getTuDecl(
3128 R"(
3129 struct A {
3130 struct {
3131 struct A *next;
3132 } entry0;
3133 struct {
3134 struct A *next;
3135 } entry1;
3136 };
3137 )",
3138 Lang_C, "input0.cc");
3139 auto *From =
3140 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3141
3142 Import(From, Lang_C);
3143
3144 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3145 auto *Entry0 =
3146 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3147 auto *Entry1 =
3148 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3149 auto *R0 = getRecordDecl(Entry0);
3150 auto *R1 = getRecordDecl(Entry1);
3151 EXPECT_NE(R0, R1);
3152 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3153 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3154 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3155 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3156}
3157
Balazs Keri2544b4b2018-08-08 09:40:57 +00003158TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
3159 Decl *FromTU = getTuDecl(
3160 R"(
3161 void f(int X, int Y, bool Z) {
3162 (void)[X, Y, Z] { (void)Z; };
3163 }
3164 )",
3165 Lang_CXX11, "input0.cc");
3166 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3167 FromTU, functionDecl(hasName("f")));
3168 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3169 EXPECT_TRUE(ToF);
3170
3171 CXXRecordDecl *FromLambda =
3172 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3173 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3174
3175 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3176 EXPECT_TRUE(ToLambda);
3177
3178 // Check if the fields of the lambda class are imported in correct order.
3179 unsigned FromIndex = 0u;
3180 for (auto *FromField : FromLambda->fields()) {
3181 ASSERT_FALSE(FromField->getDeclName());
3182 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3183 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003184 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3185 EXPECT_TRUE(ToIndex);
3186 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003187 ++FromIndex;
3188 }
3189
3190 EXPECT_EQ(FromIndex, 3u);
3191}
3192
Gabor Marton42e15de2018-08-22 11:52:14 +00003193TEST_P(ASTImporterTestBase, MergeFieldDeclsOfClassTemplateSpecialization) {
3194 std::string ClassTemplate =
3195 R"(
3196 template <typename T>
3197 struct X {
3198 int a{0}; // FieldDecl with InitListExpr
3199 X(char) : a(3) {} // (1)
3200 X(int) {} // (2)
3201 };
3202 )";
3203 Decl *ToTU = getToTuDecl(ClassTemplate +
3204 R"(
3205 void foo() {
3206 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3207 X<char> xc('c');
3208 }
3209 )", Lang_CXX11);
3210 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3211 ToTU, classTemplateSpecializationDecl(hasName("X")));
3212 // FieldDecl without InitlistExpr:
3213 auto *ToField = *ToSpec->field_begin();
3214 ASSERT_TRUE(ToField);
3215 ASSERT_FALSE(ToField->getInClassInitializer());
3216 Decl *FromTU = getTuDecl(ClassTemplate +
3217 R"(
3218 void bar() {
3219 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3220 X<char> xc(1);
3221 }
3222 )", Lang_CXX11);
3223 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3224 FromTU, classTemplateSpecializationDecl(hasName("X")));
3225 // FieldDecl with InitlistExpr:
3226 auto *FromField = *FromSpec->field_begin();
3227 ASSERT_TRUE(FromField);
3228 ASSERT_TRUE(FromField->getInClassInitializer());
3229
3230 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3231 ASSERT_TRUE(ImportedSpec);
3232 EXPECT_EQ(ImportedSpec, ToSpec);
3233 // After the import, the FieldDecl has to be merged, thus it should have the
3234 // InitListExpr.
3235 EXPECT_TRUE(ToField->getInClassInitializer());
3236}
3237
3238TEST_P(ASTImporterTestBase, MergeFunctionOfClassTemplateSpecialization) {
3239 std::string ClassTemplate =
3240 R"(
3241 template <typename T>
3242 struct X {
3243 void f() {}
3244 void g() {}
3245 };
3246 )";
3247 Decl *ToTU = getToTuDecl(ClassTemplate +
3248 R"(
3249 void foo() {
3250 X<char> x;
3251 x.f();
3252 }
3253 )", Lang_CXX11);
3254 Decl *FromTU = getTuDecl(ClassTemplate +
3255 R"(
3256 void bar() {
3257 X<char> x;
3258 x.g();
3259 }
3260 )", Lang_CXX11);
3261 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3262 FromTU, classTemplateSpecializationDecl(hasName("X")));
3263 auto FunPattern = functionDecl(hasName("g"),
3264 hasParent(classTemplateSpecializationDecl()));
3265 auto *FromFun =
3266 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3267 auto *ToFun =
3268 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3269 ASSERT_TRUE(FromFun->hasBody());
3270 ASSERT_FALSE(ToFun->hasBody());
3271 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3272 ASSERT_TRUE(ImportedSpec);
3273 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3274 ToTU, classTemplateSpecializationDecl(hasName("X")));
3275 EXPECT_EQ(ImportedSpec, ToSpec);
3276 EXPECT_TRUE(ToFun->hasBody());
3277}
3278
3279TEST_P(ASTImporterTestBase,
3280 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3281 std::string ClassTemplate =
3282 R"(
3283 template <typename T>
3284 struct X {};
3285 )";
3286 Decl *ToTU = getToTuDecl(ClassTemplate +
3287 R"(
3288 template <>
3289 struct X<char> {
3290 int a;
3291 };
3292 void foo() {
3293 X<char> x;
3294 }
3295 )",
3296 Lang_CXX11);
3297 Decl *FromTU = getTuDecl(ClassTemplate +
3298 R"(
3299 template <>
3300 struct X<char> {
3301 int b;
3302 };
3303 void foo() {
3304 X<char> x;
3305 }
3306 )",
3307 Lang_CXX11);
3308 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3309 FromTU, classTemplateSpecializationDecl(hasName("X")));
3310 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3311
3312 // We expect one (ODR) warning during the import.
3313 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3314
3315 // The second specialization is different from the first, thus it violates
3316 // ODR, consequently we expect to keep the first specialization only, which is
3317 // already in the "To" context.
3318 EXPECT_TRUE(ImportedSpec);
3319 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3320 ToTU, classTemplateSpecializationDecl(hasName("X")));
3321 EXPECT_EQ(ImportedSpec, ToSpec);
3322 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3323 ToTU, classTemplateSpecializationDecl()));
3324}
3325
3326TEST_P(ASTImporterTestBase, MergeCtorOfClassTemplateSpecialization) {
3327 std::string ClassTemplate =
3328 R"(
3329 template <typename T>
3330 struct X {
3331 X(char) {}
3332 X(int) {}
3333 };
3334 )";
3335 Decl *ToTU = getToTuDecl(ClassTemplate +
3336 R"(
3337 void foo() {
3338 X<char> x('c');
3339 }
3340 )", Lang_CXX11);
3341 Decl *FromTU = getTuDecl(ClassTemplate +
3342 R"(
3343 void bar() {
3344 X<char> x(1);
3345 }
3346 )", Lang_CXX11);
3347 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3348 FromTU, classTemplateSpecializationDecl(hasName("X")));
3349 // Match the void(int) ctor.
3350 auto CtorPattern =
3351 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3352 hasParent(classTemplateSpecializationDecl()));
3353 auto *FromCtor =
3354 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3355 auto *ToCtor =
3356 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3357 ASSERT_TRUE(FromCtor->hasBody());
3358 ASSERT_FALSE(ToCtor->hasBody());
3359 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3360 ASSERT_TRUE(ImportedSpec);
3361 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3362 ToTU, classTemplateSpecializationDecl(hasName("X")));
3363 EXPECT_EQ(ImportedSpec, ToSpec);
3364 EXPECT_TRUE(ToCtor->hasBody());
3365}
3366
3367TEST_P(ASTImporterTestBase,
3368 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3369 auto Code =
3370 R"(
3371 // primary template
3372 template<class T1, class T2, int I>
3373 class A {};
3374
3375 // partial specialization
3376 template<class T, int I>
3377 class A<T, T*, I> {};
3378 )";
3379 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3380 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3381 auto *FromSpec =
3382 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3383 FromTU, classTemplatePartialSpecializationDecl());
3384 auto *ToSpec =
3385 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3386 ToTU, classTemplatePartialSpecializationDecl());
3387
3388 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3389 EXPECT_EQ(ImportedSpec, ToSpec);
3390 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3391 ToTU, classTemplatePartialSpecializationDecl()));
3392}
3393
3394TEST_P(ASTImporterTestBase, ClassTemplateSpecializationsShouldNotBeDuplicated) {
3395 auto Code =
3396 R"(
3397 // primary template
3398 template<class T1, class T2, int I>
3399 class A {};
3400
3401 // full specialization
3402 template<>
3403 class A<int, int, 1> {};
3404 )";
3405 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3406 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3407 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3408 FromTU, classTemplateSpecializationDecl());
3409 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3410 ToTU, classTemplateSpecializationDecl());
3411
3412 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3413 EXPECT_EQ(ImportedSpec, ToSpec);
3414 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3415 ToTU, classTemplateSpecializationDecl()));
3416}
3417
3418TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3419 std::string PrimaryTemplate =
3420 R"(
3421 template<class T1, class T2, int I>
3422 class A {};
3423 )";
3424 auto PartialSpec =
3425 R"(
3426 template<class T, int I>
3427 class A<T, T*, I> {};
3428 )";
3429 auto FullSpec =
3430 R"(
3431 template<>
3432 class A<int, int, 1> {};
3433 )";
3434 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3435 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3436 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3437 FromTU, classTemplateSpecializationDecl());
3438
3439 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3440 EXPECT_TRUE(ImportedSpec);
3441 // Check the number of partial specializations.
3442 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3443 ToTU, classTemplatePartialSpecializationDecl()));
3444 // Check the number of full specializations.
3445 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3446 ToTU, classTemplateSpecializationDecl(
3447 unless(classTemplatePartialSpecializationDecl()))));
3448}
3449
Gabor Martona20ce602018-09-03 13:10:53 +00003450TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
3451 Decl *TU = getTuDecl(
3452 R"(
3453 const int &init();
3454 void foo() { const int &a{init()}; }
3455 )", Lang_CXX11, "input0.cc");
3456 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3457 ASSERT_TRUE(FromD->getAnyInitializer());
3458 auto *InitExpr = FromD->getAnyInitializer();
3459 ASSERT_TRUE(InitExpr);
3460 ASSERT_TRUE(InitExpr->isGLValue());
3461
3462 auto *ToD = Import(FromD, Lang_CXX11);
3463 EXPECT_TRUE(ToD);
3464 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3465 EXPECT_TRUE(ToInitExpr);
3466 EXPECT_TRUE(ToInitExpr->isGLValue());
3467}
3468
Gabor Martonac3a5d62018-09-17 12:04:52 +00003469struct ImportVariables : ASTImporterTestBase {};
3470
3471TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3472 Decl *FromTU = getTuDecl(
3473 R"(
3474 struct A {
3475 static const int a = 1 + 2;
3476 };
3477 const int A::a;
3478 )", Lang_CXX, "input1.cc");
3479
3480 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3481 FromTU, varDecl(hasName("a"))); // Decl with init
3482 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3483 FromTU, varDecl(hasName("a"))); // Decl with definition
3484 ASSERT_NE(FromDWithInit, FromDWithDef);
3485 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3486
3487 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3488 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3489 ASSERT_TRUE(ToD0);
3490 ASSERT_TRUE(ToD1);
3491 EXPECT_NE(ToD0, ToD1);
3492 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3493}
3494
3495TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3496 auto StructA =
3497 R"(
3498 struct A {
3499 static const int a = 1 + 2;
3500 };
3501 )";
3502 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3503 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3504 "input1.cc");
3505
3506 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3507 FromTU, varDecl(hasName("a"))); // Decl with init
3508 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3509 FromTU, varDecl(hasName("a"))); // Decl with definition
3510 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3511 ASSERT_TRUE(FromDWithInit->getInit());
3512 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3513 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3514 ASSERT_FALSE(FromDWithDef->getInit());
3515
3516 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3517 ToTU, varDecl(hasName("a"))); // Decl with init
3518 ASSERT_TRUE(ToD->getInit());
3519 ASSERT_FALSE(ToD->getDefinition());
3520
3521 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3522 EXPECT_TRUE(ImportedD->getAnyInitializer());
3523 EXPECT_TRUE(ImportedD->getDefinition());
3524}
3525
3526TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3527 auto StructA =
3528 R"(
3529 struct A {
3530 static const int a;
3531 };
3532 )";
3533 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3534 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3535 Lang_CXX, "input1.cc");
3536
3537 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3538 FromTU, varDecl(hasName("a")));
3539 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3540 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3541 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3542 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3543 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3544 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3545 ASSERT_TRUE(FromDWithDef->getInit());
3546
3547 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3548 ToTU, varDecl(hasName("a")));
3549 ASSERT_FALSE(ToD->getInit());
3550 ASSERT_FALSE(ToD->getDefinition());
3551
3552 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3553 EXPECT_TRUE(ImportedD->getAnyInitializer());
3554 EXPECT_TRUE(ImportedD->getDefinition());
3555}
3556
Gabor Marton7df342a2018-12-17 12:42:12 +00003557struct ImportClasses : ASTImporterTestBase {};
3558
3559TEST_P(ImportClasses,
3560 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
3561 Decl *FromTU = getTuDecl("class X;", Lang_CXX);
3562 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3563 auto FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3564
3565 Decl *ImportedD = Import(FromD, Lang_CXX);
3566 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3567
3568 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
3569 auto ToD = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3570 EXPECT_TRUE(ImportedD == ToD);
3571 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
3572}
3573
3574TEST_P(ImportClasses, ImportPrototypeAfterImportedPrototype) {
3575 Decl *FromTU = getTuDecl("class X; class X;", Lang_CXX);
3576 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3577 auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3578 auto From1 = LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3579
3580 Decl *Imported0 = Import(From0, Lang_CXX);
3581 Decl *Imported1 = Import(From1, Lang_CXX);
3582 Decl *ToTU = Imported0->getTranslationUnitDecl();
3583
3584 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3585 auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3586 auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3587 EXPECT_TRUE(Imported0 == To0);
3588 EXPECT_TRUE(Imported1 == To1);
3589 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3590 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3591 EXPECT_EQ(To1->getPreviousDecl(), To0);
3592}
3593
3594TEST_P(ImportClasses, DefinitionShouldBeImportedAsADefinition) {
3595 Decl *FromTU = getTuDecl("class X {};", Lang_CXX);
3596 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3597 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3598
3599 Decl *ImportedD = Import(FromD, Lang_CXX);
3600 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3601
3602 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
3603 EXPECT_TRUE(cast<CXXRecordDecl>(ImportedD)->isThisDeclarationADefinition());
3604}
3605
3606TEST_P(ImportClasses, ImportPrototypeFromDifferentTUAfterImportedPrototype) {
3607 Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
3608 Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
3609 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3610 auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3611 auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3612
3613 Decl *Imported0 = Import(From0, Lang_CXX);
3614 Decl *Imported1 = Import(From1, Lang_CXX);
3615 Decl *ToTU = Imported0->getTranslationUnitDecl();
3616
3617 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3618 auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3619 auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3620 EXPECT_TRUE(Imported0 == To0);
3621 EXPECT_TRUE(Imported1 == To1);
3622 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3623 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3624 EXPECT_EQ(To1->getPreviousDecl(), To0);
3625}
3626
3627TEST_P(ImportClasses, ImportDefinitions) {
3628 Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
3629 Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
3630 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3631 auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3632 auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3633
3634 Decl *Imported0 = Import(From0, Lang_CXX);
3635 Decl *Imported1 = Import(From1, Lang_CXX);
3636 Decl *ToTU = Imported0->getTranslationUnitDecl();
3637
3638 EXPECT_EQ(Imported0, Imported1);
3639 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
3640 auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3641 EXPECT_TRUE(Imported0 == To0);
3642 EXPECT_TRUE(To0->isThisDeclarationADefinition());
3643}
3644
3645TEST_P(ImportClasses, ImportDefinitionThenPrototype) {
3646 Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
3647 Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
3648 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3649 auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3650 auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3651
3652 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3653 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3654 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3655
3656 EXPECT_NE(ImportedDef, ImportedProto);
3657 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3658 auto ToDef = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3659 auto ToProto = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3660 EXPECT_TRUE(ImportedDef == ToDef);
3661 EXPECT_TRUE(ImportedProto == ToProto);
3662 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3663 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3664 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
3665}
3666
3667TEST_P(ImportClasses, ImportPrototypeThenDefinition) {
3668 Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
3669 Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
3670 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3671 auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3672 auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3673
3674 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3675 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3676 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3677
3678 EXPECT_NE(ImportedDef, ImportedProto);
3679 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3680 auto ToProto = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3681 auto ToDef = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3682 EXPECT_TRUE(ImportedDef == ToDef);
3683 EXPECT_TRUE(ImportedProto == ToProto);
3684 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3685 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3686 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3687}
3688
Gabor Marton54058b52018-12-17 13:53:12 +00003689TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInToContext) {
3690 Decl *ToTU = getToTuDecl("struct X;", Lang_C);
3691 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3692 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3693 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3694 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3695
3696 Decl *ImportedDef = Import(FromDef, Lang_C);
3697
3698 EXPECT_NE(ImportedDef, ToProto);
3699 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3700 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3701 EXPECT_TRUE(ImportedDef == ToDef);
3702 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3703 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3704 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3705}
3706
3707TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3708 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3709 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3710 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3711 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3712 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3713
3714 Decl *ImportedDef = Import(FromDef, Lang_C);
3715
3716 EXPECT_NE(ImportedDef, ToProto);
3717 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3718 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3719 EXPECT_TRUE(ImportedDef == ToDef);
3720 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3721 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3722 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3723}
3724
3725TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3726 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3727 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3728 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3729 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3730 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3731
3732 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3733
3734 EXPECT_NE(ImportedDef, ToProto);
3735 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3736 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3737 EXPECT_TRUE(ImportedDef == ToDef);
3738 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3739 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3740 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3741}
3742
3743TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3744 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3745 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3746 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3747 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3748 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3749
3750 Decl *ImportedProto = Import(FromProto, Lang_C);
3751 Decl *ImportedDef = Import(FromDef, Lang_C);
3752 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3753
3754 EXPECT_NE(ImportedDef, ImportedProto);
3755 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3756 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3757 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3758 EXPECT_TRUE(ImportedDef == ToDef);
3759 EXPECT_TRUE(ImportedProto == ToProto);
3760 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3761 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3762 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3763}
3764
Gabor Marton7df342a2018-12-17 12:42:12 +00003765struct ImportClassTemplates : ASTImporterTestBase {};
3766
3767TEST_P(ImportClassTemplates,
3768 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
3769 Decl *FromTU = getTuDecl("template <class T> class X;", Lang_CXX);
3770 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3771 auto FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3772
3773 Decl *ImportedD = Import(FromD, Lang_CXX);
3774 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3775
3776 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
3777 auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3778 EXPECT_TRUE(ImportedD == ToD);
3779 ASSERT_TRUE(ToD->getTemplatedDecl());
3780 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
3781}
3782
3783TEST_P(ImportClassTemplates, ImportPrototypeAfterImportedPrototype) {
3784 Decl *FromTU = getTuDecl(
3785 "template <class T> class X; template <class T> class X;", Lang_CXX);
3786 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3787 auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3788 auto From1 = LastDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3789
3790 Decl *Imported0 = Import(From0, Lang_CXX);
3791 Decl *Imported1 = Import(From1, Lang_CXX);
3792 Decl *ToTU = Imported0->getTranslationUnitDecl();
3793
3794 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3795 auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3796 auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3797 EXPECT_TRUE(Imported0 == To0);
3798 EXPECT_TRUE(Imported1 == To1);
3799 ASSERT_TRUE(To0->getTemplatedDecl());
3800 ASSERT_TRUE(To1->getTemplatedDecl());
3801 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3802 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3803 EXPECT_EQ(To1->getPreviousDecl(), To0);
3804 EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
3805 To0->getTemplatedDecl());
3806}
3807
3808TEST_P(ImportClassTemplates, DefinitionShouldBeImportedAsADefinition) {
3809 Decl *FromTU = getTuDecl("template <class T> class X {};", Lang_CXX);
3810 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3811 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3812
3813 Decl *ImportedD = Import(FromD, Lang_CXX);
3814 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3815
3816 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
3817 auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3818 ASSERT_TRUE(ToD->getTemplatedDecl());
3819 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
3820}
3821
3822TEST_P(ImportClassTemplates,
3823 ImportPrototypeFromDifferentTUAfterImportedPrototype) {
3824 Decl *FromTU0 =
3825 getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
3826 Decl *FromTU1 =
3827 getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
3828 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3829 auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3830 auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3831
3832 Decl *Imported0 = Import(From0, Lang_CXX);
3833 Decl *Imported1 = Import(From1, Lang_CXX);
3834 Decl *ToTU = Imported0->getTranslationUnitDecl();
3835
3836 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3837 auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3838 auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3839 EXPECT_TRUE(Imported0 == To0);
3840 EXPECT_TRUE(Imported1 == To1);
3841 ASSERT_TRUE(To0->getTemplatedDecl());
3842 ASSERT_TRUE(To1->getTemplatedDecl());
3843 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3844 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3845 EXPECT_EQ(To1->getPreviousDecl(), To0);
3846 EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
3847 To0->getTemplatedDecl());
3848}
3849
3850TEST_P(ImportClassTemplates, ImportDefinitions) {
3851 Decl *FromTU0 =
3852 getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
3853 Decl *FromTU1 =
3854 getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
3855 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3856 auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3857 auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3858
3859 Decl *Imported0 = Import(From0, Lang_CXX);
3860 Decl *Imported1 = Import(From1, Lang_CXX);
3861 Decl *ToTU = Imported0->getTranslationUnitDecl();
3862
3863 EXPECT_EQ(Imported0, Imported1);
3864 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
3865 auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3866 EXPECT_TRUE(Imported0 == To0);
3867 ASSERT_TRUE(To0->getTemplatedDecl());
3868 EXPECT_TRUE(To0->isThisDeclarationADefinition());
3869}
3870
3871TEST_P(ImportClassTemplates, ImportDefinitionThenPrototype) {
3872 Decl *FromTU0 =
3873 getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
3874 Decl *FromTU1 =
3875 getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
3876 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3877 auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3878 auto FromProto =
3879 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3880
3881 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3882 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3883 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3884
3885 EXPECT_NE(ImportedDef, ImportedProto);
3886 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3887 auto ToDef = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3888 auto ToProto = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3889 EXPECT_TRUE(ImportedDef == ToDef);
3890 EXPECT_TRUE(ImportedProto == ToProto);
3891 ASSERT_TRUE(ToDef->getTemplatedDecl());
3892 ASSERT_TRUE(ToProto->getTemplatedDecl());
3893 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3894 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3895 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
3896 EXPECT_EQ(ToProto->getTemplatedDecl()->getPreviousDecl(),
3897 ToDef->getTemplatedDecl());
3898}
3899
3900TEST_P(ImportClassTemplates, ImportPrototypeThenDefinition) {
3901 Decl *FromTU0 =
3902 getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
3903 Decl *FromTU1 =
3904 getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
3905 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3906 auto FromProto =
3907 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3908 auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3909
3910 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3911 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3912 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3913
3914 EXPECT_NE(ImportedDef, ImportedProto);
3915 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3916 auto ToProto = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3917 auto ToDef = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3918 EXPECT_TRUE(ImportedDef == ToDef);
3919 EXPECT_TRUE(ImportedProto == ToProto);
3920 ASSERT_TRUE(ToProto->getTemplatedDecl());
3921 ASSERT_TRUE(ToDef->getTemplatedDecl());
3922 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3923 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3924 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3925 EXPECT_EQ(ToDef->getTemplatedDecl()->getPreviousDecl(),
3926 ToProto->getTemplatedDecl());
3927}
3928
3929struct ImportFriendClasses : ASTImporterTestBase {};
3930
3931TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3932 Decl *FromTU = getTuDecl(
3933 R"(
3934 class A {
3935 template <int I> class F {};
3936 class X {
3937 template <int I> friend class F;
3938 };
3939 };
3940 )",
3941 Lang_CXX, "input0.cc");
3942
3943 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3944 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3945 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3946 FromTU, cxxRecordDecl(hasName("F")));
3947
3948 ASSERT_TRUE(FromClass);
3949 ASSERT_TRUE(FromFriendClass);
3950 ASSERT_NE(FromClass, FromFriendClass);
3951 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3952 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3953 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3954 FromClass->getDescribedClassTemplate());
3955
3956 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3957 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3958
3959 EXPECT_TRUE(ToClass);
3960 EXPECT_TRUE(ToFriendClass);
3961 EXPECT_NE(ToClass, ToFriendClass);
3962 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3963 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3964 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3965 ToClass->getDescribedClassTemplate());
3966}
3967
3968TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3969 Decl *FromTu = getTuDecl(
3970 R"(
3971 class declToImport {
3972 friend class declToImport;
3973 };
3974 )",
3975 Lang_CXX, "input.cc");
3976
3977 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3978 FromTu, cxxRecordDecl(hasName("declToImport")));
3979 auto *ToD = Import(FromD, Lang_CXX);
3980 auto Pattern = cxxRecordDecl(has(friendDecl()));
3981 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3982 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3983}
3984
3985TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3986 Decl *FromTu = getTuDecl(
3987 R"(
3988 template<class A> class declToImport {
3989 template<class A1> friend class declToImport;
3990 };
3991 )",
3992 Lang_CXX, "input.cc");
3993
3994 auto *FromD =
3995 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3996 auto *ToD = Import(FromD, Lang_CXX);
3997
3998 auto Pattern = classTemplateDecl(
3999 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4000 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4001 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4002
4003 auto *Class =
4004 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
4005 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4006 EXPECT_NE(Friend->getFriendDecl(), Class);
4007 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
4008}
4009
4010TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4011 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
4012
4013 ClassTemplateSpecializationDecl *Imported1;
4014 {
4015 Decl *FromTU = getTuDecl("template<class T> class X;"
4016 "struct Y { friend class X<int>; };",
4017 Lang_CXX, "input0.cc");
4018 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4019 FromTU, Pattern);
4020
4021 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4022 }
4023 ClassTemplateSpecializationDecl *Imported2;
4024 {
4025 Decl *FromTU = getTuDecl("template<class T> class X;"
4026 "template<> class X<int>{};"
4027 "struct Z { friend class X<int>; };",
4028 Lang_CXX, "input1.cc");
4029 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4030 FromTU, Pattern);
4031
4032 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4033 }
4034
4035 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4036 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4037 2u);
4038 ASSERT_TRUE(Imported2->getPreviousDecl());
4039 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4040}
4041
4042TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4043 Decl *FromTU0 = getTuDecl(
4044 R"(
4045 class X {
4046 class Y;
4047 };
4048 class X::Y {
4049 template <typename T>
4050 friend class F; // The decl context of F is the global namespace.
4051 };
4052 )",
4053 Lang_CXX, "input0.cc");
4054 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4055 FromTU0, classTemplateDecl(hasName("F")));
4056 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4057 Decl *FromTU1 = getTuDecl(
4058 R"(
4059 template <typename T>
4060 class F {};
4061 )",
4062 Lang_CXX, "input1.cc");
4063 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4064 FromTU1, classTemplateDecl(hasName("F")));
4065 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4066 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4067 Imported1->getTemplatedDecl()->getTypeForDecl());
4068}
4069
4070TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4071 Decl *From, *To;
4072 std::tie(From, To) =
4073 getImportedDecl("class declToImport {};", Lang_CXX,
4074 "class Y { friend class declToImport; };", Lang_CXX);
4075 auto *Imported = cast<CXXRecordDecl>(To);
4076
4077 EXPECT_TRUE(Imported->getPreviousDecl());
4078}
4079
4080TEST_P(ImportFriendClasses,
4081 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4082 Decl *ToTU = getToTuDecl(
4083 R"(
4084 class X {
4085 class Y;
4086 };
4087 class X::Y {
4088 template <typename T>
4089 friend class F; // The decl context of F is the global namespace.
4090 };
4091 )",
4092 Lang_CXX);
4093 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4094 ToTU, classTemplateDecl(hasName("F")));
4095 Decl *FromTU = getTuDecl(
4096 R"(
4097 template <typename T>
4098 class F {};
4099 )",
4100 Lang_CXX, "input0.cc");
4101 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4102 FromTU, classTemplateDecl(hasName("F")));
4103 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4104 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4105 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4106 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4107 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4108}
4109
4110TEST_P(ImportFriendClasses,
4111 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4112 Decl *FromTU0 = getTuDecl(
4113 R"(
4114 class X {
4115 class Y;
4116 };
4117 class X::Y {
4118 template <typename T>
4119 friend class F; // The decl context of F is the global namespace.
4120 };
4121 )",
4122 Lang_CXX, "input0.cc");
4123 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4124 FromTU0, classTemplateDecl(hasName("F")));
4125 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4126 Decl *FromTU1 = getTuDecl(
4127 R"(
4128 template <typename T>
4129 class F {};
4130 )",
4131 Lang_CXX, "input1.cc");
4132 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4133 FromTU1, classTemplateDecl(hasName("F")));
4134 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4135 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4136 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4137 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4138 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4139}
4140
4141TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4142 Decl *FromTU0 = getTuDecl(
4143 R"(
4144 class X {
4145 class Y;
4146 };
4147 class X::Y {
4148 friend class F; // The decl context of F is the global namespace.
4149 };
4150 )",
4151 Lang_CXX, "input0.cc");
4152 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4153 QualType FT = Friend->getFriendType()->getType();
4154 FT = FromTU0->getASTContext().getCanonicalType(FT);
4155 auto *Fwd = cast<TagType>(FT)->getDecl();
4156 auto *ImportedFwd = Import(Fwd, Lang_CXX);
4157 Decl *FromTU1 = getTuDecl(
4158 R"(
4159 class F {};
4160 )",
4161 Lang_CXX, "input1.cc");
4162 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4163 FromTU1, cxxRecordDecl(hasName("F")));
4164 auto *ImportedDef = Import(Definition, Lang_CXX);
4165 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4166 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4167}
4168
Gabor Marton54058b52018-12-17 13:53:12 +00004169TEST_P(ASTImporterTestBase, FriendFunInClassTemplate) {
4170 auto *Code = R"(
4171 template <class T>
4172 struct X {
4173 friend void foo(){}
4174 };
4175 )";
4176 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4177 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4178 ToTU, functionDecl(hasName("foo")));
4179
4180 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4181 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4182 FromTU, functionDecl(hasName("foo")));
4183 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4184 EXPECT_EQ(ImportedFoo, ToFoo);
4185}
4186
Gabor Marton61d862a2018-05-18 09:08:47 +00004187struct DeclContextTest : ASTImporterTestBase {};
4188
4189TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4190 Decl *TU = getTuDecl(
4191 R"(
4192 namespace NS {
4193
4194 template <typename T>
4195 struct S {};
4196 template struct S<int>;
4197
4198 inline namespace INS {
4199 template <typename T>
4200 struct S {};
4201 template struct S<int>;
4202 }
4203
4204 }
4205 )", Lang_CXX11, "input0.cc");
4206 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4207 TU, namespaceDecl());
4208 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4209 TU, classTemplateSpecializationDecl());
4210 ASSERT_TRUE(NS->containsDecl(Spec));
4211
4212 NS->removeDecl(Spec);
4213 EXPECT_FALSE(NS->containsDecl(Spec));
4214}
4215
Gabor Marton7df342a2018-12-17 12:42:12 +00004216TEST_P(DeclContextTest,
4217 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4218 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4219 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4220 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4221
4222 // Investigate the list.
4223 auto *DC = A0->getDeclContext();
4224 ASSERT_TRUE(DC->containsDecl(A0));
4225 ASSERT_TRUE(DC->containsDecl(A1));
4226
4227 // Investigate the lookup table.
4228 auto *Map = DC->getLookupPtr();
4229 ASSERT_TRUE(Map);
4230 auto I = Map->find(A0->getDeclName());
4231 ASSERT_NE(I, Map->end());
4232 StoredDeclsList &L = I->second;
4233 // The lookup table contains the most recent decl of A.
4234 ASSERT_NE(L.getAsDecl(), A0);
4235 ASSERT_EQ(L.getAsDecl(), A1);
4236
4237 ASSERT_TRUE(L.getAsDecl());
4238 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4239 // The point here is to have a Vec with only one element, which is not the
4240 // one we are going to delete from the DC later.
4241 L.setHasExternalDecls();
4242 ASSERT_TRUE(L.getAsVector());
4243 ASSERT_EQ(1u, L.getAsVector()->size());
4244
4245 // This asserts in the old implementation.
4246 DC->removeDecl(A0);
4247 EXPECT_FALSE(DC->containsDecl(A0));
4248}
4249
Gabor Marton5254e642018-06-27 13:32:50 +00004250struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
4251
4252TEST_P(ImportFunctionTemplateSpecializations,
4253 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4254
4255 Decl *FromTU = getTuDecl(
4256 R"(
4257 template<class T>
4258 int f() { return 0; }
4259 void foo() { f<int>(); }
4260 )",
4261 Lang_CXX, "input0.cc");
4262
4263 // Check that the function template instantiation is NOT the child of the TU.
4264 auto Pattern = translationUnitDecl(
4265 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4266 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4267
4268 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4269 FromTU, functionDecl(hasName("foo")));
4270 ASSERT_TRUE(Import(Foo, Lang_CXX));
4271
4272 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4273 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4274}
4275
4276TEST_P(ImportFunctionTemplateSpecializations,
4277 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4278
4279 Decl *FromTU = getTuDecl(
4280 R"(
4281 template<class T>
4282 int f() { return 0; }
4283 template int f<int>();
4284 )",
4285 Lang_CXX, "input0.cc");
4286
4287 // Check that the function template instantiation is NOT the child of the TU.
4288 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4289 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4290 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4291
4292 ASSERT_TRUE(
4293 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4294
4295 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4296 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4297}
4298
4299TEST_P(ImportFunctionTemplateSpecializations,
4300 TUshouldContainFunctionTemplateSpecialization) {
4301
4302 Decl *FromTU = getTuDecl(
4303 R"(
4304 template<class T>
4305 int f() { return 0; }
4306 template <> int f<int>() { return 4; }
4307 )",
4308 Lang_CXX, "input0.cc");
4309
4310 // Check that the function template specialization is the child of the TU.
4311 auto Specialization =
4312 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4313 auto Pattern = translationUnitDecl(has(Specialization));
4314 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4315
4316 ASSERT_TRUE(
4317 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4318
4319 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4320 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4321}
4322
4323TEST_P(ImportFunctionTemplateSpecializations,
4324 FunctionTemplateSpecializationRedeclChain) {
4325
4326 Decl *FromTU = getTuDecl(
4327 R"(
4328 template<class T>
4329 int f() { return 0; }
4330 template <> int f<int>() { return 4; }
4331 )",
4332 Lang_CXX, "input0.cc");
4333
4334 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4335 hasParent(translationUnitDecl()));
4336 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4337 {
4338 auto *TU = FromTU;
4339 auto *SpecD = FromSpecD;
4340 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4341 TU, functionTemplateDecl());
4342 auto *FirstSpecD = *(TemplateD->spec_begin());
4343 ASSERT_EQ(SpecD, FirstSpecD);
4344 ASSERT_TRUE(SpecD->getPreviousDecl());
4345 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4346 ->doesThisDeclarationHaveABody());
4347 }
4348
4349 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4350
4351 {
4352 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4353 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4354 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4355 TU, functionTemplateDecl());
4356 auto *FirstSpecD = *(TemplateD->spec_begin());
4357 EXPECT_EQ(SpecD, FirstSpecD);
4358 ASSERT_TRUE(SpecD->getPreviousDecl());
4359 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4360 ->doesThisDeclarationHaveABody());
4361 }
4362}
4363
4364TEST_P(ImportFunctionTemplateSpecializations,
4365 MatchNumberOfFunctionTemplateSpecializations) {
4366
4367 Decl *FromTU = getTuDecl(
4368 R"(
4369 template <typename T> constexpr int f() { return 0; }
4370 template <> constexpr int f<int>() { return 4; }
4371 void foo() {
4372 static_assert(f<char>() == 0, "");
4373 static_assert(f<int>() == 4, "");
4374 }
4375 )",
4376 Lang_CXX11, "input0.cc");
4377 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4378 FromTU, functionDecl(hasName("foo")));
4379
4380 Import(FromD, Lang_CXX11);
4381 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4382 EXPECT_EQ(
4383 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4384 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4385}
4386
4387TEST_P(ImportFunctionTemplateSpecializations,
4388 ImportPrototypes) {
4389 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4390 auto Code =
4391 R"(
4392 // Proto of the primary template.
4393 template <class T>
4394 void f();
4395 // Proto of the specialization.
4396 template <>
4397 void f<int>();
4398 )";
4399
4400 Decl *ImportedD;
4401 {
4402 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4403 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4404
4405 ImportedD = Import(FromD, Lang_CXX);
4406 }
4407 {
4408 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
4409 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4410 Import(FromD, Lang_CXX);
4411 }
4412
4413 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4414
4415 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4416 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4417 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4418 EXPECT_TRUE(ImportedD == To0);
4419 EXPECT_TRUE(ImportedD != To1);
4420 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
4421 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
4422 // Check that they are part of the same redecl chain.
4423 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
4424}
4425
4426TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
4427 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4428 auto Code =
4429 R"(
4430 // Proto of the primary template.
4431 template <class T>
4432 void f();
4433 // Specialization and definition.
4434 template <>
4435 void f<int>() {}
4436 )";
4437
4438 Decl *ImportedD;
4439 {
4440 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4441 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4442 ImportedD = Import(FromD, Lang_CXX);
4443 }
4444 {
4445 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
4446 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4447 Import(FromD, Lang_CXX);
4448 }
4449
4450 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4451
4452 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
4453 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4454 EXPECT_TRUE(ImportedD == To0);
4455 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
4456
4457 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4458 ToTU, functionTemplateDecl());
4459 auto *FirstSpecD = *(TemplateD->spec_begin());
4460 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
4461}
4462
4463TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
4464 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4465 auto Code =
4466 R"(
4467 // Proto of the primary template.
4468 template <class T>
4469 void f();
4470 // Specialization proto.
4471 template <>
4472 void f<int>();
4473 // Specialization proto.
4474 template <>
4475 void f<int>();
4476 )";
4477
4478 Decl *ImportedD;
4479 {
4480 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4481 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4482 ImportedD = Import(FromD, Lang_CXX);
4483 }
4484
4485 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4486
4487 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4488 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4489 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4490 EXPECT_TRUE(ImportedD == To0);
4491 EXPECT_TRUE(ImportedD != To1);
4492 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
4493 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
4494 EXPECT_EQ(To1->getPreviousDecl(), To0);
4495}
4496
4497TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
4498 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4499 auto Code =
4500 R"(
4501 // Proto of the primary template.
4502 template <class T>
4503 void f();
4504 // Specialization proto.
4505 template <>
4506 void f<int>();
4507 // Specialization definition.
4508 template <>
4509 void f<int>() {}
4510 )";
4511
4512 Decl *ImportedD;
4513 {
4514 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4515 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4516 ImportedD = Import(FromD, Lang_CXX);
4517 }
4518
4519 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4520
4521 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4522 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4523 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4524 EXPECT_TRUE(ImportedD == To0);
4525 EXPECT_TRUE(ImportedD != To1);
4526 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
4527 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
4528 EXPECT_EQ(To1->getPreviousDecl(), To0);
4529}
4530
4531TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
4532 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4533 auto Code =
4534 R"(
4535 // Proto of the primary template.
4536 template <class T>
4537 void f();
4538 // Specialization definition.
4539 template <>
4540 void f<int>() {}
4541 // Specialization proto.
4542 template <>
4543 void f<int>();
4544 )";
4545
4546 Decl *ImportedD;
4547 {
4548 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4549 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4550 ImportedD = Import(FromD, Lang_CXX);
4551 }
4552
4553 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4554
4555 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4556 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4557 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4558 EXPECT_TRUE(ImportedD == To0);
4559 EXPECT_TRUE(ImportedD != To1);
4560 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
4561 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
4562 EXPECT_EQ(To1->getPreviousDecl(), To0);
4563}
4564
Gabor Marton17d39672018-11-26 15:54:08 +00004565TEST_P(ASTImporterTestBase,
4566 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4567 {
4568 Decl *FromTU = getTuDecl(
4569 R"(
4570 template <typename T>
4571 struct B;
4572 )",
4573 Lang_CXX, "input0.cc");
4574 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4575 FromTU, classTemplateDecl(hasName("B")));
4576
4577 Import(FromD, Lang_CXX);
4578 }
4579
4580 {
4581 Decl *FromTU = getTuDecl(
4582 R"(
4583 template <typename T>
4584 struct B {
4585 void f();
4586 B* b;
4587 };
4588 )",
4589 Lang_CXX, "input1.cc");
4590 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4591 FromTU, functionDecl(hasName("f")));
4592 Import(FromD, Lang_CXX);
4593 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4594 FromTU, classTemplateDecl(hasName("B")));
4595 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4596 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4597
4598 // We expect no (ODR) warning during the import.
4599 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4600 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4601 }
4602}
4603
Gabor Martonb93baf62018-11-27 09:51:36 +00004604TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
4605 // We already have an incomplete underlying type in the "To" context.
4606 auto Code =
4607 R"(
4608 template <typename T>
4609 struct S {
4610 void foo();
4611 };
4612 using U = S<int>;
4613 )";
4614 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4615 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4616 typedefNameDecl(hasName("U")));
4617 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4618
4619 // The "From" context has the same typedef, but the underlying type is
4620 // complete this time.
4621 Decl *FromTU = getTuDecl(std::string(Code) +
4622 R"(
4623 void foo(U* u) {
4624 u->foo();
4625 }
4626 )", Lang_CXX11);
4627 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4628 typedefNameDecl(hasName("U")));
4629 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4630
4631 // The imported type should be complete.
4632 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4633 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4634}
4635
Gabor Marton54058b52018-12-17 13:53:12 +00004636struct ASTImporterLookupTableTest : ASTImporterTestBase {};
4637
4638TEST_P(ASTImporterLookupTableTest, OneDecl) {
4639 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4640 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4641 ASTImporterLookupTable LT(*ToTU);
4642 auto Res = LT.lookup(ToTU, D->getDeclName());
4643 ASSERT_EQ(Res.size(), 1u);
4644 EXPECT_EQ(*Res.begin(), D);
4645}
4646
4647static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4648 for (Decl *D : DC->decls()) {
4649 if (auto *ND = dyn_cast<NamedDecl>(D))
4650 if (ND->getDeclName() == Name)
4651 return ND;
4652 }
4653 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004654}
Gabor Marton54058b52018-12-17 13:53:12 +00004655
4656TEST_P(ASTImporterLookupTableTest,
4657 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4658 auto *Code = R"(
4659 template <class T>
4660 struct X {
4661 friend void foo(){}
4662 };
4663 )";
4664 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4665 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4666 ToTU, classTemplateDecl(hasName("X")));
4667 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4668 ToTU, functionDecl(hasName("foo")));
4669 DeclContext *FooDC = Foo->getDeclContext();
4670 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4671 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4672 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4673 DeclarationName FooName = Foo->getDeclName();
4674
4675 // Cannot find in the LookupTable of its DC (TUDecl)
4676 SmallVector<NamedDecl *, 2> FoundDecls;
4677 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4678 EXPECT_EQ(FoundDecls.size(), 0u);
4679
4680 // Cannot find in the LookupTable of its LexicalDC (X)
4681 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4682 EXPECT_EQ(FoundDecls.size(), 0u);
4683
4684 // Can't find in the list of Decls of the DC.
4685 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4686
4687 // Can't find in the list of Decls of the LexicalDC
4688 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4689
4690 // ASTImporter specific lookup finds it.
4691 ASTImporterLookupTable LT(*ToTU);
4692 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4693 ASSERT_EQ(Res.size(), 1u);
4694 EXPECT_EQ(*Res.begin(), Foo);
4695}
4696
4697TEST_P(ASTImporterLookupTableTest,
4698 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4699 TranslationUnitDecl *ToTU =
4700 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4701 auto *Foo =
4702 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4703 auto *A =
4704 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4705 DeclContext *FooDC = Foo->getDeclContext();
4706 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4707 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4708 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4709 DeclarationName FooName = Foo->getDeclName();
4710
4711 // Cannot find in the LookupTable of its DC (TUDecl).
4712 SmallVector<NamedDecl *, 2> FoundDecls;
4713 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4714 EXPECT_EQ(FoundDecls.size(), 0u);
4715
4716 // Cannot find in the LookupTable of its LexicalDC (A).
4717 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4718 EXPECT_EQ(FoundDecls.size(), 0u);
4719
4720 // Can't find in the list of Decls of the DC.
4721 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4722
4723 // Can find in the list of Decls of the LexicalDC.
4724 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4725
4726 // ASTImporter specific lookup finds it.
4727 ASTImporterLookupTable LT(*ToTU);
4728 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4729 ASSERT_EQ(Res.size(), 1u);
4730 EXPECT_EQ(*Res.begin(), Foo);
4731}
4732
4733TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4734 TranslationUnitDecl *ToTU =
4735 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4736 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4737 .match(ToTU, varDecl(hasName("V")))
4738 ->getDeclName();
4739 auto *A =
4740 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4741 auto *B =
4742 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4743
4744 ASTImporterLookupTable LT(*ToTU);
4745
4746 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4747 ASSERT_EQ(Res.size(), 1u);
4748 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4749 ToTU, fieldDecl(hasName("V"),
4750 hasParent(recordDecl(hasName("A"))))));
4751 Res = LT.lookup(cast<DeclContext>(B), VName);
4752 ASSERT_EQ(Res.size(), 1u);
4753 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4754 ToTU, fieldDecl(hasName("V"),
4755 hasParent(recordDecl(hasName("B"))))));
4756 Res = LT.lookup(ToTU, VName);
4757 ASSERT_EQ(Res.size(), 1u);
4758 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4759 ToTU, varDecl(hasName("V"),
4760 hasParent(translationUnitDecl()))));
4761}
4762
4763TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4764 TranslationUnitDecl *ToTU = getToTuDecl(
4765 R"(
4766 void foo();
4767 void foo(int);
4768 void foo(int, int);
4769 )",
4770 Lang_CXX);
4771
4772 ASTImporterLookupTable LT(*ToTU);
4773 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4774 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4775 DeclarationName Name = F0->getDeclName();
4776 auto Res = LT.lookup(ToTU, Name);
4777 EXPECT_EQ(Res.size(), 3u);
4778 EXPECT_EQ(Res.count(F0), 1u);
4779 EXPECT_EQ(Res.count(F2), 1u);
4780}
4781
4782static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
4783 QualType Ty = FD->getFriendType()->getType();
4784 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
4785 return cast<RecordType>(NamedTy)->getDecl();
4786}
4787
4788TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
4789 TranslationUnitDecl *ToTU = getToTuDecl(
4790 R"(
4791 class Y { friend class F; };
4792 )",
4793 Lang_CXX);
4794
4795 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4796 // So we must dig up the underlying CXXRecordDecl.
4797 ASTImporterLookupTable LT(*ToTU);
4798 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4799 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4800 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4801 ToTU, cxxRecordDecl(hasName("Y")));
4802
4803 DeclarationName Name = RD->getDeclName();
4804 auto Res = LT.lookup(ToTU, Name);
4805 EXPECT_EQ(Res.size(), 1u);
4806 EXPECT_EQ(*Res.begin(), RD);
4807
4808 Res = LT.lookup(Y, Name);
4809 EXPECT_EQ(Res.size(), 0u);
4810}
4811
4812TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4813 TranslationUnitDecl *ToTU = getToTuDecl(
4814 R"(
4815 class Y { template <class T> friend class F; };
4816 )",
4817 Lang_CXX);
4818
4819 ASTImporterLookupTable LT(*ToTU);
4820 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4821 ToTU, classTemplateDecl(hasName("F")));
4822 DeclarationName Name = F->getDeclName();
4823 auto Res = LT.lookup(ToTU, Name);
4824 EXPECT_EQ(Res.size(), 2u);
4825 EXPECT_EQ(Res.count(F), 1u);
4826 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4827}
4828
4829TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4830 TranslationUnitDecl *ToTU = getToTuDecl(
4831 R"(
4832 template <typename T>
4833 class F;
4834
4835 template <typename T>
4836 class Y {
4837 friend class F<T>;
4838 };
4839 )",
4840 Lang_CXX);
4841
4842 ASTImporterLookupTable LT(*ToTU);
4843 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4844 ToTU, classTemplateDecl(hasName("F")));
4845 DeclarationName Name = F->getDeclName();
4846 auto Res = LT.lookup(ToTU, Name);
4847 EXPECT_EQ(Res.size(), 2u);
4848 EXPECT_EQ(Res.count(F), 1u);
4849 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4850}
4851
4852TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4853 TranslationUnitDecl *ToTU = getToTuDecl(
4854 R"(
4855 template <typename T>
4856 class F;
4857
4858 class Y {
4859 friend class F<int>;
4860 };
4861 )",
4862 Lang_CXX);
4863
4864 ASTImporterLookupTable LT(*ToTU);
4865 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4866 ToTU, classTemplateDecl(hasName("F")));
4867 DeclarationName Name = F->getDeclName();
4868 auto Res = LT.lookup(ToTU, Name);
4869 ASSERT_EQ(Res.size(), 3u);
4870 EXPECT_EQ(Res.count(F), 1u);
4871 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4872 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4873}
4874
4875TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4876 TranslationUnitDecl *ToTU = getToTuDecl(
4877 R"(
4878 class Y { friend void F(); };
4879 )",
4880 Lang_CXX);
4881
4882 ASTImporterLookupTable LT(*ToTU);
4883 auto *F =
4884 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4885 DeclarationName Name = F->getDeclName();
4886 auto Res = LT.lookup(ToTU, Name);
4887 EXPECT_EQ(Res.size(), 1u);
4888 EXPECT_EQ(*Res.begin(), F);
4889}
4890
4891TEST_P(ASTImporterLookupTableTest,
4892 LookupFindsDeclsInClassTemplateSpecialization) {
4893 TranslationUnitDecl *ToTU = getToTuDecl(
4894 R"(
4895 template <typename T>
4896 struct X {
4897 int F;
4898 };
4899 void foo() {
4900 X<char> xc;
4901 }
4902 )",
4903 Lang_CXX);
4904
4905 ASTImporterLookupTable LT(*ToTU);
4906
4907 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4908 ToTU, classTemplateDecl(hasName("X")));
4909 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4910 ToTU,
4911 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4912
4913 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4914 ToTU, classTemplateSpecializationDecl(hasName("X")));
4915 FieldDecl *FieldInSpec = *Spec->field_begin();
4916 ASSERT_TRUE(FieldInSpec);
4917
4918 DeclarationName Name = FieldInSpec->getDeclName();
4919 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4920
4921 SmallVector<NamedDecl *, 2> FoundDecls;
4922 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4923 EXPECT_EQ(FoundDecls.size(), 1u);
4924 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4925
4926 auto Res = LT.lookup(TemplateDC, Name);
4927 ASSERT_EQ(Res.size(), 1u);
4928 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4929
4930 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4931 FoundDecls);
4932 EXPECT_EQ(FoundDecls.size(), 1u);
4933 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4934
4935 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4936 ASSERT_EQ(Res.size(), 1u);
4937 EXPECT_EQ(*Res.begin(), FieldInSpec);
4938}
4939
4940TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4941 TranslationUnitDecl *ToTU = getToTuDecl(
4942 R"(
4943 class Y { template <class T> friend void F(); };
4944 )",
4945 Lang_CXX);
4946
4947 ASTImporterLookupTable LT(*ToTU);
4948 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4949 ToTU, functionTemplateDecl(hasName("F")));
4950 DeclarationName Name = F->getDeclName();
4951 auto Res = LT.lookup(ToTU, Name);
4952 EXPECT_EQ(Res.size(), 2u);
4953 EXPECT_EQ(Res.count(F), 1u);
4954 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4955}
4956
4957TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4958 TranslationUnitDecl *ToTU = getToTuDecl(
4959 R"(
4960 struct X;
4961 struct A {
4962 friend struct X;
4963 };
4964 struct B {
4965 friend struct X;
4966 };
4967 )",
4968 Lang_CXX);
4969
4970 ASTImporterLookupTable LT(*ToTU);
4971 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4972 ToTU, cxxRecordDecl(hasName("X")));
4973 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4974 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4975 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4976 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4977 ASSERT_EQ(RD0, RD1);
4978 ASSERT_EQ(RD1, X);
4979
4980 DeclarationName Name = X->getDeclName();
4981 auto Res = LT.lookup(ToTU, Name);
4982 EXPECT_EQ(Res.size(), 1u);
4983 EXPECT_EQ(*Res.begin(), X);
4984}
4985
4986TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4987 TranslationUnitDecl *ToTU = getToTuDecl(
4988 R"(
4989 enum E {
4990 A,
4991 B
4992 };
4993 )",
4994 Lang_C);
4995
4996 ASTImporterLookupTable LT(*ToTU);
4997 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4998 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4999 ToTU, enumConstantDecl(hasName("A")));
5000
5001 DeclarationName Name = A->getDeclName();
5002 // Redecl context is the TU.
5003 ASSERT_EQ(E->getRedeclContext(), ToTU);
5004
5005 SmallVector<NamedDecl *, 2> FoundDecls;
5006 // Normal lookup finds in the DC.
5007 E->localUncachedLookup(Name, FoundDecls);
5008 EXPECT_EQ(FoundDecls.size(), 1u);
5009
5010 // Normal lookup finds in the Redecl context.
5011 ToTU->localUncachedLookup(Name, FoundDecls);
5012 EXPECT_EQ(FoundDecls.size(), 1u);
5013
5014 // Import specific lookup finds in the DC.
5015 auto Res = LT.lookup(E, Name);
5016 ASSERT_EQ(Res.size(), 1u);
5017 EXPECT_EQ(*Res.begin(), A);
5018
5019 // Import specific lookup finds in the Redecl context.
5020 Res = LT.lookup(ToTU, Name);
5021 ASSERT_EQ(Res.size(), 1u);
5022 EXPECT_EQ(*Res.begin(), A);
5023}
5024
5025TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
5026 TranslationUnitDecl *ToTU = getToTuDecl(
5027 R"(
5028 namespace N {
5029 int A;
5030 }
5031 namespace N {
5032 }
5033 )",
5034 Lang_CXX);
5035 auto *N1 =
5036 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
5037 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
5038 DeclarationName Name = A->getDeclName();
5039
5040 ASTImporterLookupTable LT(*ToTU);
5041 auto Res = LT.lookup(N1, Name);
5042 ASSERT_EQ(Res.size(), 1u);
5043 EXPECT_EQ(*Res.begin(), A);
5044}
5045
Gabor Marton19f4f392018-06-25 13:04:37 +00005046INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5047 ::testing::Values(ArgVector()), );
5048
Gabor Marton5254e642018-06-27 13:32:50 +00005049INSTANTIATE_TEST_CASE_P(
5050 ParameterizedTests, CanonicalRedeclChain,
5051 ::testing::Values(ArgVector()),);
5052
Gabor Marton19f4f392018-06-25 13:04:37 +00005053auto DefaultTestValuesForRunOptions = ::testing::Values(
5054 ArgVector(),
5055 ArgVector{"-fdelayed-template-parsing"},
5056 ArgVector{"-fms-compatibility"},
5057 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
5058
Gabor Marton54058b52018-12-17 13:53:12 +00005059INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5060 DefaultTestValuesForRunOptions, );
5061
Gabor Marton19f4f392018-06-25 13:04:37 +00005062INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5063 DefaultTestValuesForRunOptions, );
5064
5065INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5066 DefaultTestValuesForRunOptions, );
5067
5068INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5069 DefaultTestValuesForRunOptions, );
5070
5071INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
5072 DefaultTestValuesForRunOptions, );
5073
5074INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5075 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005076
Gabor Marton54058b52018-12-17 13:53:12 +00005077INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005078 DefaultTestValuesForRunOptions, );
5079
Gabor Marton54058b52018-12-17 13:53:12 +00005080INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005081 DefaultTestValuesForRunOptions, );
5082
5083INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplates,
5084 DefaultTestValuesForRunOptions, );
5085
5086INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5087 DefaultTestValuesForRunOptions, );
5088
Gabor Marton5254e642018-06-27 13:32:50 +00005089INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5090 ImportFunctionTemplateSpecializations,
5091 DefaultTestValuesForRunOptions, );
5092
Gabor Martonac3a5d62018-09-17 12:04:52 +00005093INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5094 DefaultTestValuesForRunOptions, );
5095
5096INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5097 DefaultTestValuesForRunOptions, );
5098
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005099} // end namespace ast_matchers
5100} // end namespace clang