blob: 2690f4e5f1fc2186d6320dfdea4e4d18a286dc7e [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();
Nico Weberb980b5c2018-07-17 14:20:02 +0000279}
Gabor Martonf086fa82018-07-17 12:06:36 +0000280
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");
Gabor Martonfe68e292018-08-06 14:38:37 +0000992 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +0000993 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.
Gabor Martonfe68e292018-08-06 14:38:37 +00001002 Decl *FromTU = getTuDecl(
1003 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1004 Lang_C, "input.c");
1005 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1006 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001007 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001008 auto *To = Import(From, Lang_C);
1009 EXPECT_EQ(To, nullptr);
1010}
1011
1012TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncFromMacro) {
1013 Decl *FromTU = getTuDecl(
1014 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1015 "int declToImport(){ return NONAME_SIZEOF(int); }",
1016 Lang_C, "input.c");
1017 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1018 FromTU, functionDecl(hasName("declToImport")));
1019 ASSERT_TRUE(From);
1020 auto *To = Import(From, Lang_C);
1021 ASSERT_TRUE(To);
1022 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1023 To, functionDecl(hasName("declToImport"),
1024 hasDescendant(unaryExprOrTypeTraitExpr()))));
1025}
1026
1027TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParamsFromMacro) {
1028 // This construct is not supported by ASTImporter.
1029 Decl *FromTU = getTuDecl(
1030 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1031 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1032 Lang_C, "input.c");
1033 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1034 FromTU, functionDecl(hasName("declToImport")));
1035 ASSERT_TRUE(From);
1036 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001037 EXPECT_EQ(To, nullptr);
1038}
1039
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001040const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1041 cxxPseudoDestructorExpr;
1042
Gabor Marton19f4f392018-06-25 13:04:37 +00001043TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001044 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001045 testImport(
1046 "typedef int T;"
1047 "void declToImport(int *p) {"
1048 " T t;"
1049 " p->T::~T();"
1050 "}",
1051 Lang_CXX, "", Lang_CXX, Verifier,
1052 functionDecl(hasDescendant(
1053 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001054}
1055
Gabor Marton19f4f392018-06-25 13:04:37 +00001056TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001057 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001058 testImport(
1059 "namespace foo { int bar; }"
1060 "void declToImport() { using foo::bar; }",
1061 Lang_CXX, "", Lang_CXX, Verifier,
1062 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001063}
1064
1065/// \brief Matches shadow declarations introduced into a scope by a
1066/// (resolved) using declaration.
1067///
1068/// Given
1069/// \code
1070/// namespace n { int f; }
1071/// namespace declToImport { using n::f; }
1072/// \endcode
1073/// usingShadowDecl()
1074/// matches \code f \endcode
1075const internal::VariadicDynCastAllOfMatcher<Decl,
1076 UsingShadowDecl> usingShadowDecl;
1077
Gabor Marton19f4f392018-06-25 13:04:37 +00001078TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001079 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001080 testImport(
1081 "namespace foo { int bar; }"
1082 "namespace declToImport { using foo::bar; }",
1083 Lang_CXX, "", Lang_CXX, Verifier,
1084 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001085}
1086
Gabor Marton19f4f392018-06-25 13:04:37 +00001087TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001088 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001089 testImport(
1090 "template<typename T> int foo();"
1091 "template <typename T> void declToImport() {"
1092 " (void)::foo<T>;"
1093 " (void)::template foo<T>;"
1094 "}"
1095 "void instantiate() { declToImport<int>(); }",
1096 Lang_CXX, "", Lang_CXX, Verifier,
1097 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001098}
1099
Gabor Marton19f4f392018-06-25 13:04:37 +00001100TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001101 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001102 testImport(
1103 "template <typename T> struct C { T t; };"
1104 "template <typename T> void declToImport() {"
1105 " C<T> d;"
1106 " d.t = T();"
1107 "}"
1108 "void instantiate() { declToImport<int>(); }",
1109 Lang_CXX, "", Lang_CXX, Verifier,
1110 functionTemplateDecl(hasDescendant(
1111 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1112 testImport(
1113 "template <typename T> struct C { T t; };"
1114 "template <typename T> void declToImport() {"
1115 " C<T> d;"
1116 " (&d)->t = T();"
1117 "}"
1118 "void instantiate() { declToImport<int>(); }",
1119 Lang_CXX, "", Lang_CXX, Verifier,
1120 functionTemplateDecl(hasDescendant(
1121 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001122}
1123
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001124/// Check that function "declToImport()" (which is the templated function
1125/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1126/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001127TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001128 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001129 testImport(
1130 "template <typename T> void declToImport() { T a = 1; }"
1131 "void instantiate() { declToImport<int>(); }",
1132 Lang_CXX, "", Lang_CXX, Verifier,
1133 functionTemplateDecl(hasAncestor(translationUnitDecl(
1134 unless(has(functionDecl(hasName("declToImport"))))))));
1135 testImport(
1136 "template <typename T> struct declToImport { T t; };"
1137 "void instantiate() { declToImport<int>(); }",
1138 Lang_CXX, "", Lang_CXX, Verifier,
1139 classTemplateDecl(hasAncestor(translationUnitDecl(
1140 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001141}
1142
Gabor Marton19f4f392018-06-25 13:04:37 +00001143TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001144 MatchVerifier<Decl> Verifier;
1145 auto Code =
1146 R"s(
1147 struct declToImport {
1148 template <typename T0> struct X;
1149 template <typename T0> struct X<T0 *> {};
1150 };
1151 )s";
1152 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1153 recordDecl(has(classTemplateDecl()),
1154 has(classTemplateSpecializationDecl())));
1155}
1156
Gabor Marton19f4f392018-06-25 13:04:37 +00001157TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001158 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001159 testImport(
1160 "class declToImport {"
1161 " void f() { *this = declToImport(); }"
1162 "};",
1163 Lang_CXX, "", Lang_CXX, Verifier,
1164 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1165 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001166}
1167
Gabor Marton19f4f392018-06-25 13:04:37 +00001168TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001169 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001170 testImport(
1171 "template<typename T, int Size> class declToImport {"
1172 " T data[Size];"
1173 "};",
1174 Lang_CXX, "", Lang_CXX, Verifier,
1175 classTemplateDecl(has(cxxRecordDecl(
1176 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001177}
1178
Gabor Martona0df7a92018-05-30 09:19:26 +00001179TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1180 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1181 auto From =
1182 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1183 ASSERT_TRUE(From);
1184 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1185 ASSERT_TRUE(To);
1186 Decl *ToTemplated = To->getTemplatedDecl();
1187 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1188 EXPECT_TRUE(ToTemplated1);
1189 EXPECT_EQ(ToTemplated1, ToTemplated);
1190}
1191
Gabor Marton26f72a92018-07-12 09:42:05 +00001192TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001193 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1194 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1195 FromTU, functionTemplateDecl());
1196 ASSERT_TRUE(From);
1197 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1198 ASSERT_TRUE(To);
1199 Decl *ToTemplated = To->getTemplatedDecl();
1200 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1201 EXPECT_TRUE(ToTemplated1);
1202 EXPECT_EQ(ToTemplated1, ToTemplated);
1203}
1204
1205TEST_P(ASTImporterTestBase,
1206 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1207 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1208 auto FromFT =
1209 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1210 ASSERT_TRUE(FromFT);
1211
1212 auto ToTemplated =
1213 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1214 EXPECT_TRUE(ToTemplated);
1215 auto ToTU = ToTemplated->getTranslationUnitDecl();
1216 auto ToFT =
1217 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1218 EXPECT_TRUE(ToFT);
1219}
1220
1221TEST_P(ASTImporterTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001222 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001223 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1224 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1225 FromTU, functionTemplateDecl());
1226 ASSERT_TRUE(FromFT);
1227
1228 auto ToTemplated =
1229 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1230 EXPECT_TRUE(ToTemplated);
1231 auto ToTU = ToTemplated->getTranslationUnitDecl();
1232 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1233 ToTU, functionTemplateDecl());
1234 EXPECT_TRUE(ToFT);
1235}
1236
Gabor Martona0df7a92018-05-30 09:19:26 +00001237TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1238 auto Code =
1239 R"(
1240 namespace x {
1241 template<class X> struct S1{};
1242 template<class X> struct S2{};
1243 template<class X> struct S3{};
1244 }
1245 )";
1246 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1247 auto FromNs =
1248 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1249 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1250 ASSERT_TRUE(ToNs);
1251 auto From =
1252 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1253 classTemplateDecl(
1254 hasName("S2")));
1255 auto To =
1256 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1257 classTemplateDecl(
1258 hasName("S2")));
1259 ASSERT_TRUE(From);
1260 ASSERT_TRUE(To);
1261 auto ToTemplated = To->getTemplatedDecl();
1262 auto ToTemplated1 =
1263 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1264 EXPECT_TRUE(ToTemplated1);
1265 ASSERT_EQ(ToTemplated1, ToTemplated);
1266}
1267
Gabor Marton26f72a92018-07-12 09:42:05 +00001268TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001269 Decl *From, *To;
1270 std::tie(From, To) = getImportedDecl(
1271 R"(
1272 template <typename T> struct X {};
1273
1274 void declToImport(int y, X<int> &x) {}
1275
1276 template <> struct X<int> {
1277 void g() {
1278 X<int> x;
1279 declToImport(0, x);
1280 }
1281 };
1282 )",
1283 Lang_CXX, "", Lang_CXX);
1284
1285 MatchVerifier<Decl> Verifier;
1286 auto Matcher = functionDecl(hasName("declToImport"),
1287 parameterCountIs(2),
1288 hasParameter(0, hasName("y")),
1289 hasParameter(1, hasName("x")),
1290 hasParameter(1, hasType(asString("X<int> &"))));
1291 ASSERT_TRUE(Verifier.match(From, Matcher));
1292 EXPECT_TRUE(Verifier.match(To, Matcher));
1293}
1294
1295TEST_P(ASTImporterTestBase,
1296 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1297 Decl *From, *To;
1298 std::tie(From, To) =
1299 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1300 "void instantiate() { declToImport<int>(); }",
1301 Lang_CXX, "", Lang_CXX);
1302
1303 auto Check = [](Decl *D) -> bool {
1304 auto TU = D->getTranslationUnitDecl();
1305 for (auto Child : TU->decls()) {
1306 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1307 if (FD->getNameAsString() == "declToImport") {
1308 GTEST_NONFATAL_FAILURE_(
1309 "TU should not contain any FunctionDecl with name declToImport");
1310 return false;
1311 }
1312 }
1313 }
1314 return true;
1315 };
1316
1317 ASSERT_TRUE(Check(From));
1318 EXPECT_TRUE(Check(To));
1319}
1320
1321TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1322 Decl *From, *To;
1323 std::tie(From, To) =
1324 getImportedDecl("template <typename T> struct declToImport { T t; };"
1325 "void instantiate() { declToImport<int>(); }",
1326 Lang_CXX, "", Lang_CXX);
1327
1328 auto Check = [](Decl *D) -> bool {
1329 auto TU = D->getTranslationUnitDecl();
1330 for (auto Child : TU->decls()) {
1331 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1332 if (RD->getNameAsString() == "declToImport") {
1333 GTEST_NONFATAL_FAILURE_(
1334 "TU should not contain any CXXRecordDecl with name declToImport");
1335 return false;
1336 }
1337 }
1338 }
1339 return true;
1340 };
1341
1342 ASSERT_TRUE(Check(From));
1343 EXPECT_TRUE(Check(To));
1344}
1345
1346TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1347 Decl *From, *To;
1348 std::tie(From, To) =
1349 getImportedDecl(
1350 "template <typename T> struct X {};"
1351 "template <typename T> using declToImport = X<T>;"
1352 "void instantiate() { declToImport<int> a; }",
1353 Lang_CXX11, "", Lang_CXX11);
1354
1355 auto Check = [](Decl *D) -> bool {
1356 auto TU = D->getTranslationUnitDecl();
1357 for (auto Child : TU->decls()) {
1358 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1359 if (AD->getNameAsString() == "declToImport") {
1360 GTEST_NONFATAL_FAILURE_(
1361 "TU should not contain any TypeAliasDecl with name declToImport");
1362 return false;
1363 }
1364 }
1365 }
1366 return true;
1367 };
1368
1369 ASSERT_TRUE(Check(From));
1370 EXPECT_TRUE(Check(To));
1371}
1372
1373TEST_P(
1374 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001375 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001376
1377 Decl *From, *To;
1378 std::tie(From, To) = getImportedDecl(
1379 R"(
1380 template<class T>
1381 class Base {};
1382 class declToImport : public Base<declToImport> {};
1383 )",
1384 Lang_CXX, "", Lang_CXX);
1385
1386 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1387 auto Pattern =
1388 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1389 ASSERT_TRUE(
1390 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1391 EXPECT_TRUE(
1392 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1393
1394 // Check that the ClassTemplateSpecializationDecl is the child of the
1395 // ClassTemplateDecl.
1396 Pattern = translationUnitDecl(has(classTemplateDecl(
1397 hasName("Base"), has(classTemplateSpecializationDecl()))));
1398 ASSERT_TRUE(
1399 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1400 EXPECT_TRUE(
1401 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1402}
1403
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001404AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1405 size_t Index = 0;
1406 for (FieldDecl *Field : Node.fields()) {
1407 if (Index == Order.size())
1408 return false;
1409 if (Field->getName() != Order[Index])
1410 return false;
1411 ++Index;
1412 }
1413 return Index == Order.size();
1414}
1415
Peter Szecsidedda6f2018-03-30 22:03:29 +00001416TEST_P(ASTImporterTestBase,
1417 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1418 Decl *From, *To;
1419 std::tie(From, To) = getImportedDecl(
1420 R"(
1421 namespace NS {
1422 template<class T>
1423 class X {};
1424 template class X<int>;
1425 }
1426 )",
1427 Lang_CXX, "", Lang_CXX, "NS");
1428
1429 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1430 // ClassTemplateDecl.
1431 auto Pattern = namespaceDecl(has(classTemplateDecl(
1432 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1433 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1434 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1435
1436 // Check that the ClassTemplateSpecializationDecl is the child of the
1437 // NamespaceDecl.
1438 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1439 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1440 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1441}
1442
1443TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1444 Decl *From, *To;
1445 std::tie(From, To) =
1446 getImportedDecl(
1447 "struct declToImport { int a; int b; };",
1448 Lang_CXX11, "", Lang_CXX11);
1449
1450 MatchVerifier<Decl> Verifier;
1451 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1452 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1453}
1454
1455TEST_P(ASTImporterTestBase,
1456 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1457 Decl *From, *To;
1458 std::tie(From, To) = getImportedDecl(
1459 // The original recursive algorithm of ASTImporter first imports 'c' then
1460 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1461 R"s(
1462 struct declToImport {
1463 int a = c + b;
1464 int b = 1;
1465 int c = 2;
1466 };
1467 )s",
1468 Lang_CXX11, "", Lang_CXX11);
1469
1470 MatchVerifier<Decl> Verifier;
1471 ASSERT_TRUE(
1472 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1473 EXPECT_TRUE(
1474 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1475}
1476
Gabor Martonde8bf262018-05-17 09:46:07 +00001477TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001478 Decl *From, *To;
1479 std::tie(From, To) = getImportedDecl(
1480 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001481 struct declToImport {
1482 };
1483 )",
1484 Lang_CXX, "", Lang_CXX);
1485
1486 MatchVerifier<Decl> Verifier;
1487 // Match the implicit Decl.
1488 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1489 ASSERT_TRUE(Verifier.match(From, Matcher));
1490 EXPECT_TRUE(Verifier.match(To, Matcher));
1491}
1492
1493TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1494 Decl *From, *To;
1495 std::tie(From, To) = getImportedDecl(
1496 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001497 template <typename U>
1498 struct declToImport {
1499 };
1500 )",
1501 Lang_CXX, "", Lang_CXX);
1502
1503 MatchVerifier<Decl> Verifier;
1504 // Match the implicit Decl.
1505 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1506 ASSERT_TRUE(Verifier.match(From, Matcher));
1507 EXPECT_TRUE(Verifier.match(To, Matcher));
1508}
1509
1510TEST_P(
1511 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001512 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001513 Decl *From, *To;
1514 std::tie(From, To) = getImportedDecl(
1515 R"(
1516 template<class T>
1517 class Base {};
1518 class declToImport : public Base<declToImport> {};
1519 )",
1520 Lang_CXX, "", Lang_CXX);
1521
1522 auto hasImplicitClass = has(cxxRecordDecl());
1523 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1524 hasName("Base"),
1525 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1526 ASSERT_TRUE(
1527 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1528 EXPECT_TRUE(
1529 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1530}
1531
1532TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1533 Decl *From, *To;
1534 std::tie(From, To) =
1535 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1536
1537 MatchVerifier<Decl> Verifier;
1538 auto Matcher = functionDecl();
1539 ASSERT_TRUE(Verifier.match(From, Matcher));
1540 EXPECT_TRUE(Verifier.match(To, Matcher));
1541 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1542}
1543
Gabor Marton2ae9da32018-05-18 15:46:18 +00001544TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001545 Decl *FromTU = getTuDecl(
1546 R"(
1547 struct X {};
1548 void operator<<(int, X);
1549 )",
1550 Lang_CXX);
1551 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1552 const Decl *To = Import(From, Lang_CXX);
1553 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1554}
1555
1556TEST_P(ASTImporterTestBase,
1557 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1558 Decl *From, *To;
1559 std::tie(From, To) = getImportedDecl(
1560 R"(
1561 template<class T>
1562 class Base { int a; };
1563 class declToImport : Base<declToImport> {};
1564 )",
1565 Lang_CXX, "", Lang_CXX);
1566
1567 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1568 hasName("Base"),
1569 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1570 ASSERT_TRUE(
1571 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1572 EXPECT_TRUE(
1573 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1574}
1575
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001576TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1577 {
1578 Decl *FromTU = getTuDecl(
1579 R"(
1580 template <typename T>
1581 struct B;
1582 )",
1583 Lang_CXX, "input0.cc");
1584 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1585 FromTU, classTemplateDecl(hasName("B")));
1586
1587 Import(FromD, Lang_CXX);
1588 }
1589
1590 {
1591 Decl *FromTU = getTuDecl(
1592 R"(
1593 template <typename T>
1594 struct B {
1595 void f();
1596 };
1597 )",
1598 Lang_CXX, "input1.cc");
1599 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1600 FromTU, functionDecl(hasName("f")));
1601 Import(FromD, Lang_CXX);
1602 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1603 FromTU, classTemplateDecl(hasName("B")));
1604 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1605 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1606 }
1607}
1608
Gabor Marton9581c332018-05-23 13:53:36 +00001609TEST_P(ASTImporterTestBase,
1610 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1611 Decl *ToTU = getToTuDecl(
1612 R"(
1613 template <typename T>
1614 struct B {
1615 void f();
1616 };
1617
1618 template <typename T>
1619 struct B;
1620 )",
1621 Lang_CXX);
1622 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1623 [](const ClassTemplateDecl *T) {
1624 return T->isThisDeclarationADefinition();
1625 })
1626 .match(ToTU, classTemplateDecl()));
1627
1628 Decl *FromTU = getTuDecl(
1629 R"(
1630 template <typename T>
1631 struct B {
1632 void f();
1633 };
1634 )",
1635 Lang_CXX, "input1.cc");
1636 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1637 FromTU, classTemplateDecl(hasName("B")));
1638
1639 Import(FromD, Lang_CXX);
1640
1641 // We should have only one definition.
1642 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1643 [](const ClassTemplateDecl *T) {
1644 return T->isThisDeclarationADefinition();
1645 })
1646 .match(ToTU, classTemplateDecl()));
1647}
1648
1649TEST_P(ASTImporterTestBase,
1650 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1651 Decl *ToTU = getToTuDecl(
1652 R"(
1653 struct B {
1654 void f();
1655 };
1656
1657 struct B;
1658 )",
1659 Lang_CXX);
1660 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001661 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001662
1663 Decl *FromTU = getTuDecl(
1664 R"(
1665 struct B {
1666 void f();
1667 };
1668 )",
1669 Lang_CXX, "input1.cc");
1670 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1671 FromTU, cxxRecordDecl(hasName("B")));
1672
1673 Import(FromD, Lang_CXX);
1674
1675 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001676 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001677}
1678
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001679static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1680 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1681 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1682 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1683 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1684}
1685static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1686 SourceManager &SM1, SourceManager &SM2) {
1687 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1688 FullSourceLoc{ Range2.getBegin(), SM2 });
1689 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1690 FullSourceLoc{ Range2.getEnd(), SM2 });
1691}
1692TEST_P(ASTImporterTestBase, ImportSourceLocs) {
1693 Decl *FromTU = getTuDecl(
1694 R"(
1695 #define MFOO(arg) arg = arg + 1
1696
1697 void foo() {
1698 int a = 5;
1699 MFOO(a);
1700 }
1701 )",
1702 Lang_CXX);
1703 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1704 auto ToD = Import(FromD, Lang_CXX);
1705
1706 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1707 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1708 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1709 auto FromRHS =
1710 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1711
1712 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1713 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1714 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1715 FromSM);
1716 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1717 FromSM);
1718 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1719 FromSM);
1720}
1721
Rafael Stahla0010472018-07-09 08:40:17 +00001722TEST_P(ASTImporterTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001723 Decl *FromTU = getTuDecl(
1724 R"(
1725 #define FUNC_INT void declToImport
1726 #define FUNC FUNC_INT
1727 FUNC(int a);
1728 )",
1729 Lang_CXX);
1730 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1731 auto ToD = Import(FromD, Lang_CXX);
1732
1733 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1734 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1735 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1736 FromSM);
1737}
1738
Gabor Marton9581c332018-05-23 13:53:36 +00001739TEST_P(
1740 ASTImporterTestBase,
1741 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1742{
1743 Decl *ToTU = getToTuDecl(
1744 R"(
1745 template <typename T>
1746 struct B;
1747
1748 template <>
1749 struct B<int> {};
1750
1751 template <>
1752 struct B<int>;
1753 )",
1754 Lang_CXX);
1755 // We should have only one definition.
1756 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1757 [](const ClassTemplateSpecializationDecl *T) {
1758 return T->isThisDeclarationADefinition();
1759 })
1760 .match(ToTU, classTemplateSpecializationDecl()));
1761
1762 Decl *FromTU = getTuDecl(
1763 R"(
1764 template <typename T>
1765 struct B;
1766
1767 template <>
1768 struct B<int> {};
1769 )",
1770 Lang_CXX, "input1.cc");
1771 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1772 FromTU, classTemplateSpecializationDecl(hasName("B")));
1773
1774 Import(FromD, Lang_CXX);
1775
1776 // We should have only one definition.
1777 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1778 [](const ClassTemplateSpecializationDecl *T) {
1779 return T->isThisDeclarationADefinition();
1780 })
1781 .match(ToTU, classTemplateSpecializationDecl()));
1782}
1783
Gabor Marton0bebf952018-07-05 09:51:13 +00001784TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
1785 Decl *FromTU = getTuDecl(
1786 R"(
1787 struct { int a; int b; } object0 = { 2, 3 };
1788 struct { int x; int y; int z; } object1;
1789 )",
1790 Lang_CXX, "input0.cc");
1791
Gabor Marton0bebf952018-07-05 09:51:13 +00001792 auto *Obj0 =
1793 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1794 auto *From0 = getRecordDecl(Obj0);
1795 auto *Obj1 =
1796 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1797 auto *From1 = getRecordDecl(Obj1);
1798
1799 auto *To0 = Import(From0, Lang_CXX);
1800 auto *To1 = Import(From1, Lang_CXX);
1801
1802 EXPECT_TRUE(To0);
1803 EXPECT_TRUE(To1);
1804 EXPECT_NE(To0, To1);
1805 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1806}
1807
Gabor Marton26f72a92018-07-12 09:42:05 +00001808TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
1809 auto Pattern = varDecl(hasName("x"));
1810 VarDecl *Imported1;
1811 {
1812 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1813 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1814 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1815 }
1816 VarDecl *Imported2;
1817 {
1818 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1819 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1820 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1821 }
1822 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1823 EXPECT_FALSE(Imported2->isUsed(false));
1824 {
1825 Decl *FromTU =
1826 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
1827 auto *FromD =
1828 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1829 Import(FromD, Lang_CXX);
1830 }
1831 EXPECT_TRUE(Imported2->isUsed(false));
1832}
1833
1834TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
1835 auto Pattern = varDecl(hasName("x"));
1836
1837 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1838 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1839
1840 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1841
1842 ASSERT_FALSE(Imported1->isUsed(false));
1843
1844 FromD->setIsUsed();
1845 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1846
1847 EXPECT_EQ(Imported1, Imported2);
1848 EXPECT_TRUE(Imported2->isUsed(false));
1849}
1850
Peter Szecsidedda6f2018-03-30 22:03:29 +00001851struct ImportFunctions : ASTImporterTestBase {};
1852
1853TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001854 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1855 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1856 auto Pattern = functionDecl(hasName("f"));
1857 FunctionDecl *FromD = // Definition
1858 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1859
1860 Decl *ImportedD = Import(FromD, Lang_CXX);
1861 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1862
Gabor Marton5254e642018-06-27 13:32:50 +00001863 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001864 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1865}
1866
1867TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1868 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1869 auto Pattern = functionDecl(hasName("f"));
1870 FunctionDecl *FromD =
1871 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1872
1873 Decl *ImportedD = Import(FromD, Lang_CXX);
1874 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1875
1876 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1877 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1878}
1879
Gabor Marton5254e642018-06-27 13:32:50 +00001880TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001881 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1882 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001883 auto *From =
1884 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001885
Gabor Marton5254e642018-06-27 13:32:50 +00001886 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001887 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1888
Gabor Marton5254e642018-06-27 13:32:50 +00001889 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1890 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1891 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1892 EXPECT_TRUE(ImportedD == To0);
1893 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1894 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1895 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001896}
1897
1898TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1899 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1900 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001901 auto *From =
1902 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001903
Gabor Marton5254e642018-06-27 13:32:50 +00001904 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001905 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1906
Gabor Marton5254e642018-06-27 13:32:50 +00001907 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1908 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1909 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1910 EXPECT_TRUE(ImportedD == To1);
1911 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1912 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1913 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001914}
1915
1916TEST_P(ImportFunctions, ImportPrototypes) {
1917 auto Pattern = functionDecl(hasName("f"));
1918
1919 Decl *ImportedD;
1920 {
1921 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001922 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001923
1924 ImportedD = Import(FromD, Lang_CXX);
1925 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001926 {
1927 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001928 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1929 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001930 }
1931
Gabor Marton5254e642018-06-27 13:32:50 +00001932 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1933
1934 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1935 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1936 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1937 EXPECT_TRUE(ImportedD == To0);
1938 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1939 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1940 EXPECT_EQ(To1->getPreviousDecl(), To0);
1941}
1942
1943TEST_P(ImportFunctions, ImportDefinitions) {
1944 auto Pattern = functionDecl(hasName("f"));
1945
1946 Decl *ImportedD;
1947 {
1948 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1949 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1950 ImportedD = Import(FromD, Lang_CXX);
1951 }
1952 {
1953 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
1954 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1955 Import(FromD, Lang_CXX);
1956 }
1957
1958 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1959
Peter Szecsidedda6f2018-03-30 22:03:29 +00001960 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00001961 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1962 EXPECT_TRUE(ImportedD == To0);
1963 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001964}
1965
1966TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1967 auto Pattern = functionDecl(hasName("f"));
1968
1969 Decl *ImportedD;
1970 {
1971 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001972 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001973 ImportedD = Import(FromD, Lang_CXX);
1974 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001975 {
1976 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001977 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1978 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001979 }
1980
1981 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001982
1983 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1984 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1985 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1986 EXPECT_TRUE(ImportedD == To0);
1987 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
1988 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1989 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001990}
1991
1992TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1993 auto Pattern = functionDecl(hasName("f"));
1994
1995 {
1996 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1997 FunctionDecl *FromD =
1998 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1999
2000 Import(FromD, Lang_CXX);
2001 }
2002 {
2003 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
2004 FunctionDecl *FromD =
2005 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2006 Import(FromD, Lang_CXX);
2007 }
2008
2009 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2010 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2011 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002012 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002013 FunctionDecl *DefinitionD =
2014 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2015 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
2016 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
2017}
2018
Gabor Marton5254e642018-06-27 13:32:50 +00002019TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002020 auto Pattern = functionDecl(hasName("f"));
2021
2022 {
2023 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002024 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002025 Import(FromD, Lang_CXX);
2026 }
2027 {
2028 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002029 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002030 Import(FromD, Lang_CXX);
2031 }
2032
2033 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002034
2035 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002036 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002037 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
2038
Peter Szecsidedda6f2018-03-30 22:03:29 +00002039 FunctionDecl *DefinitionD =
2040 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2041 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00002042
2043 EXPECT_TRUE(DefinitionD->getPreviousDecl());
2044 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
2045 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002046}
2047
2048TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2049 auto Code =
2050 R"(
2051 struct B { virtual void f(); };
2052 void B::f() {}
2053 struct D : B { void f(); };
2054 )";
2055 auto Pattern =
2056 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2057 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2058 CXXMethodDecl *Proto =
2059 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2060
2061 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2062 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2063 EXPECT_EQ(To->size_overridden_methods(), 1u);
2064}
2065
2066TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2067 auto Code =
2068 R"(
2069 struct B { virtual void f(); };
2070 void B::f() {}
2071 )";
2072 auto Pattern =
2073 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2074 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2075 CXXMethodDecl *Proto =
2076 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2077 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2078
2079 ASSERT_TRUE(Proto->isVirtual());
2080 ASSERT_TRUE(Def->isVirtual());
2081 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2082 EXPECT_TRUE(To->isVirtual());
2083}
2084
Gabor Marton5254e642018-06-27 13:32:50 +00002085TEST_P(ImportFunctions,
2086 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2087 Decl *ToTU = getToTuDecl(
2088 R"(
2089 void f() {}
2090 void f();
2091 )",
2092 Lang_CXX);
2093 ASSERT_EQ(1u,
2094 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2095 return FD->doesThisDeclarationHaveABody();
2096 }).match(ToTU, functionDecl()));
2097
2098 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2099 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2100
2101 Import(FromD, Lang_CXX);
2102
2103 EXPECT_EQ(1u,
2104 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2105 return FD->doesThisDeclarationHaveABody();
2106 }).match(ToTU, functionDecl()));
2107}
2108
2109struct ImportFriendFunctions : ImportFunctions {};
2110
2111TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2112 auto Pattern = functionDecl(hasName("f"));
2113
2114 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2115 "void f();",
2116 Lang_CXX,
2117 "input0.cc");
2118 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2119
2120 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2121 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2122 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2123 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2124 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2125 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2126 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2127}
2128
2129TEST_P(ImportFriendFunctions,
2130 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2131 auto Pattern = functionDecl(hasName("f"));
2132
2133 Decl *FromTU = getTuDecl("void f();"
2134 "struct X { friend void f(); };",
2135 Lang_CXX, "input0.cc");
2136 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2137
2138 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2139 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2140 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2141 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2142 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2143 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2144 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2145}
2146
2147TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2148 auto Pattern = functionDecl(hasName("f"));
2149
2150 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2151 "void f();",
2152 Lang_CXX,
2153 "input0.cc");
2154 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2155
2156 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2157 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2158 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2159 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2160 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2161 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2162 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2163}
2164
2165TEST_P(ImportFriendFunctions,
2166 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2167 auto Pattern = functionDecl(hasName("f"));
2168
2169 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2170 "void f(){}",
2171 Lang_CXX, "input0.cc");
2172 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2173
2174 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2175 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2176 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2177 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2178 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2179 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2180 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2181}
2182
Gabor Marton26f72a92018-07-12 09:42:05 +00002183// Disabled temporarily, because the new structural equivalence check
2184// (https://reviews.llvm.org/D48628) breaks it.
2185// PreviousDecl is not set because there is no structural match.
2186// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002187TEST_P(ImportFriendFunctions,
2188 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2189 auto Pattern = functionDecl(hasName("f"));
2190
2191 Decl *FromTU = getTuDecl(
2192 R"(
2193 class X;
2194 void f(X *x){}
2195 class X{
2196 friend void f(X *x);
2197 };
2198 )",
2199 Lang_CXX, "input0.cc");
2200 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2201
2202 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2203 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2204 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2205 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2206 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2207 .match(ToTU, friendDecl())
2208 ->getFriendDecl());
2209 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2210 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2211 // The parameters must refer the same type
2212 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2213 (*ImportedD->param_begin())->getOriginalType());
2214}
2215
Gabor Marton26f72a92018-07-12 09:42:05 +00002216// Disabled temporarily, because the new structural equivalence check
2217// (https://reviews.llvm.org/D48628) breaks it.
2218// PreviousDecl is not set because there is no structural match.
2219// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002220TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002221 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002222 auto Pattern = functionDecl(hasName("f"));
2223
2224 Decl *FromTU = getTuDecl(
2225 R"(
2226 class X;
2227 void f(X *x){}
2228 class X{
2229 friend void f(X *x);
2230 };
2231 )",
2232 Lang_CXX, "input0.cc");
2233 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2234
2235 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2236 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2237 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2238 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2239 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2240 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2241
2242 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2243 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2244 // The parameters must refer the same type
2245 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2246 (*ImportedD->param_begin())->getOriginalType());
2247}
2248
2249TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2250 auto Pattern = functionDecl(hasName("f"));
2251
2252 FunctionDecl *ImportedD;
2253 {
2254 Decl *FromTU =
2255 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2256 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2257 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2258 }
2259 FunctionDecl *ImportedD1;
2260 {
2261 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2262 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2263 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2264 }
2265
2266 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2267 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2268 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2269 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2270 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2271}
2272
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002273AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2274 InnerMatcher) {
2275 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2276 return InnerMatcher.matches(*Typedef, Finder, Builder);
2277 return false;
2278}
2279
Gabor Marton19f4f392018-06-25 13:04:37 +00002280TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002281 CodeFiles Samples{{"main.c",
2282 {"void foo();"
2283 "void moo();"
2284 "int main() { foo(); moo(); }",
2285 Lang_C}},
2286
2287 {"foo.c",
2288 {"typedef enum { THING_VALUE } thing_t;"
2289 "void conflict(thing_t type);"
2290 "void foo() { (void)THING_VALUE; }"
2291 "void conflict(thing_t type) {}",
2292 Lang_C}},
2293
2294 {"moo.c",
2295 {"typedef enum { THING_VALUE } thing_t;"
2296 "void conflict(thing_t type);"
2297 "void moo() { conflict(THING_VALUE); }",
2298 Lang_C}}};
2299
2300 auto VerificationMatcher =
2301 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2302 hasTypedefForAnonDecl(hasName("thing_t")));
2303
2304 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2305 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2306
2307 testImportSequence(
2308 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2309 // Just check that there is only one enum decl in the result AST.
2310 "main.c", enumDecl(), VerificationMatcher);
2311
2312 // For different import order, result should be the same.
2313 testImportSequence(
2314 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2315 // Check that there is only one enum decl in the result AST.
2316 "main.c", enumDecl(), VerificationMatcher);
2317}
2318
Peter Szecsice7f3182018-05-07 12:08:27 +00002319const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2320 dependentScopeDeclRefExpr;
2321
Gabor Marton19f4f392018-06-25 13:04:37 +00002322TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002323 MatchVerifier<Decl> Verifier;
2324 testImport("template <typename T> struct S { static T foo; };"
2325 "template <typename T> void declToImport() {"
2326 " (void) S<T>::foo;"
2327 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002328 "void instantiate() { declToImport<int>(); }"
2329 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002330 Lang_CXX11, "", Lang_CXX11, Verifier,
2331 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2332 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2333
2334 testImport("template <typename T> struct S {"
2335 "template<typename S> static void foo(){};"
2336 "};"
2337 "template <typename T> void declToImport() {"
2338 " S<T>::template foo<T>();"
2339 "}"
2340 "void instantiate() { declToImport<int>(); }",
2341 Lang_CXX11, "", Lang_CXX11, Verifier,
2342 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2343 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2344}
2345
2346const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2347 dependentNameType;
2348
Gabor Marton19f4f392018-06-25 13:04:37 +00002349TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002350 MatchVerifier<Decl> Verifier;
2351 testImport("template <typename T> struct declToImport {"
2352 " typedef typename T::type dependent_name;"
2353 "};",
2354 Lang_CXX11, "", Lang_CXX11, Verifier,
2355 classTemplateDecl(has(
2356 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2357}
2358
2359const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
2360 unresolvedMemberExpr;
2361
Gabor Marton19f4f392018-06-25 13:04:37 +00002362TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002363 MatchVerifier<Decl> Verifier;
2364 testImport("struct S { template <typename T> void mem(); };"
2365 "template <typename U> void declToImport() {"
2366 " S s;"
2367 " s.mem<U>();"
2368 "}"
2369 "void instantiate() { declToImport<int>(); }",
2370 Lang_CXX11, "", Lang_CXX11, Verifier,
2371 functionTemplateDecl(has(functionDecl(has(
2372 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2373}
2374
Balazs Keri1d20cc22018-07-16 12:16:39 +00002375class ImportImplicitMethods : public ASTImporterTestBase {
2376public:
2377 static constexpr auto DefaultCode = R"(
2378 struct A { int x; };
2379 void f() {
2380 A a;
2381 A a1(a);
2382 A a2(A{});
2383 a = a1;
2384 a = A{};
2385 a.~A();
2386 })";
2387
2388 template <typename MatcherType>
2389 void testImportOf(
2390 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2391 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2392 }
2393
2394 template <typename MatcherType>
2395 void testNoImportOf(
2396 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2397 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2398 }
2399
2400private:
2401 template <typename MatcherType>
2402 void test(const MatcherType &MethodMatcher,
2403 const char *Code, unsigned int ExpectedCount) {
2404 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2405
2406 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2407 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2408 ToTU, ClassMatcher);
2409
Balazs Keri2f752ba2018-07-16 14:05:18 +00002410 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002411
2412 {
2413 CXXMethodDecl *Method =
2414 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2415 ToClass->removeDecl(Method);
2416 }
2417
Balazs Keri2f752ba2018-07-16 14:05:18 +00002418 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002419
2420 Decl *ImportedClass = nullptr;
2421 {
2422 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2423 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2424 FromTU, ClassMatcher);
2425 ImportedClass = Import(FromClass, Lang_CXX11);
2426 }
2427
2428 EXPECT_EQ(ToClass, ImportedClass);
2429 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2430 ExpectedCount);
2431 }
2432};
2433
2434TEST_P(ImportImplicitMethods, DefaultConstructor) {
2435 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2436}
2437
2438TEST_P(ImportImplicitMethods, CopyConstructor) {
2439 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2440}
2441
2442TEST_P(ImportImplicitMethods, MoveConstructor) {
2443 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2444}
2445
2446TEST_P(ImportImplicitMethods, Destructor) {
2447 testImportOf(cxxDestructorDecl());
2448}
2449
2450TEST_P(ImportImplicitMethods, CopyAssignment) {
2451 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2452}
2453
2454TEST_P(ImportImplicitMethods, MoveAssignment) {
2455 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2456}
2457
2458TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2459 auto Code = R"(
2460 struct A { A() { int x; } };
2461 )";
2462 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2463}
2464
2465TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2466 auto Code = R"(
2467 struct A { A() = default; };
2468 )";
2469 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2470}
2471
2472TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2473 auto Code = R"(
2474 struct A { A() = delete; };
2475 )";
2476 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2477}
2478
2479TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2480 auto Code = R"(
2481 struct A { void f() { } };
2482 )";
2483 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2484}
2485
Balazs Keric7797c42018-07-11 09:37:24 +00002486TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
2487 Decl *ToR1;
2488 {
2489 Decl *FromTU = getTuDecl(
2490 "struct A { };", Lang_CXX, "input0.cc");
2491 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2492 FromTU, cxxRecordDecl(hasName("A")));
2493
2494 ToR1 = Import(FromR, Lang_CXX);
2495 }
2496
2497 Decl *ToR2;
2498 {
2499 Decl *FromTU = getTuDecl(
2500 "struct A { };", Lang_CXX, "input1.cc");
2501 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2502 FromTU, cxxRecordDecl(hasName("A")));
2503
2504 ToR2 = Import(FromR, Lang_CXX);
2505 }
2506
2507 EXPECT_EQ(ToR1, ToR2);
2508}
2509
2510TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
2511 Decl *ToR1;
2512 {
2513 Decl *FromTU = getTuDecl(
2514 "struct A { int x; };", Lang_CXX, "input0.cc");
2515 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2516 FromTU, cxxRecordDecl(hasName("A")));
2517 ToR1 = Import(FromR, Lang_CXX);
2518 }
2519 Decl *ToR2;
2520 {
2521 Decl *FromTU = getTuDecl(
2522 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2523 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2524 FromTU, cxxRecordDecl(hasName("A")));
2525 ToR2 = Import(FromR, Lang_CXX);
2526 }
2527 EXPECT_NE(ToR1, ToR2);
2528}
2529
2530TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
2531 Decl *ToF1;
2532 {
2533 Decl *FromTU = getTuDecl(
2534 "struct A { int x; };", Lang_CXX, "input0.cc");
2535 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2536 FromTU, fieldDecl(hasName("x")));
2537 ToF1 = Import(FromF, Lang_CXX);
2538 }
2539 Decl *ToF2;
2540 {
2541 Decl *FromTU = getTuDecl(
2542 "struct A { int x; };", Lang_CXX, "input1.cc");
2543 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2544 FromTU, fieldDecl(hasName("x")));
2545 ToF2 = Import(FromF, Lang_CXX);
2546 }
2547 EXPECT_EQ(ToF1, ToF2);
2548}
2549
2550TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
2551 Decl *ToF1;
2552 {
2553 Decl *FromTU = getTuDecl(
2554 "struct A { int x; };", Lang_CXX, "input0.cc");
2555 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2556 FromTU, fieldDecl(hasName("x")));
2557 ToF1 = Import(FromF, Lang_CXX);
2558 }
2559 Decl *ToF2;
2560 {
2561 Decl *FromTU = getTuDecl(
2562 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2563 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2564 FromTU, fieldDecl(hasName("x")));
2565 ToF2 = Import(FromF, Lang_CXX);
2566 }
2567 EXPECT_NE(ToF1, ToF2);
2568}
2569
2570TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
2571 Decl *ToM1;
2572 {
2573 Decl *FromTU = getTuDecl(
2574 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2575 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2576 FromTU, functionDecl(hasName("x"), isDefinition()));
2577 ToM1 = Import(FromM, Lang_CXX);
2578 }
2579 Decl *ToM2;
2580 {
2581 Decl *FromTU = getTuDecl(
2582 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2583 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2584 FromTU, functionDecl(hasName("x"), isDefinition()));
2585 ToM2 = Import(FromM, Lang_CXX);
2586 }
2587 EXPECT_EQ(ToM1, ToM2);
2588}
2589
2590TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
2591 Decl *ToM1;
2592 {
2593 Decl *FromTU = getTuDecl(
2594 "struct A { void x(); }; void A::x() { }",
2595 Lang_CXX, "input0.cc");
2596 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2597 FromTU, functionDecl(hasName("x"), isDefinition()));
2598 ToM1 = Import(FromM, Lang_CXX);
2599 }
2600 Decl *ToM2;
2601 {
2602 Decl *FromTU = getTuDecl(
2603 "struct A { void x() const; }; void A::x() const { }",
2604 Lang_CXX, "input1.cc");
2605 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2606 FromTU, functionDecl(hasName("x"), isDefinition()));
2607 ToM2 = Import(FromM, Lang_CXX);
2608 }
2609 EXPECT_NE(ToM1, ToM2);
2610}
2611
Gabor Martonf086fa82018-07-17 12:06:36 +00002612TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
2613 Decl *FromTU = getTuDecl(
2614 R"(
2615 struct A {
2616 struct {
2617 struct A *next;
2618 } entry0;
2619 struct {
2620 struct A *next;
2621 } entry1;
2622 };
2623 )",
2624 Lang_C, "input0.cc");
2625 auto *From =
2626 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
2627
2628 Import(From, Lang_C);
2629
2630 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2631 auto *Entry0 =
2632 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
2633 auto *Entry1 =
2634 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
2635 auto *R0 = getRecordDecl(Entry0);
2636 auto *R1 = getRecordDecl(Entry1);
2637 EXPECT_NE(R0, R1);
2638 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2639 R0, recordDecl(has(fieldDecl(hasName("next"))))));
2640 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2641 R1, recordDecl(has(fieldDecl(hasName("next"))))));
2642}
2643
Balazs Keri2544b4b2018-08-08 09:40:57 +00002644TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
2645 Decl *FromTU = getTuDecl(
2646 R"(
2647 void f(int X, int Y, bool Z) {
2648 (void)[X, Y, Z] { (void)Z; };
2649 }
2650 )",
2651 Lang_CXX11, "input0.cc");
2652 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
2653 FromTU, functionDecl(hasName("f")));
2654 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
2655 EXPECT_TRUE(ToF);
2656
2657 CXXRecordDecl *FromLambda =
2658 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
2659 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
2660
2661 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
2662 EXPECT_TRUE(ToLambda);
2663
2664 // Check if the fields of the lambda class are imported in correct order.
2665 unsigned FromIndex = 0u;
2666 for (auto *FromField : FromLambda->fields()) {
2667 ASSERT_FALSE(FromField->getDeclName());
2668 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
2669 EXPECT_TRUE(ToField);
2670 unsigned ToIndex = ASTImporter::getFieldIndex(ToField);
2671 EXPECT_EQ(ToIndex, FromIndex + 1);
2672 ++FromIndex;
2673 }
2674
2675 EXPECT_EQ(FromIndex, 3u);
2676}
2677
Gabor Marton61d862a2018-05-18 09:08:47 +00002678struct DeclContextTest : ASTImporterTestBase {};
2679
2680TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
2681 Decl *TU = getTuDecl(
2682 R"(
2683 namespace NS {
2684
2685 template <typename T>
2686 struct S {};
2687 template struct S<int>;
2688
2689 inline namespace INS {
2690 template <typename T>
2691 struct S {};
2692 template struct S<int>;
2693 }
2694
2695 }
2696 )", Lang_CXX11, "input0.cc");
2697 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
2698 TU, namespaceDecl());
2699 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2700 TU, classTemplateSpecializationDecl());
2701 ASSERT_TRUE(NS->containsDecl(Spec));
2702
2703 NS->removeDecl(Spec);
2704 EXPECT_FALSE(NS->containsDecl(Spec));
2705}
2706
Gabor Marton5254e642018-06-27 13:32:50 +00002707struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
2708
2709TEST_P(ImportFunctionTemplateSpecializations,
2710 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
2711
2712 Decl *FromTU = getTuDecl(
2713 R"(
2714 template<class T>
2715 int f() { return 0; }
2716 void foo() { f<int>(); }
2717 )",
2718 Lang_CXX, "input0.cc");
2719
2720 // Check that the function template instantiation is NOT the child of the TU.
2721 auto Pattern = translationUnitDecl(
2722 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
2723 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2724
2725 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
2726 FromTU, functionDecl(hasName("foo")));
2727 ASSERT_TRUE(Import(Foo, Lang_CXX));
2728
2729 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2730 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2731}
2732
2733TEST_P(ImportFunctionTemplateSpecializations,
2734 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
2735
2736 Decl *FromTU = getTuDecl(
2737 R"(
2738 template<class T>
2739 int f() { return 0; }
2740 template int f<int>();
2741 )",
2742 Lang_CXX, "input0.cc");
2743
2744 // Check that the function template instantiation is NOT the child of the TU.
2745 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
2746 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
2747 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2748
2749 ASSERT_TRUE(
2750 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
2751
2752 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2753 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2754}
2755
2756TEST_P(ImportFunctionTemplateSpecializations,
2757 TUshouldContainFunctionTemplateSpecialization) {
2758
2759 Decl *FromTU = getTuDecl(
2760 R"(
2761 template<class T>
2762 int f() { return 0; }
2763 template <> int f<int>() { return 4; }
2764 )",
2765 Lang_CXX, "input0.cc");
2766
2767 // Check that the function template specialization is the child of the TU.
2768 auto Specialization =
2769 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2770 auto Pattern = translationUnitDecl(has(Specialization));
2771 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2772
2773 ASSERT_TRUE(
2774 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
2775
2776 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2777 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2778}
2779
2780TEST_P(ImportFunctionTemplateSpecializations,
2781 FunctionTemplateSpecializationRedeclChain) {
2782
2783 Decl *FromTU = getTuDecl(
2784 R"(
2785 template<class T>
2786 int f() { return 0; }
2787 template <> int f<int>() { return 4; }
2788 )",
2789 Lang_CXX, "input0.cc");
2790
2791 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
2792 hasParent(translationUnitDecl()));
2793 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
2794 {
2795 auto *TU = FromTU;
2796 auto *SpecD = FromSpecD;
2797 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2798 TU, functionTemplateDecl());
2799 auto *FirstSpecD = *(TemplateD->spec_begin());
2800 ASSERT_EQ(SpecD, FirstSpecD);
2801 ASSERT_TRUE(SpecD->getPreviousDecl());
2802 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2803 ->doesThisDeclarationHaveABody());
2804 }
2805
2806 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
2807
2808 {
2809 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
2810 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
2811 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2812 TU, functionTemplateDecl());
2813 auto *FirstSpecD = *(TemplateD->spec_begin());
2814 EXPECT_EQ(SpecD, FirstSpecD);
2815 ASSERT_TRUE(SpecD->getPreviousDecl());
2816 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2817 ->doesThisDeclarationHaveABody());
2818 }
2819}
2820
2821TEST_P(ImportFunctionTemplateSpecializations,
2822 MatchNumberOfFunctionTemplateSpecializations) {
2823
2824 Decl *FromTU = getTuDecl(
2825 R"(
2826 template <typename T> constexpr int f() { return 0; }
2827 template <> constexpr int f<int>() { return 4; }
2828 void foo() {
2829 static_assert(f<char>() == 0, "");
2830 static_assert(f<int>() == 4, "");
2831 }
2832 )",
2833 Lang_CXX11, "input0.cc");
2834 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2835 FromTU, functionDecl(hasName("foo")));
2836
2837 Import(FromD, Lang_CXX11);
2838 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2839 EXPECT_EQ(
2840 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
2841 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
2842}
2843
2844TEST_P(ImportFunctionTemplateSpecializations,
2845 ImportPrototypes) {
2846 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2847 auto Code =
2848 R"(
2849 // Proto of the primary template.
2850 template <class T>
2851 void f();
2852 // Proto of the specialization.
2853 template <>
2854 void f<int>();
2855 )";
2856
2857 Decl *ImportedD;
2858 {
2859 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2860 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2861
2862 ImportedD = Import(FromD, Lang_CXX);
2863 }
2864 {
2865 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2866 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2867 Import(FromD, Lang_CXX);
2868 }
2869
2870 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2871
2872 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2873 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2874 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2875 EXPECT_TRUE(ImportedD == To0);
2876 EXPECT_TRUE(ImportedD != To1);
2877 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2878 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2879 // Check that they are part of the same redecl chain.
2880 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
2881}
2882
2883TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
2884 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2885 auto Code =
2886 R"(
2887 // Proto of the primary template.
2888 template <class T>
2889 void f();
2890 // Specialization and definition.
2891 template <>
2892 void f<int>() {}
2893 )";
2894
2895 Decl *ImportedD;
2896 {
2897 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2898 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2899 ImportedD = Import(FromD, Lang_CXX);
2900 }
2901 {
2902 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2903 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2904 Import(FromD, Lang_CXX);
2905 }
2906
2907 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2908
2909 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2910 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2911 EXPECT_TRUE(ImportedD == To0);
2912 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2913
2914 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2915 ToTU, functionTemplateDecl());
2916 auto *FirstSpecD = *(TemplateD->spec_begin());
2917 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
2918}
2919
2920TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
2921 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2922 auto Code =
2923 R"(
2924 // Proto of the primary template.
2925 template <class T>
2926 void f();
2927 // Specialization proto.
2928 template <>
2929 void f<int>();
2930 // Specialization proto.
2931 template <>
2932 void f<int>();
2933 )";
2934
2935 Decl *ImportedD;
2936 {
2937 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2938 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2939 ImportedD = Import(FromD, Lang_CXX);
2940 }
2941
2942 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2943
2944 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2945 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2946 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2947 EXPECT_TRUE(ImportedD == To0);
2948 EXPECT_TRUE(ImportedD != To1);
2949 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2950 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2951 EXPECT_EQ(To1->getPreviousDecl(), To0);
2952}
2953
2954TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
2955 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2956 auto Code =
2957 R"(
2958 // Proto of the primary template.
2959 template <class T>
2960 void f();
2961 // Specialization proto.
2962 template <>
2963 void f<int>();
2964 // Specialization definition.
2965 template <>
2966 void f<int>() {}
2967 )";
2968
2969 Decl *ImportedD;
2970 {
2971 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2972 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2973 ImportedD = Import(FromD, Lang_CXX);
2974 }
2975
2976 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2977
2978 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2979 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2980 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2981 EXPECT_TRUE(ImportedD == To0);
2982 EXPECT_TRUE(ImportedD != To1);
2983 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2984 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2985 EXPECT_EQ(To1->getPreviousDecl(), To0);
2986}
2987
2988TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
2989 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2990 auto Code =
2991 R"(
2992 // Proto of the primary template.
2993 template <class T>
2994 void f();
2995 // Specialization definition.
2996 template <>
2997 void f<int>() {}
2998 // Specialization proto.
2999 template <>
3000 void f<int>();
3001 )";
3002
3003 Decl *ImportedD;
3004 {
3005 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3006 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3007 ImportedD = Import(FromD, Lang_CXX);
3008 }
3009
3010 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3011
3012 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3013 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3014 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3015 EXPECT_TRUE(ImportedD == To0);
3016 EXPECT_TRUE(ImportedD != To1);
3017 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
3018 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3019 EXPECT_EQ(To1->getPreviousDecl(), To0);
3020}
3021
Gabor Marton19f4f392018-06-25 13:04:37 +00003022INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
3023 ::testing::Values(ArgVector()), );
3024
Gabor Marton5254e642018-06-27 13:32:50 +00003025INSTANTIATE_TEST_CASE_P(
3026 ParameterizedTests, CanonicalRedeclChain,
3027 ::testing::Values(ArgVector()),);
3028
Gabor Marton19f4f392018-06-25 13:04:37 +00003029auto DefaultTestValuesForRunOptions = ::testing::Values(
3030 ArgVector(),
3031 ArgVector{"-fdelayed-template-parsing"},
3032 ArgVector{"-fms-compatibility"},
3033 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
3034
3035INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
3036 DefaultTestValuesForRunOptions, );
3037
3038INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
3039 DefaultTestValuesForRunOptions, );
3040
3041INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
3042 DefaultTestValuesForRunOptions, );
3043
3044INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
3045 DefaultTestValuesForRunOptions, );
3046
3047INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
3048 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00003049
Gabor Marton5254e642018-06-27 13:32:50 +00003050INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
3051 DefaultTestValuesForRunOptions, );
3052
3053INSTANTIATE_TEST_CASE_P(ParameterizedTests,
3054 ImportFunctionTemplateSpecializations,
3055 DefaultTestValuesForRunOptions, );
3056
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00003057} // end namespace ast_matchers
3058} // end namespace clang