blob: 84bfdadae2db1892ab38ebf399d43576ea7ecf96 [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Tests for the correct import of AST nodes from one AST context to another.
11//
12//===----------------------------------------------------------------------===//
13
Aleksei Sidorin8fc85102018-01-26 11:36:54 +000014#include "MatchVerifier.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000015#include "clang/AST/ASTContext.h"
16#include "clang/AST/ASTImporter.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000017#include "clang/ASTMatchers/ASTMatchFinder.h"
18#include "clang/ASTMatchers/ASTMatchers.h"
19#include "clang/Tooling/Tooling.h"
Peter Szecsidedda6f2018-03-30 22:03:29 +000020
21#include "DeclMatcher.h"
Gabor Marton1f667532018-05-24 08:41:07 +000022#include "Language.h"
Gabor Marton5254e642018-06-27 13:32:50 +000023#include "gmock/gmock.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000024#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000025
26namespace clang {
27namespace ast_matchers {
28
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000029using internal::Matcher;
30using internal::BindableMatcher;
31using llvm::StringMap;
32
Peter Szecsidedda6f2018-03-30 22:03:29 +000033// Creates a virtual file and assigns that to the context of given AST. If the
34// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000035static void
36createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
37 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000038 assert(ToAST);
39 ASTContext &ToCtx = ToAST->getASTContext();
40 auto *OFS = static_cast<vfs::OverlayFileSystem *>(
41 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
42 auto *MFS =
43 static_cast<vfs::InMemoryFileSystem *>(OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000044 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000045}
46
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000047static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
48 StringRef Code) {
49 return createVirtualFileIfNeeded(ToAST, FileName,
50 llvm::MemoryBuffer::getMemBuffer(Code));
51}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000052
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000053const StringRef DeclToImportID = "declToImport";
54const StringRef DeclToVerifyID = "declToVerify";
55
Gabor Marton19f4f392018-06-25 13:04:37 +000056// Common base for the different families of ASTImporter tests that are
57// parameterized on the compiler options which may result a different AST. E.g.
58// -fms-compatibility or -fdelayed-template-parsing.
59struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000060
Gabor Marton19f4f392018-06-25 13:04:37 +000061 // Returns the argument vector used for a specific language option, this set
62 // can be tweaked by the test parameters.
63 ArgVector getArgVectorForLanguage(Language Lang) const {
64 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
65 ArgVector ExtraArgs = GetParam();
66 for (const auto &Arg : ExtraArgs) {
67 Args.push_back(Arg);
68 }
69 return Args;
70 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000071
Gabor Marton19f4f392018-06-25 13:04:37 +000072};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000073
Gabor Marton19f4f392018-06-25 13:04:37 +000074// Base class for those tests which use the family of `testImport` functions.
75class TestImportBase : public ParameterizedTestsFixture {
Adam Baloghe4192a82018-06-15 06:45:39 +000076
Gabor Marton19f4f392018-06-25 13:04:37 +000077 template <typename NodeType>
78 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
79 NodeType Node) {
80 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000081
Gabor Marton19f4f392018-06-25 13:04:37 +000082 // Add 'From' file to virtual file system so importer can 'find' it
83 // while importing SourceLocations. It is safe to add same file multiple
84 // times - it just isn't replaced.
85 StringRef FromFileName = From->getMainFileName();
86 createVirtualFileIfNeeded(To, FromFileName,
87 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000088
Gabor Marton19f4f392018-06-25 13:04:37 +000089 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000090
Gabor Marton19f4f392018-06-25 13:04:37 +000091 // This should dump source locations and assert if some source locations
92 // were not imported.
93 SmallString<1024> ImportChecker;
94 llvm::raw_svector_ostream ToNothing(ImportChecker);
95 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000096
Gabor Marton19f4f392018-06-25 13:04:37 +000097 // This traverses the AST to catch certain bugs like poorly or not
98 // implemented subtrees.
99 Imported->dump(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000100
Gabor Marton19f4f392018-06-25 13:04:37 +0000101 return Imported;
102 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000103
Gabor Marton19f4f392018-06-25 13:04:37 +0000104 template <typename NodeType>
105 testing::AssertionResult
106 testImport(const std::string &FromCode, const ArgVector &FromArgs,
107 const std::string &ToCode, const ArgVector &ToArgs,
108 MatchVerifier<NodeType> &Verifier,
109 const BindableMatcher<NodeType> &SearchMatcher,
110 const BindableMatcher<NodeType> &VerificationMatcher) {
111 const char *const InputFileName = "input.cc";
112 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000113
Gabor Marton19f4f392018-06-25 13:04:37 +0000114 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
115 FromCode, FromArgs, InputFileName),
116 ToAST = tooling::buildASTFromCodeWithArgs(
117 ToCode, ToArgs, OutputFileName);
118
119 ASTContext &FromCtx = FromAST->getASTContext(),
120 &ToCtx = ToAST->getASTContext();
121
122 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
123 FromAST->getFileManager(), false);
124
125 auto FoundNodes = match(SearchMatcher, FromCtx);
126 if (FoundNodes.size() != 1)
127 return testing::AssertionFailure()
128 << "Multiple potential nodes were found!";
129
130 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
131 if (!ToImport)
132 return testing::AssertionFailure() << "Node type mismatch!";
133
134 // Sanity check: the node being imported should match in the same way as
135 // the result node.
136 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
137 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
138
139 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
140 if (!Imported)
141 return testing::AssertionFailure() << "Import failed, nullptr returned!";
142
143 return Verifier.match(Imported, WrapperMatcher);
144 }
145
146 template <typename NodeType>
147 testing::AssertionResult
148 testImport(const std::string &FromCode, const ArgVector &FromArgs,
149 const std::string &ToCode, const ArgVector &ToArgs,
150 MatchVerifier<NodeType> &Verifier,
151 const BindableMatcher<NodeType> &VerificationMatcher) {
152 return testImport(
153 FromCode, FromArgs, ToCode, ToArgs, Verifier,
154 translationUnitDecl(
155 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
156 VerificationMatcher);
157 }
158
159public:
160
161 /// Test how AST node named "declToImport" located in the translation unit
162 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
163 /// The verification is done by running AMatcher over the imported node.
164 template <typename NodeType, typename MatcherType>
165 void testImport(const std::string &FromCode, Language FromLang,
166 const std::string &ToCode, Language ToLang,
167 MatchVerifier<NodeType> &Verifier,
168 const MatcherType &AMatcher) {
169 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
170 ToArgs = getArgVectorForLanguage(ToLang);
171 EXPECT_TRUE(
172 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
173 }
174
175 struct ImportAction {
176 StringRef FromFilename;
177 StringRef ToFilename;
178 // FIXME: Generalize this to support other node kinds.
179 BindableMatcher<Decl> ImportPredicate;
180
181 ImportAction(StringRef FromFilename, StringRef ToFilename,
182 DeclarationMatcher ImportPredicate)
183 : FromFilename(FromFilename), ToFilename(ToFilename),
184 ImportPredicate(ImportPredicate) {}
185
186 ImportAction(StringRef FromFilename, StringRef ToFilename,
187 const std::string &DeclName)
188 : FromFilename(FromFilename), ToFilename(ToFilename),
189 ImportPredicate(namedDecl(hasName(DeclName))) {}
190 };
191
192 using SingleASTUnit = std::unique_ptr<ASTUnit>;
193 using AllASTUnits = StringMap<SingleASTUnit>;
194
195 struct CodeEntry {
196 std::string CodeSample;
197 Language Lang;
198 };
199
200 using CodeFiles = StringMap<CodeEntry>;
201
202 /// Builds an ASTUnit for one potential compile options set.
203 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
204 ArgVector Args = getArgVectorForLanguage(CE.Lang);
205 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
206 EXPECT_TRUE(AST.get());
207 return AST;
208 }
209
210 /// Test an arbitrary sequence of imports for a set of given in-memory files.
211 /// The verification is done by running VerificationMatcher against a
212 /// specified AST node inside of one of given files.
213 /// \param CodeSamples Map whose key is the file name and the value is the
214 /// file content.
215 /// \param ImportActions Sequence of imports. Each import in sequence
216 /// specifies "from file" and "to file" and a matcher that is used for
217 /// searching a declaration for import in "from file".
218 /// \param FileForFinalCheck Name of virtual file for which the final check is
219 /// applied.
220 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
221 /// FileForFinalCheck for which the verification will be done.
222 /// \param VerificationMatcher Matcher that will be used for verification
223 /// after all imports in sequence are done.
224 void testImportSequence(const CodeFiles &CodeSamples,
225 const std::vector<ImportAction> &ImportActions,
226 StringRef FileForFinalCheck,
227 BindableMatcher<Decl> FinalSelectPredicate,
228 BindableMatcher<Decl> VerificationMatcher) {
229 AllASTUnits AllASTs;
230 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
231 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
232
233 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
234 if (!AllASTs.count(Filename)) {
235 auto Found = CodeSamples.find(Filename);
236 assert(Found != CodeSamples.end() && "Wrong file for import!");
237 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
238 }
239 };
240
241 for (const ImportAction &Action : ImportActions) {
242 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
243 GenASTsIfNeeded(FromFile);
244 GenASTsIfNeeded(ToFile);
245
246 ASTUnit *From = AllASTs[FromFile].get();
247 ASTUnit *To = AllASTs[ToFile].get();
248
249 // Create a new importer if needed.
250 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
251 if (!ImporterRef)
252 ImporterRef.reset(new ASTImporter(
253 To->getASTContext(), To->getFileManager(), From->getASTContext(),
254 From->getFileManager(), false));
255
256 // Find the declaration and import it.
257 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
258 From->getASTContext());
259 EXPECT_TRUE(FoundDecl.size() == 1);
260 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
261 auto Imported = importNode(From, To, *ImporterRef, ToImport);
262 EXPECT_TRUE(Imported);
263 }
264
265 // Find the declaration and import it.
266 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
267 AllASTs[FileForFinalCheck]->getASTContext());
268 EXPECT_TRUE(FoundDecl.size() == 1);
269 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
270 MatchVerifier<Decl> Verifier;
271 EXPECT_TRUE(
272 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
273 }
274};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000275
Gabor Martonf086fa82018-07-17 12:06:36 +0000276template <typename T> RecordDecl *getRecordDecl(T *D) {
277 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
278 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
279};
280
Peter Szecsidedda6f2018-03-30 22:03:29 +0000281// This class provides generic methods to write tests which can check internal
Balazs Keri21f938c2018-07-02 14:14:07 +0000282// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000283// this fixture makes it possible to import from several "From" contexts.
Gabor Marton19f4f392018-06-25 13:04:37 +0000284class ASTImporterTestBase : public ParameterizedTestsFixture {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000285
286 const char *const InputFileName = "input.cc";
287 const char *const OutputFileName = "output.cc";
288
289 // Buffer for the To context, must live in the test scope.
290 std::string ToCode;
291
Gabor Marton26f72a92018-07-12 09:42:05 +0000292 // Represents a "From" translation unit and holds an importer object which we
293 // use to import from this translation unit.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000294 struct TU {
295 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000296 std::string Code;
297 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000298 std::unique_ptr<ASTUnit> Unit;
299 TranslationUnitDecl *TUDecl = nullptr;
Gabor Marton26f72a92018-07-12 09:42:05 +0000300 std::unique_ptr<ASTImporter> Importer;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000301 TU(StringRef Code, StringRef FileName, ArgVector Args)
302 : Code(Code), FileName(FileName),
303 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
304 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000305 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
306 Unit->enableSourceFileDiagnostics();
307 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000308
Gabor Marton6e1510c2018-07-12 11:50:21 +0000309 void lazyInitImporter(ASTUnit *ToAST) {
Gabor Marton26f72a92018-07-12 09:42:05 +0000310 assert(ToAST);
311 if (!Importer) {
312 Importer.reset(new ASTImporter(
313 ToAST->getASTContext(), ToAST->getFileManager(),
314 Unit->getASTContext(), Unit->getFileManager(), false));
315 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000316 assert(&ToAST->getASTContext() == &Importer->getToContext());
317 createVirtualFileIfNeeded(ToAST, FileName, Code);
318 }
319
320 Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
321 lazyInitImporter(ToAST);
Gabor Marton26f72a92018-07-12 09:42:05 +0000322 return Importer->Import(FromDecl);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000323 }
324
325 QualType import(ASTUnit *ToAST, QualType FromType) {
326 lazyInitImporter(ToAST);
327 return Importer->Import(FromType);
Gabor Marton26f72a92018-07-12 09:42:05 +0000328 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000329 };
330
331 // We may have several From contexts and related translation units. In each
332 // AST, the buffers for the source are handled via references and are set
333 // during the creation of the AST. These references must point to a valid
334 // buffer until the AST is alive. Thus, we must use a list in order to avoid
335 // moving of the stored objects because that would mean breaking the
336 // references in the AST. By using a vector a move could happen when the
337 // vector is expanding, with the list we won't have these issues.
338 std::list<TU> FromTUs;
339
Gabor Marton6e1510c2018-07-12 11:50:21 +0000340 void lazyInitToAST(Language ToLang) {
341 if (ToAST)
342 return;
343 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
344 // Build the AST from an empty file.
345 ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
346 ToAST->enableSourceFileDiagnostics();
347 }
348
349 TU *findFromTU(Decl *From) {
350 // Create a virtual file in the To Ctx which corresponds to the file from
351 // which we want to import the `From` Decl. Without this source locations
352 // will be invalid in the ToCtx.
353 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
354 return E.TUDecl == From->getTranslationUnitDecl();
355 });
356 assert(It != FromTUs.end());
357 return &*It;
358 }
359
Peter Szecsidedda6f2018-03-30 22:03:29 +0000360public:
361 // We may have several From context but only one To context.
362 std::unique_ptr<ASTUnit> ToAST;
363
Peter Szecsidedda6f2018-03-30 22:03:29 +0000364 // Creates an AST both for the From and To source code and imports the Decl
365 // of the identifier into the To context.
366 // Must not be called more than once within the same test.
367 std::tuple<Decl *, Decl *>
368 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
369 Language ToLang, StringRef Identifier = DeclToImportID) {
370 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
371 ToArgs = getArgVectorForLanguage(ToLang);
372
373 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
374 TU &FromTU = FromTUs.back();
375
376 ToCode = ToSrcCode;
377 assert(!ToAST);
378 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000379 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000380
Gabor Marton26f72a92018-07-12 09:42:05 +0000381 ASTContext &FromCtx = FromTU.Unit->getASTContext();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000382
383 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
384
Peter Szecsidedda6f2018-03-30 22:03:29 +0000385 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
386 assert(ImportedII && "Declaration with the given identifier "
387 "should be specified in test!");
388 DeclarationName ImportDeclName(ImportedII);
389 SmallVector<NamedDecl *, 4> FoundDecls;
390 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
391 FoundDecls);
392
393 assert(FoundDecls.size() == 1);
394
Gabor Marton26f72a92018-07-12 09:42:05 +0000395 Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
396
Peter Szecsidedda6f2018-03-30 22:03:29 +0000397 assert(Imported);
398 return std::make_tuple(*FoundDecls.begin(), Imported);
399 }
400
Gabor Marton9581c332018-05-23 13:53:36 +0000401 // Creates a TU decl for the given source code which can be used as a From
402 // context. May be called several times in a given test (with different file
403 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000404 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
405 StringRef FileName = "input.cc") {
406 assert(
407 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
408 return E.FileName == FileName;
409 }) == FromTUs.end());
410
411 ArgVector Args = getArgVectorForLanguage(Lang);
412 FromTUs.emplace_back(SrcCode, FileName, Args);
413 TU &Tu = FromTUs.back();
414
415 return Tu.TUDecl;
416 }
417
Gabor Marton9581c332018-05-23 13:53:36 +0000418 // Creates the To context with the given source code and returns the TU decl.
419 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
420 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
421 ToCode = ToSrcCode;
422 assert(!ToAST);
423 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000424 ToAST->enableSourceFileDiagnostics();
Gabor Marton9581c332018-05-23 13:53:36 +0000425
426 return ToAST->getASTContext().getTranslationUnitDecl();
427 }
428
Peter Szecsidedda6f2018-03-30 22:03:29 +0000429 // Import the given Decl into the ToCtx.
430 // May be called several times in a given test.
431 // The different instances of the param From may have different ASTContext.
432 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000433 lazyInitToAST(ToLang);
434 TU *FromTU = findFromTU(From);
435 return FromTU->import(ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000436 }
437
Gabor Marton6e1510c2018-07-12 11:50:21 +0000438 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
439 lazyInitToAST(ToLang);
440 TU *FromTU = findFromTU(TUDecl);
441 return FromTU->import(ToAST.get(), FromType);
442 }
443
Peter Szecsidedda6f2018-03-30 22:03:29 +0000444 ~ASTImporterTestBase() {
445 if (!::testing::Test::HasFailure()) return;
446
447 for (auto &Tu : FromTUs) {
448 assert(Tu.Unit);
449 llvm::errs() << "FromAST:\n";
450 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
451 llvm::errs() << "\n";
452 }
453 if (ToAST) {
454 llvm::errs() << "ToAST:\n";
455 ToAST->getASTContext().getTranslationUnitDecl()->dump();
456 }
457 }
458};
459
Gabor Marton19f4f392018-06-25 13:04:37 +0000460struct ImportExpr : TestImportBase {};
461struct ImportType : TestImportBase {};
462struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000463
Gabor Marton5254e642018-06-27 13:32:50 +0000464struct CanonicalRedeclChain : ASTImporterTestBase {};
465
466TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
467 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
468 auto Pattern = functionDecl(hasName("f"));
469 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
470
471 auto Redecls = getCanonicalForwardRedeclChain(D0);
472 ASSERT_EQ(Redecls.size(), 1u);
473 EXPECT_EQ(D0, Redecls[0]);
474}
475
476TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
477 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
478 auto Pattern = functionDecl(hasName("f"));
479 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
480 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
481 FunctionDecl *D1 = D2->getPreviousDecl();
482
483 auto Redecls = getCanonicalForwardRedeclChain(D0);
484 ASSERT_EQ(Redecls.size(), 3u);
485 EXPECT_EQ(D0, Redecls[0]);
486 EXPECT_EQ(D1, Redecls[1]);
487 EXPECT_EQ(D2, Redecls[2]);
488}
489
490TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
491 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
492 auto Pattern = functionDecl(hasName("f"));
493 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
494 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
495 FunctionDecl *D1 = D2->getPreviousDecl();
496
497 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
498 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
499 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
500
501 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
502 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
503}
504
505
Gabor Marton19f4f392018-06-25 13:04:37 +0000506TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000507 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000508 testImport(
509 "void declToImport() { (void)\"foo\"; }",
510 Lang_CXX, "", Lang_CXX, Verifier,
511 functionDecl(hasDescendant(
512 stringLiteral(hasType(asString("const char [4]"))))));
513 testImport(
514 "void declToImport() { (void)L\"foo\"; }",
515 Lang_CXX, "", Lang_CXX, Verifier,
516 functionDecl(hasDescendant(
517 stringLiteral(hasType(asString("const wchar_t [4]"))))));
518 testImport(
519 "void declToImport() { (void) \"foo\" \"bar\"; }",
520 Lang_CXX, "", Lang_CXX, Verifier,
521 functionDecl(hasDescendant(
522 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000523}
524
Gabor Marton19f4f392018-06-25 13:04:37 +0000525TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000526 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000527 testImport(
528 "void declToImport() { (void)__null; }",
529 Lang_CXX, "", Lang_CXX, Verifier,
530 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000531}
532
Gabor Marton19f4f392018-06-25 13:04:37 +0000533TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000534 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000535 testImport(
536 "void declToImport() { (void)nullptr; }",
537 Lang_CXX11, "", Lang_CXX11, Verifier,
538 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000539}
540
541
Gabor Marton19f4f392018-06-25 13:04:37 +0000542TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000543 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000544 testImport(
545 "void declToImport() { (void)1.0; }",
546 Lang_C, "", Lang_C, Verifier,
547 functionDecl(hasDescendant(
548 floatLiteral(equals(1.0), hasType(asString("double"))))));
549 testImport(
550 "void declToImport() { (void)1.0e-5f; }",
551 Lang_C, "", Lang_C, Verifier,
552 functionDecl(hasDescendant(
553 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000554}
555
Gabor Marton19f4f392018-06-25 13:04:37 +0000556TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000557 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000558 testImport(
559 "void declToImport() {"
560 " struct s { int x; long y; unsigned z; }; "
561 " (void)(struct s){ 42, 0L, 1U }; }",
562 Lang_CXX, "", Lang_CXX, Verifier,
563 functionDecl(hasDescendant(
564 compoundLiteralExpr(
565 hasType(asString("struct s")),
566 has(initListExpr(
567 hasType(asString("struct s")),
568 has(integerLiteral(
569 equals(42), hasType(asString("int")))),
570 has(integerLiteral(
571 equals(0), hasType(asString("long")))),
572 has(integerLiteral(
573 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000574}
575
Gabor Marton19f4f392018-06-25 13:04:37 +0000576TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000577 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000578 testImport(
579 "class declToImport { void f() { (void)this; } };",
580 Lang_CXX, "", Lang_CXX, Verifier,
581 cxxRecordDecl(
582 hasMethod(
583 hasDescendant(
584 cxxThisExpr(
585 hasType(
586 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000587}
588
Gabor Marton19f4f392018-06-25 13:04:37 +0000589TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000590 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000591 testImport(
592 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
593 Lang_C, "", Lang_C, Verifier,
594 functionDecl(hasDescendant(
595 atomicExpr(
596 has(ignoringParenImpCasts(
597 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
598 hasType(asString("int *"))))),
599 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000600}
601
Gabor Marton19f4f392018-06-25 13:04:37 +0000602TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000603 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000604 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000605 "void declToImport() { loop: goto loop; (void)&&loop; }",
606 Lang_C, "", Lang_C, Verifier,
607 functionDecl(
608 hasDescendant(
609 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
610 hasDescendant(
611 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000612}
613
614AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
615 internal::Matcher<NamedDecl>, InnerMatcher) {
616 const NamedDecl *Template = Node.getTemplatedDecl();
617 return Template && InnerMatcher.matches(*Template, Finder, Builder);
618}
619
Gabor Marton19f4f392018-06-25 13:04:37 +0000620TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000621 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000622 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000623 "template<typename T> class dummy { void f() { dummy X(*this); } };"
624 "typedef dummy<int> declToImport;"
625 "template class dummy<int>;",
626 Lang_CXX, "", Lang_CXX, Verifier,
627 typedefDecl(hasType(templateSpecializationType(
628 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
629 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
630 hasName("f"),
631 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
632 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
633 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000634 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000635}
636
Gabor Marton19f4f392018-06-25 13:04:37 +0000637TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000638 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000639 testImport(
640 "void declToImport() { int b; switch (b) { case 1: break; } }",
641 Lang_C, "", Lang_C, Verifier,
642 functionDecl(hasDescendant(
643 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000644}
645
Gabor Marton19f4f392018-06-25 13:04:37 +0000646TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000647 MatchVerifier<Decl> Verifier;
648 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000649 testImport(
650 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
651 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000652 functionDecl(hasDescendant(
653 varDecl(
654 hasName("C"),
655 hasType(asString("int")),
656 hasInitializer(
657 stmtExpr(
658 hasAnySubstatement(declStmt(hasSingleDecl(
659 varDecl(
660 hasName("X"),
661 hasType(asString("int")),
662 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000663 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000664 hasDescendant(
665 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000666}
667
Gabor Marton19f4f392018-06-25 13:04:37 +0000668TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000669 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000670 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000671 "void declToImport() { (void)(true ? 1 : -5); }",
672 Lang_CXX, "", Lang_CXX, Verifier,
673 functionDecl(hasDescendant(
674 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000675 hasCondition(cxxBoolLiteral(equals(true))),
676 hasTrueExpression(integerLiteral(equals(1))),
677 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000678 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
679 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000680}
681
Gabor Marton19f4f392018-06-25 13:04:37 +0000682TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000683 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000684 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000685 "void declToImport() { (void)(1 ?: -5); }",
686 Lang_CXX, "", Lang_CXX, Verifier,
687 functionDecl(hasDescendant(
688 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000689 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000690 implicitCastExpr(
691 hasSourceExpression(opaqueValueExpr(
692 hasSourceExpression(integerLiteral(equals(1))))),
693 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000694 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000695 opaqueValueExpr(
696 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000697 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000698 unaryOperator(
699 hasOperatorName("-"),
700 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000701}
702
Gabor Marton19f4f392018-06-25 13:04:37 +0000703TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000704 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000705 testImport(
706 "void declToImport() {"
707 " struct point { double x; double y; };"
708 " struct point ptarray[10] = "
709 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
710 Lang_C, "", Lang_C, Verifier,
711 functionDecl(hasDescendant(
712 initListExpr(
713 has(designatedInitExpr(
714 designatorCountIs(2),
715 has(floatLiteral(equals(1.0))),
716 has(integerLiteral(equals(2))))),
717 has(designatedInitExpr(
718 designatorCountIs(2),
719 has(floatLiteral(equals(2.0))),
720 has(integerLiteral(equals(2))))),
721 has(designatedInitExpr(
722 designatorCountIs(2),
723 has(floatLiteral(equals(1.0))),
724 has(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000725}
726
727
Gabor Marton19f4f392018-06-25 13:04:37 +0000728TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000729 MatchVerifier<Decl> Verifier;
730 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000731 testImport(
732 "void declToImport() { (void)__func__; }",
733 Lang_CXX, "", Lang_CXX, Verifier,
734 functionDecl(hasDescendant(
735 predefinedExpr(
736 hasType(
737 asString("const char [13]")),
738 has(stringLiteral(hasType(
739 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000740}
741
Gabor Marton19f4f392018-06-25 13:04:37 +0000742TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000743 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000744 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000745 "void declToImport() {"
746 " struct point { double x; double y; };"
747 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
748 " [0].x = 1.0 }; }",
749 Lang_CXX, "", Lang_CXX, Verifier,
750 functionDecl(hasDescendant(
751 initListExpr(
752 has(
753 cxxConstructExpr(
754 requiresZeroInitialization())),
755 has(
756 initListExpr(
757 hasType(asString("struct point")),
758 has(floatLiteral(equals(1.0))),
759 has(implicitValueInitExpr(
760 hasType(asString("double")))))),
761 has(
762 initListExpr(
763 hasType(asString("struct point")),
764 has(floatLiteral(equals(2.0))),
765 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000766}
767
768
Aleksei Sidorina693b372016-09-28 10:16:56 +0000769const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
770
Gabor Marton19f4f392018-06-25 13:04:37 +0000771TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000772 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000773 testImport(
774 "void declToImport(__builtin_va_list list, ...) {"
775 " (void)__builtin_va_arg(list, int); }",
776 Lang_CXX, "", Lang_CXX, Verifier,
777 functionDecl(hasDescendant(
778 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000779}
780
Gabor Marton19f4f392018-06-25 13:04:37 +0000781TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000782 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000783 testImport(
784 "struct C {};"
785 "void declToImport() { C c = C(); }",
786 Lang_CXX, "", Lang_CXX, Verifier,
787 functionDecl(hasDescendant(
788 exprWithCleanups(has(cxxConstructExpr(
789 has(materializeTemporaryExpr(has(implicitCastExpr(
790 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000791}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000792
Gabor Marton19f4f392018-06-25 13:04:37 +0000793TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000794 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000795 testImport(
796 "void declToImport() { typedef _Atomic(int) a_int; }",
797 Lang_CXX11, "", Lang_CXX11, Verifier,
798 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000799}
800
Gabor Marton19f4f392018-06-25 13:04:37 +0000801TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000802 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000803 testImport(
804 "template <typename T> void declToImport() { };",
805 Lang_CXX, "", Lang_CXX, Verifier,
806 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000807}
808
809const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
810 cxxDependentScopeMemberExpr;
811
Gabor Marton19f4f392018-06-25 13:04:37 +0000812TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000813 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000814 testImport(
815 "template <typename T> struct C { T t; };"
816 "template <typename T> void declToImport() {"
817 " C<T> d;"
818 " (void)d.t;"
819 "}"
820 "void instantiate() { declToImport<int>(); }",
821 Lang_CXX, "", Lang_CXX, Verifier,
822 functionTemplateDecl(hasDescendant(
823 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
824 testImport(
825 "template <typename T> struct C { T t; };"
826 "template <typename T> void declToImport() {"
827 " C<T> d;"
828 " (void)(&d)->t;"
829 "}"
830 "void instantiate() { declToImport<int>(); }",
831 Lang_CXX, "", Lang_CXX, Verifier,
832 functionTemplateDecl(hasDescendant(
833 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000834}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000835
Gabor Marton19f4f392018-06-25 13:04:37 +0000836TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000837 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000838 testImport(
839 "template <int K>"
840 "struct dummy { static const int i = K; };"
841 "template <int K> using dummy2 = dummy<K>;"
842 "int declToImport() { return dummy2<3>::i; }",
843 Lang_CXX11, "", Lang_CXX11, Verifier,
844 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000845 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000846 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
847}
848
849const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
850 varTemplateSpecializationDecl;
851
Gabor Marton19f4f392018-06-25 13:04:37 +0000852TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000853 MatchVerifier<Decl> Verifier;
854 testImport(
855 "template <typename T>"
856 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000857 "void declToImport() { (void)pi<int>; }",
858 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000859 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000860 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000861 unless(hasAncestor(translationUnitDecl(has(varDecl(
862 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000863}
864
Gabor Marton19f4f392018-06-25 13:04:37 +0000865TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000866 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000867 testImport(
868 "template <typename... Args>"
869 "struct dummy {"
870 " dummy(Args... args) {}"
871 " static const int i = 4;"
872 "};"
873 "int declToImport() { return dummy<int>::i; }",
874 Lang_CXX11, "", Lang_CXX11, Verifier,
875 functionDecl(hasDescendant(
876 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000877}
878
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000879const internal::VariadicDynCastAllOfMatcher<Type,
880 DependentTemplateSpecializationType>
881 dependentTemplateSpecializationType;
882
Gabor Marton19f4f392018-06-25 13:04:37 +0000883TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000884 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000885 testImport(
886 "template<typename T>"
887 "struct A;"
888 "template<typename T>"
889 "struct declToImport {"
890 " typename A<T>::template B<T> a;"
891 "};",
892 Lang_CXX, "", Lang_CXX, Verifier,
893 classTemplateDecl(has(cxxRecordDecl(has(
894 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000895}
896
897const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
898 sizeOfPackExpr;
899
Gabor Marton19f4f392018-06-25 13:04:37 +0000900TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000901 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000902 testImport(
903 "template <typename... Ts>"
904 "void declToImport() {"
905 " const int i = sizeof...(Ts);"
906 "};"
907 "void g() { declToImport<int>(); }",
908 Lang_CXX11, "", Lang_CXX11, Verifier,
909 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000910 testImport(
911 "template <typename... Ts>"
912 "using X = int[sizeof...(Ts)];"
913 "template <typename... Us>"
914 "struct Y {"
915 " X<Us..., int, double, int, Us...> f;"
916 "};"
917 "Y<float, int> declToImport;",
918 Lang_CXX11, "", Lang_CXX11, Verifier,
919 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
920 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
921}
922
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000923/// \brief Matches __builtin_types_compatible_p:
924/// GNU extension to check equivalent types
925/// Given
926/// \code
927/// __builtin_types_compatible_p(int, int)
928/// \endcode
929// will generate TypeTraitExpr <...> 'int'
930const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
931
Gabor Marton19f4f392018-06-25 13:04:37 +0000932TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000933 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000934 testImport(
935 "void declToImport() { "
936 " (void)__builtin_types_compatible_p(int, int);"
937 "}",
938 Lang_C, "", Lang_C, Verifier,
939 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000940}
941
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000942const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
943
Gabor Marton19f4f392018-06-25 13:04:37 +0000944TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000945 MatchVerifier<Decl> Verifier;
946 testImport(
947 "namespace std { class type_info {}; }"
948 "void declToImport() {"
949 " int x;"
950 " auto a = typeid(int); auto b = typeid(x);"
951 "}",
952 Lang_CXX11, "", Lang_CXX11, Verifier,
953 functionDecl(
954 hasDescendant(varDecl(
955 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
956 hasDescendant(varDecl(
957 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
958}
959
Gabor Marton19f4f392018-06-25 13:04:37 +0000960TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000961 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000962 testImport(
963 "template<typename T> struct declToImport {"
964 " void m() { (void)__is_pod(T); }"
965 "};"
966 "void f() { declToImport<int>().m(); }",
967 Lang_CXX11, "", Lang_CXX11, Verifier,
968 classTemplateDecl(has(cxxRecordDecl(has(
969 functionDecl(hasDescendant(
970 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000971}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000972
Gabor Marton6e1510c2018-07-12 11:50:21 +0000973TEST_P(ImportDecl, ImportRecordDeclInFunc) {
974 MatchVerifier<Decl> Verifier;
975 testImport("int declToImport() { "
976 " struct data_t {int a;int b;};"
977 " struct data_t d;"
978 " return 0;"
979 "}",
980 Lang_C, "", Lang_C, Verifier,
981 functionDecl(hasBody(compoundStmt(
982 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
983}
984
985TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
986 Decl *FromTU = getTuDecl("int declToImport() { "
987 " struct data_t {int a;int b;};"
988 " struct data_t d;"
989 " return 0;"
990 "}",
991 Lang_C, "input.c");
992 auto FromVar =
993 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
994 ASSERT_TRUE(FromVar);
995 auto ToType =
996 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
997 EXPECT_FALSE(ToType.isNull());
998}
999
1000TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
1001 // This construct is not supported by ASTImporter.
1002 Decl *FromTU =
1003 getTuDecl("int declToImport(struct data_t{int a;int b;} *d){ return 0; }",
1004 Lang_C, "input.c");
1005 auto From = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1006 ASSERT_TRUE(From);
1007 auto To = Import(From, Lang_C);
1008 EXPECT_EQ(To, nullptr);
1009}
1010
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001011const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1012 cxxPseudoDestructorExpr;
1013
Gabor Marton19f4f392018-06-25 13:04:37 +00001014TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001015 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001016 testImport(
1017 "typedef int T;"
1018 "void declToImport(int *p) {"
1019 " T t;"
1020 " p->T::~T();"
1021 "}",
1022 Lang_CXX, "", Lang_CXX, Verifier,
1023 functionDecl(hasDescendant(
1024 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001025}
1026
Gabor Marton19f4f392018-06-25 13:04:37 +00001027TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001028 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001029 testImport(
1030 "namespace foo { int bar; }"
1031 "void declToImport() { using foo::bar; }",
1032 Lang_CXX, "", Lang_CXX, Verifier,
1033 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001034}
1035
1036/// \brief Matches shadow declarations introduced into a scope by a
1037/// (resolved) using declaration.
1038///
1039/// Given
1040/// \code
1041/// namespace n { int f; }
1042/// namespace declToImport { using n::f; }
1043/// \endcode
1044/// usingShadowDecl()
1045/// matches \code f \endcode
1046const internal::VariadicDynCastAllOfMatcher<Decl,
1047 UsingShadowDecl> usingShadowDecl;
1048
Gabor Marton19f4f392018-06-25 13:04:37 +00001049TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001050 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001051 testImport(
1052 "namespace foo { int bar; }"
1053 "namespace declToImport { using foo::bar; }",
1054 Lang_CXX, "", Lang_CXX, Verifier,
1055 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001056}
1057
Gabor Marton19f4f392018-06-25 13:04:37 +00001058TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001059 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001060 testImport(
1061 "template<typename T> int foo();"
1062 "template <typename T> void declToImport() {"
1063 " (void)::foo<T>;"
1064 " (void)::template foo<T>;"
1065 "}"
1066 "void instantiate() { declToImport<int>(); }",
1067 Lang_CXX, "", Lang_CXX, Verifier,
1068 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001069}
1070
Gabor Marton19f4f392018-06-25 13:04:37 +00001071TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001072 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001073 testImport(
1074 "template <typename T> struct C { T t; };"
1075 "template <typename T> void declToImport() {"
1076 " C<T> d;"
1077 " d.t = T();"
1078 "}"
1079 "void instantiate() { declToImport<int>(); }",
1080 Lang_CXX, "", Lang_CXX, Verifier,
1081 functionTemplateDecl(hasDescendant(
1082 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1083 testImport(
1084 "template <typename T> struct C { T t; };"
1085 "template <typename T> void declToImport() {"
1086 " C<T> d;"
1087 " (&d)->t = T();"
1088 "}"
1089 "void instantiate() { declToImport<int>(); }",
1090 Lang_CXX, "", Lang_CXX, Verifier,
1091 functionTemplateDecl(hasDescendant(
1092 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001093}
1094
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001095/// Check that function "declToImport()" (which is the templated function
1096/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1097/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001098TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001099 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001100 testImport(
1101 "template <typename T> void declToImport() { T a = 1; }"
1102 "void instantiate() { declToImport<int>(); }",
1103 Lang_CXX, "", Lang_CXX, Verifier,
1104 functionTemplateDecl(hasAncestor(translationUnitDecl(
1105 unless(has(functionDecl(hasName("declToImport"))))))));
1106 testImport(
1107 "template <typename T> struct declToImport { T t; };"
1108 "void instantiate() { declToImport<int>(); }",
1109 Lang_CXX, "", Lang_CXX, Verifier,
1110 classTemplateDecl(hasAncestor(translationUnitDecl(
1111 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001112}
1113
Gabor Marton19f4f392018-06-25 13:04:37 +00001114TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001115 MatchVerifier<Decl> Verifier;
1116 auto Code =
1117 R"s(
1118 struct declToImport {
1119 template <typename T0> struct X;
1120 template <typename T0> struct X<T0 *> {};
1121 };
1122 )s";
1123 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1124 recordDecl(has(classTemplateDecl()),
1125 has(classTemplateSpecializationDecl())));
1126}
1127
Gabor Marton19f4f392018-06-25 13:04:37 +00001128TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001129 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001130 testImport(
1131 "class declToImport {"
1132 " void f() { *this = declToImport(); }"
1133 "};",
1134 Lang_CXX, "", Lang_CXX, Verifier,
1135 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1136 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001137}
1138
Gabor Marton19f4f392018-06-25 13:04:37 +00001139TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001140 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001141 testImport(
1142 "template<typename T, int Size> class declToImport {"
1143 " T data[Size];"
1144 "};",
1145 Lang_CXX, "", Lang_CXX, Verifier,
1146 classTemplateDecl(has(cxxRecordDecl(
1147 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001148}
1149
Gabor Martona0df7a92018-05-30 09:19:26 +00001150TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1151 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1152 auto From =
1153 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1154 ASSERT_TRUE(From);
1155 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1156 ASSERT_TRUE(To);
1157 Decl *ToTemplated = To->getTemplatedDecl();
1158 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1159 EXPECT_TRUE(ToTemplated1);
1160 EXPECT_EQ(ToTemplated1, ToTemplated);
1161}
1162
Gabor Marton26f72a92018-07-12 09:42:05 +00001163TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001164 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1165 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1166 FromTU, functionTemplateDecl());
1167 ASSERT_TRUE(From);
1168 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1169 ASSERT_TRUE(To);
1170 Decl *ToTemplated = To->getTemplatedDecl();
1171 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1172 EXPECT_TRUE(ToTemplated1);
1173 EXPECT_EQ(ToTemplated1, ToTemplated);
1174}
1175
1176TEST_P(ASTImporterTestBase,
1177 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1178 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1179 auto FromFT =
1180 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1181 ASSERT_TRUE(FromFT);
1182
1183 auto ToTemplated =
1184 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1185 EXPECT_TRUE(ToTemplated);
1186 auto ToTU = ToTemplated->getTranslationUnitDecl();
1187 auto ToFT =
1188 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1189 EXPECT_TRUE(ToFT);
1190}
1191
1192TEST_P(ASTImporterTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001193 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001194 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1195 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1196 FromTU, functionTemplateDecl());
1197 ASSERT_TRUE(FromFT);
1198
1199 auto ToTemplated =
1200 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1201 EXPECT_TRUE(ToTemplated);
1202 auto ToTU = ToTemplated->getTranslationUnitDecl();
1203 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1204 ToTU, functionTemplateDecl());
1205 EXPECT_TRUE(ToFT);
1206}
1207
Gabor Martona0df7a92018-05-30 09:19:26 +00001208TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1209 auto Code =
1210 R"(
1211 namespace x {
1212 template<class X> struct S1{};
1213 template<class X> struct S2{};
1214 template<class X> struct S3{};
1215 }
1216 )";
1217 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1218 auto FromNs =
1219 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1220 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1221 ASSERT_TRUE(ToNs);
1222 auto From =
1223 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1224 classTemplateDecl(
1225 hasName("S2")));
1226 auto To =
1227 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1228 classTemplateDecl(
1229 hasName("S2")));
1230 ASSERT_TRUE(From);
1231 ASSERT_TRUE(To);
1232 auto ToTemplated = To->getTemplatedDecl();
1233 auto ToTemplated1 =
1234 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1235 EXPECT_TRUE(ToTemplated1);
1236 ASSERT_EQ(ToTemplated1, ToTemplated);
1237}
1238
Gabor Marton26f72a92018-07-12 09:42:05 +00001239TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001240 Decl *From, *To;
1241 std::tie(From, To) = getImportedDecl(
1242 R"(
1243 template <typename T> struct X {};
1244
1245 void declToImport(int y, X<int> &x) {}
1246
1247 template <> struct X<int> {
1248 void g() {
1249 X<int> x;
1250 declToImport(0, x);
1251 }
1252 };
1253 )",
1254 Lang_CXX, "", Lang_CXX);
1255
1256 MatchVerifier<Decl> Verifier;
1257 auto Matcher = functionDecl(hasName("declToImport"),
1258 parameterCountIs(2),
1259 hasParameter(0, hasName("y")),
1260 hasParameter(1, hasName("x")),
1261 hasParameter(1, hasType(asString("X<int> &"))));
1262 ASSERT_TRUE(Verifier.match(From, Matcher));
1263 EXPECT_TRUE(Verifier.match(To, Matcher));
1264}
1265
1266TEST_P(ASTImporterTestBase,
1267 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1268 Decl *From, *To;
1269 std::tie(From, To) =
1270 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1271 "void instantiate() { declToImport<int>(); }",
1272 Lang_CXX, "", Lang_CXX);
1273
1274 auto Check = [](Decl *D) -> bool {
1275 auto TU = D->getTranslationUnitDecl();
1276 for (auto Child : TU->decls()) {
1277 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1278 if (FD->getNameAsString() == "declToImport") {
1279 GTEST_NONFATAL_FAILURE_(
1280 "TU should not contain any FunctionDecl with name declToImport");
1281 return false;
1282 }
1283 }
1284 }
1285 return true;
1286 };
1287
1288 ASSERT_TRUE(Check(From));
1289 EXPECT_TRUE(Check(To));
1290}
1291
1292TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1293 Decl *From, *To;
1294 std::tie(From, To) =
1295 getImportedDecl("template <typename T> struct declToImport { T t; };"
1296 "void instantiate() { declToImport<int>(); }",
1297 Lang_CXX, "", Lang_CXX);
1298
1299 auto Check = [](Decl *D) -> bool {
1300 auto TU = D->getTranslationUnitDecl();
1301 for (auto Child : TU->decls()) {
1302 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1303 if (RD->getNameAsString() == "declToImport") {
1304 GTEST_NONFATAL_FAILURE_(
1305 "TU should not contain any CXXRecordDecl with name declToImport");
1306 return false;
1307 }
1308 }
1309 }
1310 return true;
1311 };
1312
1313 ASSERT_TRUE(Check(From));
1314 EXPECT_TRUE(Check(To));
1315}
1316
1317TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1318 Decl *From, *To;
1319 std::tie(From, To) =
1320 getImportedDecl(
1321 "template <typename T> struct X {};"
1322 "template <typename T> using declToImport = X<T>;"
1323 "void instantiate() { declToImport<int> a; }",
1324 Lang_CXX11, "", Lang_CXX11);
1325
1326 auto Check = [](Decl *D) -> bool {
1327 auto TU = D->getTranslationUnitDecl();
1328 for (auto Child : TU->decls()) {
1329 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1330 if (AD->getNameAsString() == "declToImport") {
1331 GTEST_NONFATAL_FAILURE_(
1332 "TU should not contain any TypeAliasDecl with name declToImport");
1333 return false;
1334 }
1335 }
1336 }
1337 return true;
1338 };
1339
1340 ASSERT_TRUE(Check(From));
1341 EXPECT_TRUE(Check(To));
1342}
1343
1344TEST_P(
1345 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001346 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001347
1348 Decl *From, *To;
1349 std::tie(From, To) = getImportedDecl(
1350 R"(
1351 template<class T>
1352 class Base {};
1353 class declToImport : public Base<declToImport> {};
1354 )",
1355 Lang_CXX, "", Lang_CXX);
1356
1357 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1358 auto Pattern =
1359 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1360 ASSERT_TRUE(
1361 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1362 EXPECT_TRUE(
1363 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1364
1365 // Check that the ClassTemplateSpecializationDecl is the child of the
1366 // ClassTemplateDecl.
1367 Pattern = translationUnitDecl(has(classTemplateDecl(
1368 hasName("Base"), has(classTemplateSpecializationDecl()))));
1369 ASSERT_TRUE(
1370 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1371 EXPECT_TRUE(
1372 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1373}
1374
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001375AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1376 size_t Index = 0;
1377 for (FieldDecl *Field : Node.fields()) {
1378 if (Index == Order.size())
1379 return false;
1380 if (Field->getName() != Order[Index])
1381 return false;
1382 ++Index;
1383 }
1384 return Index == Order.size();
1385}
1386
Peter Szecsidedda6f2018-03-30 22:03:29 +00001387TEST_P(ASTImporterTestBase,
1388 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1389 Decl *From, *To;
1390 std::tie(From, To) = getImportedDecl(
1391 R"(
1392 namespace NS {
1393 template<class T>
1394 class X {};
1395 template class X<int>;
1396 }
1397 )",
1398 Lang_CXX, "", Lang_CXX, "NS");
1399
1400 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1401 // ClassTemplateDecl.
1402 auto Pattern = namespaceDecl(has(classTemplateDecl(
1403 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1404 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1405 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1406
1407 // Check that the ClassTemplateSpecializationDecl is the child of the
1408 // NamespaceDecl.
1409 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1410 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1411 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1412}
1413
1414TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1415 Decl *From, *To;
1416 std::tie(From, To) =
1417 getImportedDecl(
1418 "struct declToImport { int a; int b; };",
1419 Lang_CXX11, "", Lang_CXX11);
1420
1421 MatchVerifier<Decl> Verifier;
1422 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1423 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1424}
1425
1426TEST_P(ASTImporterTestBase,
1427 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1428 Decl *From, *To;
1429 std::tie(From, To) = getImportedDecl(
1430 // The original recursive algorithm of ASTImporter first imports 'c' then
1431 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1432 R"s(
1433 struct declToImport {
1434 int a = c + b;
1435 int b = 1;
1436 int c = 2;
1437 };
1438 )s",
1439 Lang_CXX11, "", Lang_CXX11);
1440
1441 MatchVerifier<Decl> Verifier;
1442 ASSERT_TRUE(
1443 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1444 EXPECT_TRUE(
1445 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1446}
1447
Gabor Martonde8bf262018-05-17 09:46:07 +00001448TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001449 Decl *From, *To;
1450 std::tie(From, To) = getImportedDecl(
1451 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001452 struct declToImport {
1453 };
1454 )",
1455 Lang_CXX, "", Lang_CXX);
1456
1457 MatchVerifier<Decl> Verifier;
1458 // Match the implicit Decl.
1459 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1460 ASSERT_TRUE(Verifier.match(From, Matcher));
1461 EXPECT_TRUE(Verifier.match(To, Matcher));
1462}
1463
1464TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1465 Decl *From, *To;
1466 std::tie(From, To) = getImportedDecl(
1467 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001468 template <typename U>
1469 struct declToImport {
1470 };
1471 )",
1472 Lang_CXX, "", Lang_CXX);
1473
1474 MatchVerifier<Decl> Verifier;
1475 // Match the implicit Decl.
1476 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1477 ASSERT_TRUE(Verifier.match(From, Matcher));
1478 EXPECT_TRUE(Verifier.match(To, Matcher));
1479}
1480
1481TEST_P(
1482 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001483 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001484 Decl *From, *To;
1485 std::tie(From, To) = getImportedDecl(
1486 R"(
1487 template<class T>
1488 class Base {};
1489 class declToImport : public Base<declToImport> {};
1490 )",
1491 Lang_CXX, "", Lang_CXX);
1492
1493 auto hasImplicitClass = has(cxxRecordDecl());
1494 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1495 hasName("Base"),
1496 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1497 ASSERT_TRUE(
1498 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1499 EXPECT_TRUE(
1500 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1501}
1502
1503TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1504 Decl *From, *To;
1505 std::tie(From, To) =
1506 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1507
1508 MatchVerifier<Decl> Verifier;
1509 auto Matcher = functionDecl();
1510 ASSERT_TRUE(Verifier.match(From, Matcher));
1511 EXPECT_TRUE(Verifier.match(To, Matcher));
1512 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1513}
1514
Gabor Marton2ae9da32018-05-18 15:46:18 +00001515TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001516 Decl *FromTU = getTuDecl(
1517 R"(
1518 struct X {};
1519 void operator<<(int, X);
1520 )",
1521 Lang_CXX);
1522 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1523 const Decl *To = Import(From, Lang_CXX);
1524 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1525}
1526
1527TEST_P(ASTImporterTestBase,
1528 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1529 Decl *From, *To;
1530 std::tie(From, To) = getImportedDecl(
1531 R"(
1532 template<class T>
1533 class Base { int a; };
1534 class declToImport : Base<declToImport> {};
1535 )",
1536 Lang_CXX, "", Lang_CXX);
1537
1538 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1539 hasName("Base"),
1540 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1541 ASSERT_TRUE(
1542 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1543 EXPECT_TRUE(
1544 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1545}
1546
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001547TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1548 {
1549 Decl *FromTU = getTuDecl(
1550 R"(
1551 template <typename T>
1552 struct B;
1553 )",
1554 Lang_CXX, "input0.cc");
1555 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1556 FromTU, classTemplateDecl(hasName("B")));
1557
1558 Import(FromD, Lang_CXX);
1559 }
1560
1561 {
1562 Decl *FromTU = getTuDecl(
1563 R"(
1564 template <typename T>
1565 struct B {
1566 void f();
1567 };
1568 )",
1569 Lang_CXX, "input1.cc");
1570 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1571 FromTU, functionDecl(hasName("f")));
1572 Import(FromD, Lang_CXX);
1573 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1574 FromTU, classTemplateDecl(hasName("B")));
1575 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1576 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1577 }
1578}
1579
Gabor Marton9581c332018-05-23 13:53:36 +00001580TEST_P(ASTImporterTestBase,
1581 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1582 Decl *ToTU = getToTuDecl(
1583 R"(
1584 template <typename T>
1585 struct B {
1586 void f();
1587 };
1588
1589 template <typename T>
1590 struct B;
1591 )",
1592 Lang_CXX);
1593 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1594 [](const ClassTemplateDecl *T) {
1595 return T->isThisDeclarationADefinition();
1596 })
1597 .match(ToTU, classTemplateDecl()));
1598
1599 Decl *FromTU = getTuDecl(
1600 R"(
1601 template <typename T>
1602 struct B {
1603 void f();
1604 };
1605 )",
1606 Lang_CXX, "input1.cc");
1607 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1608 FromTU, classTemplateDecl(hasName("B")));
1609
1610 Import(FromD, Lang_CXX);
1611
1612 // We should have only one definition.
1613 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1614 [](const ClassTemplateDecl *T) {
1615 return T->isThisDeclarationADefinition();
1616 })
1617 .match(ToTU, classTemplateDecl()));
1618}
1619
1620TEST_P(ASTImporterTestBase,
1621 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1622 Decl *ToTU = getToTuDecl(
1623 R"(
1624 struct B {
1625 void f();
1626 };
1627
1628 struct B;
1629 )",
1630 Lang_CXX);
1631 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001632 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001633
1634 Decl *FromTU = getTuDecl(
1635 R"(
1636 struct B {
1637 void f();
1638 };
1639 )",
1640 Lang_CXX, "input1.cc");
1641 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1642 FromTU, cxxRecordDecl(hasName("B")));
1643
1644 Import(FromD, Lang_CXX);
1645
1646 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001647 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001648}
1649
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001650static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1651 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1652 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1653 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1654 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1655}
1656static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1657 SourceManager &SM1, SourceManager &SM2) {
1658 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1659 FullSourceLoc{ Range2.getBegin(), SM2 });
1660 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1661 FullSourceLoc{ Range2.getEnd(), SM2 });
1662}
1663TEST_P(ASTImporterTestBase, ImportSourceLocs) {
1664 Decl *FromTU = getTuDecl(
1665 R"(
1666 #define MFOO(arg) arg = arg + 1
1667
1668 void foo() {
1669 int a = 5;
1670 MFOO(a);
1671 }
1672 )",
1673 Lang_CXX);
1674 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1675 auto ToD = Import(FromD, Lang_CXX);
1676
1677 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1678 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1679 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1680 auto FromRHS =
1681 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1682
1683 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1684 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1685 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1686 FromSM);
1687 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1688 FromSM);
1689 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1690 FromSM);
1691}
1692
Rafael Stahla0010472018-07-09 08:40:17 +00001693TEST_P(ASTImporterTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001694 Decl *FromTU = getTuDecl(
1695 R"(
1696 #define FUNC_INT void declToImport
1697 #define FUNC FUNC_INT
1698 FUNC(int a);
1699 )",
1700 Lang_CXX);
1701 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1702 auto ToD = Import(FromD, Lang_CXX);
1703
1704 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1705 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1706 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1707 FromSM);
1708}
1709
Gabor Marton9581c332018-05-23 13:53:36 +00001710TEST_P(
1711 ASTImporterTestBase,
1712 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1713{
1714 Decl *ToTU = getToTuDecl(
1715 R"(
1716 template <typename T>
1717 struct B;
1718
1719 template <>
1720 struct B<int> {};
1721
1722 template <>
1723 struct B<int>;
1724 )",
1725 Lang_CXX);
1726 // We should have only one definition.
1727 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1728 [](const ClassTemplateSpecializationDecl *T) {
1729 return T->isThisDeclarationADefinition();
1730 })
1731 .match(ToTU, classTemplateSpecializationDecl()));
1732
1733 Decl *FromTU = getTuDecl(
1734 R"(
1735 template <typename T>
1736 struct B;
1737
1738 template <>
1739 struct B<int> {};
1740 )",
1741 Lang_CXX, "input1.cc");
1742 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1743 FromTU, classTemplateSpecializationDecl(hasName("B")));
1744
1745 Import(FromD, Lang_CXX);
1746
1747 // We should have only one definition.
1748 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1749 [](const ClassTemplateSpecializationDecl *T) {
1750 return T->isThisDeclarationADefinition();
1751 })
1752 .match(ToTU, classTemplateSpecializationDecl()));
1753}
1754
Gabor Marton0bebf952018-07-05 09:51:13 +00001755TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
1756 Decl *FromTU = getTuDecl(
1757 R"(
1758 struct { int a; int b; } object0 = { 2, 3 };
1759 struct { int x; int y; int z; } object1;
1760 )",
1761 Lang_CXX, "input0.cc");
1762
Gabor Marton0bebf952018-07-05 09:51:13 +00001763 auto *Obj0 =
1764 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1765 auto *From0 = getRecordDecl(Obj0);
1766 auto *Obj1 =
1767 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1768 auto *From1 = getRecordDecl(Obj1);
1769
1770 auto *To0 = Import(From0, Lang_CXX);
1771 auto *To1 = Import(From1, Lang_CXX);
1772
1773 EXPECT_TRUE(To0);
1774 EXPECT_TRUE(To1);
1775 EXPECT_NE(To0, To1);
1776 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1777}
1778
Gabor Marton26f72a92018-07-12 09:42:05 +00001779TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
1780 auto Pattern = varDecl(hasName("x"));
1781 VarDecl *Imported1;
1782 {
1783 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1784 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1785 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1786 }
1787 VarDecl *Imported2;
1788 {
1789 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1790 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1791 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1792 }
1793 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1794 EXPECT_FALSE(Imported2->isUsed(false));
1795 {
1796 Decl *FromTU =
1797 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
1798 auto *FromD =
1799 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1800 Import(FromD, Lang_CXX);
1801 }
1802 EXPECT_TRUE(Imported2->isUsed(false));
1803}
1804
1805TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
1806 auto Pattern = varDecl(hasName("x"));
1807
1808 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1809 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1810
1811 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1812
1813 ASSERT_FALSE(Imported1->isUsed(false));
1814
1815 FromD->setIsUsed();
1816 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1817
1818 EXPECT_EQ(Imported1, Imported2);
1819 EXPECT_TRUE(Imported2->isUsed(false));
1820}
1821
Peter Szecsidedda6f2018-03-30 22:03:29 +00001822struct ImportFunctions : ASTImporterTestBase {};
1823
1824TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001825 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1826 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1827 auto Pattern = functionDecl(hasName("f"));
1828 FunctionDecl *FromD = // Definition
1829 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1830
1831 Decl *ImportedD = Import(FromD, Lang_CXX);
1832 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1833
Gabor Marton5254e642018-06-27 13:32:50 +00001834 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001835 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1836}
1837
1838TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1839 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1840 auto Pattern = functionDecl(hasName("f"));
1841 FunctionDecl *FromD =
1842 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1843
1844 Decl *ImportedD = Import(FromD, Lang_CXX);
1845 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1846
1847 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1848 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1849}
1850
Gabor Marton5254e642018-06-27 13:32:50 +00001851TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001852 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1853 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001854 auto *From =
1855 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001856
Gabor Marton5254e642018-06-27 13:32:50 +00001857 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001858 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1859
Gabor Marton5254e642018-06-27 13:32:50 +00001860 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1861 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1862 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1863 EXPECT_TRUE(ImportedD == To0);
1864 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1865 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1866 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001867}
1868
1869TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1870 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1871 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001872 auto *From =
1873 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001874
Gabor Marton5254e642018-06-27 13:32:50 +00001875 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001876 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1877
Gabor Marton5254e642018-06-27 13:32:50 +00001878 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1879 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1880 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1881 EXPECT_TRUE(ImportedD == To1);
1882 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1883 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1884 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001885}
1886
1887TEST_P(ImportFunctions, ImportPrototypes) {
1888 auto Pattern = functionDecl(hasName("f"));
1889
1890 Decl *ImportedD;
1891 {
1892 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001893 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001894
1895 ImportedD = Import(FromD, Lang_CXX);
1896 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001897 {
1898 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001899 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1900 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001901 }
1902
Gabor Marton5254e642018-06-27 13:32:50 +00001903 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1904
1905 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1906 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1907 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1908 EXPECT_TRUE(ImportedD == To0);
1909 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1910 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1911 EXPECT_EQ(To1->getPreviousDecl(), To0);
1912}
1913
1914TEST_P(ImportFunctions, ImportDefinitions) {
1915 auto Pattern = functionDecl(hasName("f"));
1916
1917 Decl *ImportedD;
1918 {
1919 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1920 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1921 ImportedD = Import(FromD, Lang_CXX);
1922 }
1923 {
1924 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
1925 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1926 Import(FromD, Lang_CXX);
1927 }
1928
1929 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1930
Peter Szecsidedda6f2018-03-30 22:03:29 +00001931 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00001932 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1933 EXPECT_TRUE(ImportedD == To0);
1934 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001935}
1936
1937TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1938 auto Pattern = functionDecl(hasName("f"));
1939
1940 Decl *ImportedD;
1941 {
1942 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001943 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001944 ImportedD = Import(FromD, Lang_CXX);
1945 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001946 {
1947 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001948 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1949 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001950 }
1951
1952 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001953
1954 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1955 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1956 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1957 EXPECT_TRUE(ImportedD == To0);
1958 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
1959 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1960 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001961}
1962
1963TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1964 auto Pattern = functionDecl(hasName("f"));
1965
1966 {
1967 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1968 FunctionDecl *FromD =
1969 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1970
1971 Import(FromD, Lang_CXX);
1972 }
1973 {
1974 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1975 FunctionDecl *FromD =
1976 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1977 Import(FromD, Lang_CXX);
1978 }
1979
1980 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1981 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1982 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00001983 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001984 FunctionDecl *DefinitionD =
1985 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1986 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1987 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1988}
1989
Gabor Marton5254e642018-06-27 13:32:50 +00001990TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001991 auto Pattern = functionDecl(hasName("f"));
1992
1993 {
1994 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001995 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001996 Import(FromD, Lang_CXX);
1997 }
1998 {
1999 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002000 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002001 Import(FromD, Lang_CXX);
2002 }
2003
2004 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002005
2006 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002007 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002008 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
2009
Peter Szecsidedda6f2018-03-30 22:03:29 +00002010 FunctionDecl *DefinitionD =
2011 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2012 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00002013
2014 EXPECT_TRUE(DefinitionD->getPreviousDecl());
2015 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
2016 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002017}
2018
2019TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2020 auto Code =
2021 R"(
2022 struct B { virtual void f(); };
2023 void B::f() {}
2024 struct D : B { void f(); };
2025 )";
2026 auto Pattern =
2027 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2028 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2029 CXXMethodDecl *Proto =
2030 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2031
2032 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2033 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2034 EXPECT_EQ(To->size_overridden_methods(), 1u);
2035}
2036
2037TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2038 auto Code =
2039 R"(
2040 struct B { virtual void f(); };
2041 void B::f() {}
2042 )";
2043 auto Pattern =
2044 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2045 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2046 CXXMethodDecl *Proto =
2047 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2048 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2049
2050 ASSERT_TRUE(Proto->isVirtual());
2051 ASSERT_TRUE(Def->isVirtual());
2052 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2053 EXPECT_TRUE(To->isVirtual());
2054}
2055
Gabor Marton5254e642018-06-27 13:32:50 +00002056TEST_P(ImportFunctions,
2057 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2058 Decl *ToTU = getToTuDecl(
2059 R"(
2060 void f() {}
2061 void f();
2062 )",
2063 Lang_CXX);
2064 ASSERT_EQ(1u,
2065 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2066 return FD->doesThisDeclarationHaveABody();
2067 }).match(ToTU, functionDecl()));
2068
2069 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2070 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2071
2072 Import(FromD, Lang_CXX);
2073
2074 EXPECT_EQ(1u,
2075 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2076 return FD->doesThisDeclarationHaveABody();
2077 }).match(ToTU, functionDecl()));
2078}
2079
2080struct ImportFriendFunctions : ImportFunctions {};
2081
2082TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2083 auto Pattern = functionDecl(hasName("f"));
2084
2085 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2086 "void f();",
2087 Lang_CXX,
2088 "input0.cc");
2089 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2090
2091 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2092 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2093 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2094 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2095 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2096 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2097 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2098}
2099
2100TEST_P(ImportFriendFunctions,
2101 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2102 auto Pattern = functionDecl(hasName("f"));
2103
2104 Decl *FromTU = getTuDecl("void f();"
2105 "struct X { friend void f(); };",
2106 Lang_CXX, "input0.cc");
2107 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2108
2109 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2110 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2111 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2112 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2113 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2114 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2115 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2116}
2117
2118TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2119 auto Pattern = functionDecl(hasName("f"));
2120
2121 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2122 "void f();",
2123 Lang_CXX,
2124 "input0.cc");
2125 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2126
2127 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2128 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2129 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2130 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2131 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2132 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2133 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2134}
2135
2136TEST_P(ImportFriendFunctions,
2137 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2138 auto Pattern = functionDecl(hasName("f"));
2139
2140 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2141 "void f(){}",
2142 Lang_CXX, "input0.cc");
2143 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2144
2145 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2146 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2147 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2148 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2149 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2150 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2151 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2152}
2153
Gabor Marton26f72a92018-07-12 09:42:05 +00002154// Disabled temporarily, because the new structural equivalence check
2155// (https://reviews.llvm.org/D48628) breaks it.
2156// PreviousDecl is not set because there is no structural match.
2157// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002158TEST_P(ImportFriendFunctions,
2159 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2160 auto Pattern = functionDecl(hasName("f"));
2161
2162 Decl *FromTU = getTuDecl(
2163 R"(
2164 class X;
2165 void f(X *x){}
2166 class X{
2167 friend void f(X *x);
2168 };
2169 )",
2170 Lang_CXX, "input0.cc");
2171 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2172
2173 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2174 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2175 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2176 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2177 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2178 .match(ToTU, friendDecl())
2179 ->getFriendDecl());
2180 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2181 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2182 // The parameters must refer the same type
2183 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2184 (*ImportedD->param_begin())->getOriginalType());
2185}
2186
Gabor Marton26f72a92018-07-12 09:42:05 +00002187// Disabled temporarily, because the new structural equivalence check
2188// (https://reviews.llvm.org/D48628) breaks it.
2189// PreviousDecl is not set because there is no structural match.
2190// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002191TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002192 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002193 auto Pattern = functionDecl(hasName("f"));
2194
2195 Decl *FromTU = getTuDecl(
2196 R"(
2197 class X;
2198 void f(X *x){}
2199 class X{
2200 friend void f(X *x);
2201 };
2202 )",
2203 Lang_CXX, "input0.cc");
2204 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2205
2206 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2207 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2208 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2209 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2210 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2211 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2212
2213 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2214 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2215 // The parameters must refer the same type
2216 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2217 (*ImportedD->param_begin())->getOriginalType());
2218}
2219
2220TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2221 auto Pattern = functionDecl(hasName("f"));
2222
2223 FunctionDecl *ImportedD;
2224 {
2225 Decl *FromTU =
2226 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2227 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2228 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2229 }
2230 FunctionDecl *ImportedD1;
2231 {
2232 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2233 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2234 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2235 }
2236
2237 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2238 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2239 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2240 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2241 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2242}
2243
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002244AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2245 InnerMatcher) {
2246 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2247 return InnerMatcher.matches(*Typedef, Finder, Builder);
2248 return false;
2249}
2250
Gabor Marton19f4f392018-06-25 13:04:37 +00002251TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002252 CodeFiles Samples{{"main.c",
2253 {"void foo();"
2254 "void moo();"
2255 "int main() { foo(); moo(); }",
2256 Lang_C}},
2257
2258 {"foo.c",
2259 {"typedef enum { THING_VALUE } thing_t;"
2260 "void conflict(thing_t type);"
2261 "void foo() { (void)THING_VALUE; }"
2262 "void conflict(thing_t type) {}",
2263 Lang_C}},
2264
2265 {"moo.c",
2266 {"typedef enum { THING_VALUE } thing_t;"
2267 "void conflict(thing_t type);"
2268 "void moo() { conflict(THING_VALUE); }",
2269 Lang_C}}};
2270
2271 auto VerificationMatcher =
2272 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2273 hasTypedefForAnonDecl(hasName("thing_t")));
2274
2275 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2276 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2277
2278 testImportSequence(
2279 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2280 // Just check that there is only one enum decl in the result AST.
2281 "main.c", enumDecl(), VerificationMatcher);
2282
2283 // For different import order, result should be the same.
2284 testImportSequence(
2285 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2286 // Check that there is only one enum decl in the result AST.
2287 "main.c", enumDecl(), VerificationMatcher);
2288}
2289
Peter Szecsice7f3182018-05-07 12:08:27 +00002290const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2291 dependentScopeDeclRefExpr;
2292
Gabor Marton19f4f392018-06-25 13:04:37 +00002293TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002294 MatchVerifier<Decl> Verifier;
2295 testImport("template <typename T> struct S { static T foo; };"
2296 "template <typename T> void declToImport() {"
2297 " (void) S<T>::foo;"
2298 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002299 "void instantiate() { declToImport<int>(); }"
2300 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002301 Lang_CXX11, "", Lang_CXX11, Verifier,
2302 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2303 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2304
2305 testImport("template <typename T> struct S {"
2306 "template<typename S> static void foo(){};"
2307 "};"
2308 "template <typename T> void declToImport() {"
2309 " S<T>::template foo<T>();"
2310 "}"
2311 "void instantiate() { declToImport<int>(); }",
2312 Lang_CXX11, "", Lang_CXX11, Verifier,
2313 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2314 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2315}
2316
2317const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2318 dependentNameType;
2319
Gabor Marton19f4f392018-06-25 13:04:37 +00002320TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002321 MatchVerifier<Decl> Verifier;
2322 testImport("template <typename T> struct declToImport {"
2323 " typedef typename T::type dependent_name;"
2324 "};",
2325 Lang_CXX11, "", Lang_CXX11, Verifier,
2326 classTemplateDecl(has(
2327 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2328}
2329
2330const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
2331 unresolvedMemberExpr;
2332
Gabor Marton19f4f392018-06-25 13:04:37 +00002333TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002334 MatchVerifier<Decl> Verifier;
2335 testImport("struct S { template <typename T> void mem(); };"
2336 "template <typename U> void declToImport() {"
2337 " S s;"
2338 " s.mem<U>();"
2339 "}"
2340 "void instantiate() { declToImport<int>(); }",
2341 Lang_CXX11, "", Lang_CXX11, Verifier,
2342 functionTemplateDecl(has(functionDecl(has(
2343 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2344}
2345
Balazs Keri1d20cc22018-07-16 12:16:39 +00002346class ImportImplicitMethods : public ASTImporterTestBase {
2347public:
2348 static constexpr auto DefaultCode = R"(
2349 struct A { int x; };
2350 void f() {
2351 A a;
2352 A a1(a);
2353 A a2(A{});
2354 a = a1;
2355 a = A{};
2356 a.~A();
2357 })";
2358
2359 template <typename MatcherType>
2360 void testImportOf(
2361 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2362 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2363 }
2364
2365 template <typename MatcherType>
2366 void testNoImportOf(
2367 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2368 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2369 }
2370
2371private:
2372 template <typename MatcherType>
2373 void test(const MatcherType &MethodMatcher,
2374 const char *Code, unsigned int ExpectedCount) {
2375 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2376
2377 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2378 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2379 ToTU, ClassMatcher);
2380
Balazs Keri2f752ba2018-07-16 14:05:18 +00002381 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002382
2383 {
2384 CXXMethodDecl *Method =
2385 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2386 ToClass->removeDecl(Method);
2387 }
2388
Balazs Keri2f752ba2018-07-16 14:05:18 +00002389 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002390
2391 Decl *ImportedClass = nullptr;
2392 {
2393 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2394 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2395 FromTU, ClassMatcher);
2396 ImportedClass = Import(FromClass, Lang_CXX11);
2397 }
2398
2399 EXPECT_EQ(ToClass, ImportedClass);
2400 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2401 ExpectedCount);
2402 }
2403};
2404
2405TEST_P(ImportImplicitMethods, DefaultConstructor) {
2406 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2407}
2408
2409TEST_P(ImportImplicitMethods, CopyConstructor) {
2410 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2411}
2412
2413TEST_P(ImportImplicitMethods, MoveConstructor) {
2414 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2415}
2416
2417TEST_P(ImportImplicitMethods, Destructor) {
2418 testImportOf(cxxDestructorDecl());
2419}
2420
2421TEST_P(ImportImplicitMethods, CopyAssignment) {
2422 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2423}
2424
2425TEST_P(ImportImplicitMethods, MoveAssignment) {
2426 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2427}
2428
2429TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2430 auto Code = R"(
2431 struct A { A() { int x; } };
2432 )";
2433 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2434}
2435
2436TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2437 auto Code = R"(
2438 struct A { A() = default; };
2439 )";
2440 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2441}
2442
2443TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2444 auto Code = R"(
2445 struct A { A() = delete; };
2446 )";
2447 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2448}
2449
2450TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2451 auto Code = R"(
2452 struct A { void f() { } };
2453 )";
2454 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2455}
2456
Balazs Keric7797c42018-07-11 09:37:24 +00002457TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
2458 Decl *ToR1;
2459 {
2460 Decl *FromTU = getTuDecl(
2461 "struct A { };", Lang_CXX, "input0.cc");
2462 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2463 FromTU, cxxRecordDecl(hasName("A")));
2464
2465 ToR1 = Import(FromR, Lang_CXX);
2466 }
2467
2468 Decl *ToR2;
2469 {
2470 Decl *FromTU = getTuDecl(
2471 "struct A { };", Lang_CXX, "input1.cc");
2472 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2473 FromTU, cxxRecordDecl(hasName("A")));
2474
2475 ToR2 = Import(FromR, Lang_CXX);
2476 }
2477
2478 EXPECT_EQ(ToR1, ToR2);
2479}
2480
2481TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
2482 Decl *ToR1;
2483 {
2484 Decl *FromTU = getTuDecl(
2485 "struct A { int x; };", Lang_CXX, "input0.cc");
2486 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2487 FromTU, cxxRecordDecl(hasName("A")));
2488 ToR1 = Import(FromR, Lang_CXX);
2489 }
2490 Decl *ToR2;
2491 {
2492 Decl *FromTU = getTuDecl(
2493 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2494 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2495 FromTU, cxxRecordDecl(hasName("A")));
2496 ToR2 = Import(FromR, Lang_CXX);
2497 }
2498 EXPECT_NE(ToR1, ToR2);
2499}
2500
2501TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
2502 Decl *ToF1;
2503 {
2504 Decl *FromTU = getTuDecl(
2505 "struct A { int x; };", Lang_CXX, "input0.cc");
2506 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2507 FromTU, fieldDecl(hasName("x")));
2508 ToF1 = Import(FromF, Lang_CXX);
2509 }
2510 Decl *ToF2;
2511 {
2512 Decl *FromTU = getTuDecl(
2513 "struct A { int x; };", Lang_CXX, "input1.cc");
2514 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2515 FromTU, fieldDecl(hasName("x")));
2516 ToF2 = Import(FromF, Lang_CXX);
2517 }
2518 EXPECT_EQ(ToF1, ToF2);
2519}
2520
2521TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
2522 Decl *ToF1;
2523 {
2524 Decl *FromTU = getTuDecl(
2525 "struct A { int x; };", Lang_CXX, "input0.cc");
2526 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2527 FromTU, fieldDecl(hasName("x")));
2528 ToF1 = Import(FromF, Lang_CXX);
2529 }
2530 Decl *ToF2;
2531 {
2532 Decl *FromTU = getTuDecl(
2533 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2534 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2535 FromTU, fieldDecl(hasName("x")));
2536 ToF2 = Import(FromF, Lang_CXX);
2537 }
2538 EXPECT_NE(ToF1, ToF2);
2539}
2540
2541TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
2542 Decl *ToM1;
2543 {
2544 Decl *FromTU = getTuDecl(
2545 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2546 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2547 FromTU, functionDecl(hasName("x"), isDefinition()));
2548 ToM1 = Import(FromM, Lang_CXX);
2549 }
2550 Decl *ToM2;
2551 {
2552 Decl *FromTU = getTuDecl(
2553 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2554 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2555 FromTU, functionDecl(hasName("x"), isDefinition()));
2556 ToM2 = Import(FromM, Lang_CXX);
2557 }
2558 EXPECT_EQ(ToM1, ToM2);
2559}
2560
2561TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
2562 Decl *ToM1;
2563 {
2564 Decl *FromTU = getTuDecl(
2565 "struct A { void x(); }; void A::x() { }",
2566 Lang_CXX, "input0.cc");
2567 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2568 FromTU, functionDecl(hasName("x"), isDefinition()));
2569 ToM1 = Import(FromM, Lang_CXX);
2570 }
2571 Decl *ToM2;
2572 {
2573 Decl *FromTU = getTuDecl(
2574 "struct A { void x() const; }; void A::x() const { }",
2575 Lang_CXX, "input1.cc");
2576 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2577 FromTU, functionDecl(hasName("x"), isDefinition()));
2578 ToM2 = Import(FromM, Lang_CXX);
2579 }
2580 EXPECT_NE(ToM1, ToM2);
2581}
2582
Gabor Martonf086fa82018-07-17 12:06:36 +00002583TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
2584 Decl *FromTU = getTuDecl(
2585 R"(
2586 struct A {
2587 struct {
2588 struct A *next;
2589 } entry0;
2590 struct {
2591 struct A *next;
2592 } entry1;
2593 };
2594 )",
2595 Lang_C, "input0.cc");
2596 auto *From =
2597 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
2598
2599 Import(From, Lang_C);
2600
2601 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2602 auto *Entry0 =
2603 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
2604 auto *Entry1 =
2605 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
2606 auto *R0 = getRecordDecl(Entry0);
2607 auto *R1 = getRecordDecl(Entry1);
2608 EXPECT_NE(R0, R1);
2609 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2610 R0, recordDecl(has(fieldDecl(hasName("next"))))));
2611 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2612 R1, recordDecl(has(fieldDecl(hasName("next"))))));
2613}
2614
Gabor Marton61d862a2018-05-18 09:08:47 +00002615struct DeclContextTest : ASTImporterTestBase {};
2616
2617TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
2618 Decl *TU = getTuDecl(
2619 R"(
2620 namespace NS {
2621
2622 template <typename T>
2623 struct S {};
2624 template struct S<int>;
2625
2626 inline namespace INS {
2627 template <typename T>
2628 struct S {};
2629 template struct S<int>;
2630 }
2631
2632 }
2633 )", Lang_CXX11, "input0.cc");
2634 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
2635 TU, namespaceDecl());
2636 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2637 TU, classTemplateSpecializationDecl());
2638 ASSERT_TRUE(NS->containsDecl(Spec));
2639
2640 NS->removeDecl(Spec);
2641 EXPECT_FALSE(NS->containsDecl(Spec));
2642}
2643
Gabor Marton5254e642018-06-27 13:32:50 +00002644struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
2645
2646TEST_P(ImportFunctionTemplateSpecializations,
2647 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
2648
2649 Decl *FromTU = getTuDecl(
2650 R"(
2651 template<class T>
2652 int f() { return 0; }
2653 void foo() { f<int>(); }
2654 )",
2655 Lang_CXX, "input0.cc");
2656
2657 // Check that the function template instantiation is NOT the child of the TU.
2658 auto Pattern = translationUnitDecl(
2659 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
2660 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2661
2662 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
2663 FromTU, functionDecl(hasName("foo")));
2664 ASSERT_TRUE(Import(Foo, Lang_CXX));
2665
2666 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2667 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2668}
2669
2670TEST_P(ImportFunctionTemplateSpecializations,
2671 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
2672
2673 Decl *FromTU = getTuDecl(
2674 R"(
2675 template<class T>
2676 int f() { return 0; }
2677 template int f<int>();
2678 )",
2679 Lang_CXX, "input0.cc");
2680
2681 // Check that the function template instantiation is NOT the child of the TU.
2682 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
2683 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
2684 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2685
2686 ASSERT_TRUE(
2687 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
2688
2689 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2690 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2691}
2692
2693TEST_P(ImportFunctionTemplateSpecializations,
2694 TUshouldContainFunctionTemplateSpecialization) {
2695
2696 Decl *FromTU = getTuDecl(
2697 R"(
2698 template<class T>
2699 int f() { return 0; }
2700 template <> int f<int>() { return 4; }
2701 )",
2702 Lang_CXX, "input0.cc");
2703
2704 // Check that the function template specialization is the child of the TU.
2705 auto Specialization =
2706 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2707 auto Pattern = translationUnitDecl(has(Specialization));
2708 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2709
2710 ASSERT_TRUE(
2711 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
2712
2713 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2714 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2715}
2716
2717TEST_P(ImportFunctionTemplateSpecializations,
2718 FunctionTemplateSpecializationRedeclChain) {
2719
2720 Decl *FromTU = getTuDecl(
2721 R"(
2722 template<class T>
2723 int f() { return 0; }
2724 template <> int f<int>() { return 4; }
2725 )",
2726 Lang_CXX, "input0.cc");
2727
2728 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
2729 hasParent(translationUnitDecl()));
2730 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
2731 {
2732 auto *TU = FromTU;
2733 auto *SpecD = FromSpecD;
2734 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2735 TU, functionTemplateDecl());
2736 auto *FirstSpecD = *(TemplateD->spec_begin());
2737 ASSERT_EQ(SpecD, FirstSpecD);
2738 ASSERT_TRUE(SpecD->getPreviousDecl());
2739 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2740 ->doesThisDeclarationHaveABody());
2741 }
2742
2743 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
2744
2745 {
2746 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
2747 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
2748 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2749 TU, functionTemplateDecl());
2750 auto *FirstSpecD = *(TemplateD->spec_begin());
2751 EXPECT_EQ(SpecD, FirstSpecD);
2752 ASSERT_TRUE(SpecD->getPreviousDecl());
2753 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2754 ->doesThisDeclarationHaveABody());
2755 }
2756}
2757
2758TEST_P(ImportFunctionTemplateSpecializations,
2759 MatchNumberOfFunctionTemplateSpecializations) {
2760
2761 Decl *FromTU = getTuDecl(
2762 R"(
2763 template <typename T> constexpr int f() { return 0; }
2764 template <> constexpr int f<int>() { return 4; }
2765 void foo() {
2766 static_assert(f<char>() == 0, "");
2767 static_assert(f<int>() == 4, "");
2768 }
2769 )",
2770 Lang_CXX11, "input0.cc");
2771 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2772 FromTU, functionDecl(hasName("foo")));
2773
2774 Import(FromD, Lang_CXX11);
2775 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2776 EXPECT_EQ(
2777 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
2778 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
2779}
2780
2781TEST_P(ImportFunctionTemplateSpecializations,
2782 ImportPrototypes) {
2783 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2784 auto Code =
2785 R"(
2786 // Proto of the primary template.
2787 template <class T>
2788 void f();
2789 // Proto of the specialization.
2790 template <>
2791 void f<int>();
2792 )";
2793
2794 Decl *ImportedD;
2795 {
2796 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2797 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2798
2799 ImportedD = Import(FromD, Lang_CXX);
2800 }
2801 {
2802 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2803 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2804 Import(FromD, Lang_CXX);
2805 }
2806
2807 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2808
2809 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2810 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2811 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2812 EXPECT_TRUE(ImportedD == To0);
2813 EXPECT_TRUE(ImportedD != To1);
2814 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2815 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2816 // Check that they are part of the same redecl chain.
2817 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
2818}
2819
2820TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
2821 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2822 auto Code =
2823 R"(
2824 // Proto of the primary template.
2825 template <class T>
2826 void f();
2827 // Specialization and definition.
2828 template <>
2829 void f<int>() {}
2830 )";
2831
2832 Decl *ImportedD;
2833 {
2834 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2835 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2836 ImportedD = Import(FromD, Lang_CXX);
2837 }
2838 {
2839 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2840 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2841 Import(FromD, Lang_CXX);
2842 }
2843
2844 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2845
2846 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2847 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2848 EXPECT_TRUE(ImportedD == To0);
2849 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2850
2851 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2852 ToTU, functionTemplateDecl());
2853 auto *FirstSpecD = *(TemplateD->spec_begin());
2854 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
2855}
2856
2857TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
2858 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2859 auto Code =
2860 R"(
2861 // Proto of the primary template.
2862 template <class T>
2863 void f();
2864 // Specialization proto.
2865 template <>
2866 void f<int>();
2867 // Specialization proto.
2868 template <>
2869 void f<int>();
2870 )";
2871
2872 Decl *ImportedD;
2873 {
2874 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2875 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2876 ImportedD = Import(FromD, Lang_CXX);
2877 }
2878
2879 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2880
2881 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2882 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2883 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2884 EXPECT_TRUE(ImportedD == To0);
2885 EXPECT_TRUE(ImportedD != To1);
2886 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2887 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2888 EXPECT_EQ(To1->getPreviousDecl(), To0);
2889}
2890
2891TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
2892 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2893 auto Code =
2894 R"(
2895 // Proto of the primary template.
2896 template <class T>
2897 void f();
2898 // Specialization proto.
2899 template <>
2900 void f<int>();
2901 // Specialization definition.
2902 template <>
2903 void f<int>() {}
2904 )";
2905
2906 Decl *ImportedD;
2907 {
2908 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2909 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2910 ImportedD = Import(FromD, Lang_CXX);
2911 }
2912
2913 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2914
2915 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2916 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2917 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2918 EXPECT_TRUE(ImportedD == To0);
2919 EXPECT_TRUE(ImportedD != To1);
2920 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2921 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2922 EXPECT_EQ(To1->getPreviousDecl(), To0);
2923}
2924
2925TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
2926 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2927 auto Code =
2928 R"(
2929 // Proto of the primary template.
2930 template <class T>
2931 void f();
2932 // Specialization definition.
2933 template <>
2934 void f<int>() {}
2935 // Specialization proto.
2936 template <>
2937 void f<int>();
2938 )";
2939
2940 Decl *ImportedD;
2941 {
2942 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2943 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2944 ImportedD = Import(FromD, Lang_CXX);
2945 }
2946
2947 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2948
2949 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2950 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2951 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2952 EXPECT_TRUE(ImportedD == To0);
2953 EXPECT_TRUE(ImportedD != To1);
2954 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2955 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2956 EXPECT_EQ(To1->getPreviousDecl(), To0);
2957}
2958
Gabor Marton19f4f392018-06-25 13:04:37 +00002959INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
2960 ::testing::Values(ArgVector()), );
2961
Gabor Marton5254e642018-06-27 13:32:50 +00002962INSTANTIATE_TEST_CASE_P(
2963 ParameterizedTests, CanonicalRedeclChain,
2964 ::testing::Values(ArgVector()),);
2965
Gabor Marton19f4f392018-06-25 13:04:37 +00002966auto DefaultTestValuesForRunOptions = ::testing::Values(
2967 ArgVector(),
2968 ArgVector{"-fdelayed-template-parsing"},
2969 ArgVector{"-fms-compatibility"},
2970 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
2971
2972INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
2973 DefaultTestValuesForRunOptions, );
2974
2975INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
2976 DefaultTestValuesForRunOptions, );
2977
2978INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
2979 DefaultTestValuesForRunOptions, );
2980
2981INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
2982 DefaultTestValuesForRunOptions, );
2983
2984INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
2985 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00002986
Gabor Marton5254e642018-06-27 13:32:50 +00002987INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
2988 DefaultTestValuesForRunOptions, );
2989
2990INSTANTIATE_TEST_CASE_P(ParameterizedTests,
2991 ImportFunctionTemplateSpecializations,
2992 DefaultTestValuesForRunOptions, );
2993
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00002994} // end namespace ast_matchers
2995} // end namespace clang