blob: 70edd150467c462741a154eb9f2846d714b2c0c6 [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 Martonbf7f18b2018-08-09 12:18:07 +0000556TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
557 MatchVerifier<Decl> Verifier;
558 testImport(
559 "void declToImport() { (void)1.0i; }",
560 Lang_CXX14, "", Lang_CXX14, Verifier,
561 functionDecl(hasDescendant(imaginaryLiteral())));
562}
563
Gabor Marton19f4f392018-06-25 13:04:37 +0000564TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000565 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000566 testImport(
567 "void declToImport() {"
568 " struct s { int x; long y; unsigned z; }; "
569 " (void)(struct s){ 42, 0L, 1U }; }",
570 Lang_CXX, "", Lang_CXX, Verifier,
571 functionDecl(hasDescendant(
572 compoundLiteralExpr(
573 hasType(asString("struct s")),
574 has(initListExpr(
575 hasType(asString("struct s")),
576 has(integerLiteral(
577 equals(42), hasType(asString("int")))),
578 has(integerLiteral(
579 equals(0), hasType(asString("long")))),
580 has(integerLiteral(
581 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000582}
583
Gabor Marton19f4f392018-06-25 13:04:37 +0000584TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000585 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000586 testImport(
587 "class declToImport { void f() { (void)this; } };",
588 Lang_CXX, "", Lang_CXX, Verifier,
589 cxxRecordDecl(
590 hasMethod(
591 hasDescendant(
592 cxxThisExpr(
593 hasType(
594 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000595}
596
Gabor Marton19f4f392018-06-25 13:04:37 +0000597TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000598 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000599 testImport(
600 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
601 Lang_C, "", Lang_C, Verifier,
602 functionDecl(hasDescendant(
603 atomicExpr(
604 has(ignoringParenImpCasts(
605 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
606 hasType(asString("int *"))))),
607 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000608}
609
Gabor Marton19f4f392018-06-25 13:04:37 +0000610TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000611 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000612 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000613 "void declToImport() { loop: goto loop; (void)&&loop; }",
614 Lang_C, "", Lang_C, Verifier,
615 functionDecl(
616 hasDescendant(
617 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
618 hasDescendant(
619 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000620}
621
622AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
623 internal::Matcher<NamedDecl>, InnerMatcher) {
624 const NamedDecl *Template = Node.getTemplatedDecl();
625 return Template && InnerMatcher.matches(*Template, Finder, Builder);
626}
627
Gabor Marton19f4f392018-06-25 13:04:37 +0000628TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000629 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000630 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000631 "template<typename T> class dummy { void f() { dummy X(*this); } };"
632 "typedef dummy<int> declToImport;"
633 "template class dummy<int>;",
634 Lang_CXX, "", Lang_CXX, Verifier,
635 typedefDecl(hasType(templateSpecializationType(
636 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
637 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
638 hasName("f"),
639 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
640 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
641 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000642 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000643}
644
Gabor Marton19f4f392018-06-25 13:04:37 +0000645TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000646 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000647 testImport(
648 "void declToImport() { int b; switch (b) { case 1: break; } }",
649 Lang_C, "", Lang_C, Verifier,
650 functionDecl(hasDescendant(
651 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000652}
653
Gabor Marton19f4f392018-06-25 13:04:37 +0000654TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000655 MatchVerifier<Decl> Verifier;
656 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000657 testImport(
658 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
659 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000660 functionDecl(hasDescendant(
661 varDecl(
662 hasName("C"),
663 hasType(asString("int")),
664 hasInitializer(
665 stmtExpr(
666 hasAnySubstatement(declStmt(hasSingleDecl(
667 varDecl(
668 hasName("X"),
669 hasType(asString("int")),
670 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000671 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000672 hasDescendant(
673 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000674}
675
Gabor Marton19f4f392018-06-25 13:04:37 +0000676TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000677 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000678 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000679 "void declToImport() { (void)(true ? 1 : -5); }",
680 Lang_CXX, "", Lang_CXX, Verifier,
681 functionDecl(hasDescendant(
682 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000683 hasCondition(cxxBoolLiteral(equals(true))),
684 hasTrueExpression(integerLiteral(equals(1))),
685 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000686 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
687 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000688}
689
Gabor Marton19f4f392018-06-25 13:04:37 +0000690TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000691 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000692 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000693 "void declToImport() { (void)(1 ?: -5); }",
694 Lang_CXX, "", Lang_CXX, Verifier,
695 functionDecl(hasDescendant(
696 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000697 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000698 implicitCastExpr(
699 hasSourceExpression(opaqueValueExpr(
700 hasSourceExpression(integerLiteral(equals(1))))),
701 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000702 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000703 opaqueValueExpr(
704 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000705 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000706 unaryOperator(
707 hasOperatorName("-"),
708 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000709}
710
Gabor Marton19f4f392018-06-25 13:04:37 +0000711TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000712 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000713 testImport(
714 "void declToImport() {"
715 " struct point { double x; double y; };"
716 " struct point ptarray[10] = "
717 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
718 Lang_C, "", Lang_C, Verifier,
719 functionDecl(hasDescendant(
720 initListExpr(
721 has(designatedInitExpr(
722 designatorCountIs(2),
723 has(floatLiteral(equals(1.0))),
724 has(integerLiteral(equals(2))))),
725 has(designatedInitExpr(
726 designatorCountIs(2),
727 has(floatLiteral(equals(2.0))),
728 has(integerLiteral(equals(2))))),
729 has(designatedInitExpr(
730 designatorCountIs(2),
731 has(floatLiteral(equals(1.0))),
732 has(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000733}
734
735
Gabor Marton19f4f392018-06-25 13:04:37 +0000736TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000737 MatchVerifier<Decl> Verifier;
738 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000739 testImport(
740 "void declToImport() { (void)__func__; }",
741 Lang_CXX, "", Lang_CXX, Verifier,
742 functionDecl(hasDescendant(
743 predefinedExpr(
744 hasType(
745 asString("const char [13]")),
746 has(stringLiteral(hasType(
747 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000748}
749
Gabor Marton19f4f392018-06-25 13:04:37 +0000750TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000751 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000752 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000753 "void declToImport() {"
754 " struct point { double x; double y; };"
755 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
756 " [0].x = 1.0 }; }",
757 Lang_CXX, "", Lang_CXX, Verifier,
758 functionDecl(hasDescendant(
759 initListExpr(
760 has(
761 cxxConstructExpr(
762 requiresZeroInitialization())),
763 has(
764 initListExpr(
765 hasType(asString("struct point")),
766 has(floatLiteral(equals(1.0))),
767 has(implicitValueInitExpr(
768 hasType(asString("double")))))),
769 has(
770 initListExpr(
771 hasType(asString("struct point")),
772 has(floatLiteral(equals(2.0))),
773 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000774}
775
776
Aleksei Sidorina693b372016-09-28 10:16:56 +0000777const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
778
Gabor Marton19f4f392018-06-25 13:04:37 +0000779TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000780 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000781 testImport(
782 "void declToImport(__builtin_va_list list, ...) {"
783 " (void)__builtin_va_arg(list, int); }",
784 Lang_CXX, "", Lang_CXX, Verifier,
785 functionDecl(hasDescendant(
786 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000787}
788
Gabor Marton19f4f392018-06-25 13:04:37 +0000789TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000790 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000791 testImport(
792 "struct C {};"
793 "void declToImport() { C c = C(); }",
794 Lang_CXX, "", Lang_CXX, Verifier,
795 functionDecl(hasDescendant(
796 exprWithCleanups(has(cxxConstructExpr(
797 has(materializeTemporaryExpr(has(implicitCastExpr(
798 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000799}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000800
Gabor Marton19f4f392018-06-25 13:04:37 +0000801TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000802 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000803 testImport(
804 "void declToImport() { typedef _Atomic(int) a_int; }",
805 Lang_CXX11, "", Lang_CXX11, Verifier,
806 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000807}
808
Gabor Marton19f4f392018-06-25 13:04:37 +0000809TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000810 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000811 testImport(
812 "template <typename T> void declToImport() { };",
813 Lang_CXX, "", Lang_CXX, Verifier,
814 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000815}
816
817const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
818 cxxDependentScopeMemberExpr;
819
Gabor Marton19f4f392018-06-25 13:04:37 +0000820TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000821 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000822 testImport(
823 "template <typename T> struct C { T t; };"
824 "template <typename T> void declToImport() {"
825 " C<T> d;"
826 " (void)d.t;"
827 "}"
828 "void instantiate() { declToImport<int>(); }",
829 Lang_CXX, "", Lang_CXX, Verifier,
830 functionTemplateDecl(hasDescendant(
831 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
832 testImport(
833 "template <typename T> struct C { T t; };"
834 "template <typename T> void declToImport() {"
835 " C<T> d;"
836 " (void)(&d)->t;"
837 "}"
838 "void instantiate() { declToImport<int>(); }",
839 Lang_CXX, "", Lang_CXX, Verifier,
840 functionTemplateDecl(hasDescendant(
841 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000842}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000843
Gabor Marton19f4f392018-06-25 13:04:37 +0000844TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000845 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000846 testImport(
847 "template <int K>"
848 "struct dummy { static const int i = K; };"
849 "template <int K> using dummy2 = dummy<K>;"
850 "int declToImport() { return dummy2<3>::i; }",
851 Lang_CXX11, "", Lang_CXX11, Verifier,
852 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000853 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000854 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
855}
856
857const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
858 varTemplateSpecializationDecl;
859
Gabor Marton19f4f392018-06-25 13:04:37 +0000860TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000861 MatchVerifier<Decl> Verifier;
862 testImport(
863 "template <typename T>"
864 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000865 "void declToImport() { (void)pi<int>; }",
866 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000867 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000868 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000869 unless(hasAncestor(translationUnitDecl(has(varDecl(
870 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000871}
872
Gabor Marton19f4f392018-06-25 13:04:37 +0000873TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000874 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000875 testImport(
876 "template <typename... Args>"
877 "struct dummy {"
878 " dummy(Args... args) {}"
879 " static const int i = 4;"
880 "};"
881 "int declToImport() { return dummy<int>::i; }",
882 Lang_CXX11, "", Lang_CXX11, Verifier,
883 functionDecl(hasDescendant(
884 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000885}
886
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000887const internal::VariadicDynCastAllOfMatcher<Type,
888 DependentTemplateSpecializationType>
889 dependentTemplateSpecializationType;
890
Gabor Marton19f4f392018-06-25 13:04:37 +0000891TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000892 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000893 testImport(
894 "template<typename T>"
895 "struct A;"
896 "template<typename T>"
897 "struct declToImport {"
898 " typename A<T>::template B<T> a;"
899 "};",
900 Lang_CXX, "", Lang_CXX, Verifier,
901 classTemplateDecl(has(cxxRecordDecl(has(
902 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000903}
904
905const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
906 sizeOfPackExpr;
907
Gabor Marton19f4f392018-06-25 13:04:37 +0000908TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000909 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000910 testImport(
911 "template <typename... Ts>"
912 "void declToImport() {"
913 " const int i = sizeof...(Ts);"
914 "};"
915 "void g() { declToImport<int>(); }",
916 Lang_CXX11, "", Lang_CXX11, Verifier,
917 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000918 testImport(
919 "template <typename... Ts>"
920 "using X = int[sizeof...(Ts)];"
921 "template <typename... Us>"
922 "struct Y {"
923 " X<Us..., int, double, int, Us...> f;"
924 "};"
925 "Y<float, int> declToImport;",
926 Lang_CXX11, "", Lang_CXX11, Verifier,
927 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
928 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
929}
930
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000931/// \brief Matches __builtin_types_compatible_p:
932/// GNU extension to check equivalent types
933/// Given
934/// \code
935/// __builtin_types_compatible_p(int, int)
936/// \endcode
937// will generate TypeTraitExpr <...> 'int'
938const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
939
Gabor Marton19f4f392018-06-25 13:04:37 +0000940TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000941 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000942 testImport(
943 "void declToImport() { "
944 " (void)__builtin_types_compatible_p(int, int);"
945 "}",
946 Lang_C, "", Lang_C, Verifier,
947 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000948}
949
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000950const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
951
Gabor Marton19f4f392018-06-25 13:04:37 +0000952TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000953 MatchVerifier<Decl> Verifier;
954 testImport(
955 "namespace std { class type_info {}; }"
956 "void declToImport() {"
957 " int x;"
958 " auto a = typeid(int); auto b = typeid(x);"
959 "}",
960 Lang_CXX11, "", Lang_CXX11, Verifier,
961 functionDecl(
962 hasDescendant(varDecl(
963 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
964 hasDescendant(varDecl(
965 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
966}
967
Gabor Marton19f4f392018-06-25 13:04:37 +0000968TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000969 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000970 testImport(
971 "template<typename T> struct declToImport {"
972 " void m() { (void)__is_pod(T); }"
973 "};"
974 "void f() { declToImport<int>().m(); }",
975 Lang_CXX11, "", Lang_CXX11, Verifier,
976 classTemplateDecl(has(cxxRecordDecl(has(
977 functionDecl(hasDescendant(
978 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000979}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000980
Gabor Marton6e1510c2018-07-12 11:50:21 +0000981TEST_P(ImportDecl, ImportRecordDeclInFunc) {
982 MatchVerifier<Decl> Verifier;
983 testImport("int declToImport() { "
984 " struct data_t {int a;int b;};"
985 " struct data_t d;"
986 " return 0;"
987 "}",
988 Lang_C, "", Lang_C, Verifier,
989 functionDecl(hasBody(compoundStmt(
990 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
991}
992
993TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
994 Decl *FromTU = getTuDecl("int declToImport() { "
995 " struct data_t {int a;int b;};"
996 " struct data_t d;"
997 " return 0;"
998 "}",
999 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +00001000 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +00001001 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
1002 ASSERT_TRUE(FromVar);
1003 auto ToType =
1004 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
1005 EXPECT_FALSE(ToType.isNull());
1006}
1007
1008TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
1009 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +00001010 Decl *FromTU = getTuDecl(
1011 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1012 Lang_C, "input.c");
1013 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1014 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001015 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001016 auto *To = Import(From, Lang_C);
1017 EXPECT_EQ(To, nullptr);
1018}
1019
1020TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncFromMacro) {
1021 Decl *FromTU = getTuDecl(
1022 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1023 "int declToImport(){ return NONAME_SIZEOF(int); }",
1024 Lang_C, "input.c");
1025 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1026 FromTU, functionDecl(hasName("declToImport")));
1027 ASSERT_TRUE(From);
1028 auto *To = Import(From, Lang_C);
1029 ASSERT_TRUE(To);
1030 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1031 To, functionDecl(hasName("declToImport"),
1032 hasDescendant(unaryExprOrTypeTraitExpr()))));
1033}
1034
1035TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParamsFromMacro) {
1036 // This construct is not supported by ASTImporter.
1037 Decl *FromTU = getTuDecl(
1038 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1039 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1040 Lang_C, "input.c");
1041 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1042 FromTU, functionDecl(hasName("declToImport")));
1043 ASSERT_TRUE(From);
1044 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001045 EXPECT_EQ(To, nullptr);
1046}
1047
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001048const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1049 cxxPseudoDestructorExpr;
1050
Gabor Marton19f4f392018-06-25 13:04:37 +00001051TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001052 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001053 testImport(
1054 "typedef int T;"
1055 "void declToImport(int *p) {"
1056 " T t;"
1057 " p->T::~T();"
1058 "}",
1059 Lang_CXX, "", Lang_CXX, Verifier,
1060 functionDecl(hasDescendant(
1061 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001062}
1063
Gabor Marton19f4f392018-06-25 13:04:37 +00001064TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001065 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001066 testImport(
1067 "namespace foo { int bar; }"
1068 "void declToImport() { using foo::bar; }",
1069 Lang_CXX, "", Lang_CXX, Verifier,
1070 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001071}
1072
1073/// \brief Matches shadow declarations introduced into a scope by a
1074/// (resolved) using declaration.
1075///
1076/// Given
1077/// \code
1078/// namespace n { int f; }
1079/// namespace declToImport { using n::f; }
1080/// \endcode
1081/// usingShadowDecl()
1082/// matches \code f \endcode
1083const internal::VariadicDynCastAllOfMatcher<Decl,
1084 UsingShadowDecl> usingShadowDecl;
1085
Gabor Marton19f4f392018-06-25 13:04:37 +00001086TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001087 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001088 testImport(
1089 "namespace foo { int bar; }"
1090 "namespace declToImport { using foo::bar; }",
1091 Lang_CXX, "", Lang_CXX, Verifier,
1092 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001093}
1094
Gabor Marton19f4f392018-06-25 13:04:37 +00001095TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001096 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001097 testImport(
1098 "template<typename T> int foo();"
1099 "template <typename T> void declToImport() {"
1100 " (void)::foo<T>;"
1101 " (void)::template foo<T>;"
1102 "}"
1103 "void instantiate() { declToImport<int>(); }",
1104 Lang_CXX, "", Lang_CXX, Verifier,
1105 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001106}
1107
Gabor Marton19f4f392018-06-25 13:04:37 +00001108TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001109 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001110 testImport(
1111 "template <typename T> struct C { T t; };"
1112 "template <typename T> void declToImport() {"
1113 " C<T> d;"
1114 " d.t = T();"
1115 "}"
1116 "void instantiate() { declToImport<int>(); }",
1117 Lang_CXX, "", Lang_CXX, Verifier,
1118 functionTemplateDecl(hasDescendant(
1119 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1120 testImport(
1121 "template <typename T> struct C { T t; };"
1122 "template <typename T> void declToImport() {"
1123 " C<T> d;"
1124 " (&d)->t = T();"
1125 "}"
1126 "void instantiate() { declToImport<int>(); }",
1127 Lang_CXX, "", Lang_CXX, Verifier,
1128 functionTemplateDecl(hasDescendant(
1129 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001130}
1131
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001132/// Check that function "declToImport()" (which is the templated function
1133/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1134/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001135TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001136 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001137 testImport(
1138 "template <typename T> void declToImport() { T a = 1; }"
1139 "void instantiate() { declToImport<int>(); }",
1140 Lang_CXX, "", Lang_CXX, Verifier,
1141 functionTemplateDecl(hasAncestor(translationUnitDecl(
1142 unless(has(functionDecl(hasName("declToImport"))))))));
1143 testImport(
1144 "template <typename T> struct declToImport { T t; };"
1145 "void instantiate() { declToImport<int>(); }",
1146 Lang_CXX, "", Lang_CXX, Verifier,
1147 classTemplateDecl(hasAncestor(translationUnitDecl(
1148 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001149}
1150
Gabor Marton19f4f392018-06-25 13:04:37 +00001151TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001152 MatchVerifier<Decl> Verifier;
1153 auto Code =
1154 R"s(
1155 struct declToImport {
1156 template <typename T0> struct X;
1157 template <typename T0> struct X<T0 *> {};
1158 };
1159 )s";
1160 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1161 recordDecl(has(classTemplateDecl()),
1162 has(classTemplateSpecializationDecl())));
1163}
1164
Gabor Marton19f4f392018-06-25 13:04:37 +00001165TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001166 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001167 testImport(
1168 "class declToImport {"
1169 " void f() { *this = declToImport(); }"
1170 "};",
1171 Lang_CXX, "", Lang_CXX, Verifier,
1172 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1173 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001174}
1175
Gabor Marton19f4f392018-06-25 13:04:37 +00001176TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001177 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001178 testImport(
1179 "template<typename T, int Size> class declToImport {"
1180 " T data[Size];"
1181 "};",
1182 Lang_CXX, "", Lang_CXX, Verifier,
1183 classTemplateDecl(has(cxxRecordDecl(
1184 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001185}
1186
Gabor Martona0df7a92018-05-30 09:19:26 +00001187TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1188 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1189 auto From =
1190 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1191 ASSERT_TRUE(From);
1192 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1193 ASSERT_TRUE(To);
1194 Decl *ToTemplated = To->getTemplatedDecl();
1195 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1196 EXPECT_TRUE(ToTemplated1);
1197 EXPECT_EQ(ToTemplated1, ToTemplated);
1198}
1199
Gabor Marton26f72a92018-07-12 09:42:05 +00001200TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001201 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1202 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1203 FromTU, functionTemplateDecl());
1204 ASSERT_TRUE(From);
1205 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1206 ASSERT_TRUE(To);
1207 Decl *ToTemplated = To->getTemplatedDecl();
1208 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1209 EXPECT_TRUE(ToTemplated1);
1210 EXPECT_EQ(ToTemplated1, ToTemplated);
1211}
1212
1213TEST_P(ASTImporterTestBase,
1214 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1215 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1216 auto FromFT =
1217 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1218 ASSERT_TRUE(FromFT);
1219
1220 auto ToTemplated =
1221 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1222 EXPECT_TRUE(ToTemplated);
1223 auto ToTU = ToTemplated->getTranslationUnitDecl();
1224 auto ToFT =
1225 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1226 EXPECT_TRUE(ToFT);
1227}
1228
1229TEST_P(ASTImporterTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001230 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001231 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1232 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1233 FromTU, functionTemplateDecl());
1234 ASSERT_TRUE(FromFT);
1235
1236 auto ToTemplated =
1237 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1238 EXPECT_TRUE(ToTemplated);
1239 auto ToTU = ToTemplated->getTranslationUnitDecl();
1240 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1241 ToTU, functionTemplateDecl());
1242 EXPECT_TRUE(ToFT);
1243}
1244
Gabor Martona0df7a92018-05-30 09:19:26 +00001245TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1246 auto Code =
1247 R"(
1248 namespace x {
1249 template<class X> struct S1{};
1250 template<class X> struct S2{};
1251 template<class X> struct S3{};
1252 }
1253 )";
1254 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1255 auto FromNs =
1256 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1257 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1258 ASSERT_TRUE(ToNs);
1259 auto From =
1260 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1261 classTemplateDecl(
1262 hasName("S2")));
1263 auto To =
1264 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1265 classTemplateDecl(
1266 hasName("S2")));
1267 ASSERT_TRUE(From);
1268 ASSERT_TRUE(To);
1269 auto ToTemplated = To->getTemplatedDecl();
1270 auto ToTemplated1 =
1271 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1272 EXPECT_TRUE(ToTemplated1);
1273 ASSERT_EQ(ToTemplated1, ToTemplated);
1274}
1275
Gabor Marton26f72a92018-07-12 09:42:05 +00001276TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001277 Decl *From, *To;
1278 std::tie(From, To) = getImportedDecl(
1279 R"(
1280 template <typename T> struct X {};
1281
1282 void declToImport(int y, X<int> &x) {}
1283
1284 template <> struct X<int> {
1285 void g() {
1286 X<int> x;
1287 declToImport(0, x);
1288 }
1289 };
1290 )",
1291 Lang_CXX, "", Lang_CXX);
1292
1293 MatchVerifier<Decl> Verifier;
1294 auto Matcher = functionDecl(hasName("declToImport"),
1295 parameterCountIs(2),
1296 hasParameter(0, hasName("y")),
1297 hasParameter(1, hasName("x")),
1298 hasParameter(1, hasType(asString("X<int> &"))));
1299 ASSERT_TRUE(Verifier.match(From, Matcher));
1300 EXPECT_TRUE(Verifier.match(To, Matcher));
1301}
1302
1303TEST_P(ASTImporterTestBase,
1304 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1305 Decl *From, *To;
1306 std::tie(From, To) =
1307 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1308 "void instantiate() { declToImport<int>(); }",
1309 Lang_CXX, "", Lang_CXX);
1310
1311 auto Check = [](Decl *D) -> bool {
1312 auto TU = D->getTranslationUnitDecl();
1313 for (auto Child : TU->decls()) {
1314 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1315 if (FD->getNameAsString() == "declToImport") {
1316 GTEST_NONFATAL_FAILURE_(
1317 "TU should not contain any FunctionDecl with name declToImport");
1318 return false;
1319 }
1320 }
1321 }
1322 return true;
1323 };
1324
1325 ASSERT_TRUE(Check(From));
1326 EXPECT_TRUE(Check(To));
1327}
1328
1329TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1330 Decl *From, *To;
1331 std::tie(From, To) =
1332 getImportedDecl("template <typename T> struct declToImport { T t; };"
1333 "void instantiate() { declToImport<int>(); }",
1334 Lang_CXX, "", Lang_CXX);
1335
1336 auto Check = [](Decl *D) -> bool {
1337 auto TU = D->getTranslationUnitDecl();
1338 for (auto Child : TU->decls()) {
1339 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1340 if (RD->getNameAsString() == "declToImport") {
1341 GTEST_NONFATAL_FAILURE_(
1342 "TU should not contain any CXXRecordDecl with name declToImport");
1343 return false;
1344 }
1345 }
1346 }
1347 return true;
1348 };
1349
1350 ASSERT_TRUE(Check(From));
1351 EXPECT_TRUE(Check(To));
1352}
1353
1354TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1355 Decl *From, *To;
1356 std::tie(From, To) =
1357 getImportedDecl(
1358 "template <typename T> struct X {};"
1359 "template <typename T> using declToImport = X<T>;"
1360 "void instantiate() { declToImport<int> a; }",
1361 Lang_CXX11, "", Lang_CXX11);
1362
1363 auto Check = [](Decl *D) -> bool {
1364 auto TU = D->getTranslationUnitDecl();
1365 for (auto Child : TU->decls()) {
1366 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1367 if (AD->getNameAsString() == "declToImport") {
1368 GTEST_NONFATAL_FAILURE_(
1369 "TU should not contain any TypeAliasDecl with name declToImport");
1370 return false;
1371 }
1372 }
1373 }
1374 return true;
1375 };
1376
1377 ASSERT_TRUE(Check(From));
1378 EXPECT_TRUE(Check(To));
1379}
1380
1381TEST_P(
1382 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001383 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001384
1385 Decl *From, *To;
1386 std::tie(From, To) = getImportedDecl(
1387 R"(
1388 template<class T>
1389 class Base {};
1390 class declToImport : public Base<declToImport> {};
1391 )",
1392 Lang_CXX, "", Lang_CXX);
1393
1394 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1395 auto Pattern =
1396 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1397 ASSERT_TRUE(
1398 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1399 EXPECT_TRUE(
1400 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1401
1402 // Check that the ClassTemplateSpecializationDecl is the child of the
1403 // ClassTemplateDecl.
1404 Pattern = translationUnitDecl(has(classTemplateDecl(
1405 hasName("Base"), has(classTemplateSpecializationDecl()))));
1406 ASSERT_TRUE(
1407 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1408 EXPECT_TRUE(
1409 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1410}
1411
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001412AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1413 size_t Index = 0;
1414 for (FieldDecl *Field : Node.fields()) {
1415 if (Index == Order.size())
1416 return false;
1417 if (Field->getName() != Order[Index])
1418 return false;
1419 ++Index;
1420 }
1421 return Index == Order.size();
1422}
1423
Peter Szecsidedda6f2018-03-30 22:03:29 +00001424TEST_P(ASTImporterTestBase,
1425 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1426 Decl *From, *To;
1427 std::tie(From, To) = getImportedDecl(
1428 R"(
1429 namespace NS {
1430 template<class T>
1431 class X {};
1432 template class X<int>;
1433 }
1434 )",
1435 Lang_CXX, "", Lang_CXX, "NS");
1436
1437 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1438 // ClassTemplateDecl.
1439 auto Pattern = namespaceDecl(has(classTemplateDecl(
1440 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1441 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1442 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1443
1444 // Check that the ClassTemplateSpecializationDecl is the child of the
1445 // NamespaceDecl.
1446 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1447 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1448 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1449}
1450
1451TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1452 Decl *From, *To;
1453 std::tie(From, To) =
1454 getImportedDecl(
1455 "struct declToImport { int a; int b; };",
1456 Lang_CXX11, "", Lang_CXX11);
1457
1458 MatchVerifier<Decl> Verifier;
1459 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1460 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1461}
1462
1463TEST_P(ASTImporterTestBase,
1464 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1465 Decl *From, *To;
1466 std::tie(From, To) = getImportedDecl(
1467 // The original recursive algorithm of ASTImporter first imports 'c' then
1468 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1469 R"s(
1470 struct declToImport {
1471 int a = c + b;
1472 int b = 1;
1473 int c = 2;
1474 };
1475 )s",
1476 Lang_CXX11, "", Lang_CXX11);
1477
1478 MatchVerifier<Decl> Verifier;
1479 ASSERT_TRUE(
1480 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1481 EXPECT_TRUE(
1482 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1483}
1484
Gabor Martonde8bf262018-05-17 09:46:07 +00001485TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001486 Decl *From, *To;
1487 std::tie(From, To) = getImportedDecl(
1488 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001489 struct declToImport {
1490 };
1491 )",
1492 Lang_CXX, "", Lang_CXX);
1493
1494 MatchVerifier<Decl> Verifier;
1495 // Match the implicit Decl.
1496 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1497 ASSERT_TRUE(Verifier.match(From, Matcher));
1498 EXPECT_TRUE(Verifier.match(To, Matcher));
1499}
1500
1501TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1502 Decl *From, *To;
1503 std::tie(From, To) = getImportedDecl(
1504 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001505 template <typename U>
1506 struct declToImport {
1507 };
1508 )",
1509 Lang_CXX, "", Lang_CXX);
1510
1511 MatchVerifier<Decl> Verifier;
1512 // Match the implicit Decl.
1513 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1514 ASSERT_TRUE(Verifier.match(From, Matcher));
1515 EXPECT_TRUE(Verifier.match(To, Matcher));
1516}
1517
1518TEST_P(
1519 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001520 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001521 Decl *From, *To;
1522 std::tie(From, To) = getImportedDecl(
1523 R"(
1524 template<class T>
1525 class Base {};
1526 class declToImport : public Base<declToImport> {};
1527 )",
1528 Lang_CXX, "", Lang_CXX);
1529
1530 auto hasImplicitClass = has(cxxRecordDecl());
1531 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1532 hasName("Base"),
1533 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1534 ASSERT_TRUE(
1535 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1536 EXPECT_TRUE(
1537 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1538}
1539
1540TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1541 Decl *From, *To;
1542 std::tie(From, To) =
1543 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1544
1545 MatchVerifier<Decl> Verifier;
1546 auto Matcher = functionDecl();
1547 ASSERT_TRUE(Verifier.match(From, Matcher));
1548 EXPECT_TRUE(Verifier.match(To, Matcher));
1549 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1550}
1551
Gabor Marton2ae9da32018-05-18 15:46:18 +00001552TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001553 Decl *FromTU = getTuDecl(
1554 R"(
1555 struct X {};
1556 void operator<<(int, X);
1557 )",
1558 Lang_CXX);
1559 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1560 const Decl *To = Import(From, Lang_CXX);
1561 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1562}
1563
1564TEST_P(ASTImporterTestBase,
1565 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1566 Decl *From, *To;
1567 std::tie(From, To) = getImportedDecl(
1568 R"(
1569 template<class T>
1570 class Base { int a; };
1571 class declToImport : Base<declToImport> {};
1572 )",
1573 Lang_CXX, "", Lang_CXX);
1574
1575 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1576 hasName("Base"),
1577 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1578 ASSERT_TRUE(
1579 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1580 EXPECT_TRUE(
1581 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1582}
1583
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001584TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1585 {
1586 Decl *FromTU = getTuDecl(
1587 R"(
1588 template <typename T>
1589 struct B;
1590 )",
1591 Lang_CXX, "input0.cc");
1592 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1593 FromTU, classTemplateDecl(hasName("B")));
1594
1595 Import(FromD, Lang_CXX);
1596 }
1597
1598 {
1599 Decl *FromTU = getTuDecl(
1600 R"(
1601 template <typename T>
1602 struct B {
1603 void f();
1604 };
1605 )",
1606 Lang_CXX, "input1.cc");
1607 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1608 FromTU, functionDecl(hasName("f")));
1609 Import(FromD, Lang_CXX);
1610 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1611 FromTU, classTemplateDecl(hasName("B")));
1612 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1613 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1614 }
1615}
1616
Gabor Marton9581c332018-05-23 13:53:36 +00001617TEST_P(ASTImporterTestBase,
1618 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1619 Decl *ToTU = getToTuDecl(
1620 R"(
1621 template <typename T>
1622 struct B {
1623 void f();
1624 };
1625
1626 template <typename T>
1627 struct B;
1628 )",
1629 Lang_CXX);
1630 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1631 [](const ClassTemplateDecl *T) {
1632 return T->isThisDeclarationADefinition();
1633 })
1634 .match(ToTU, classTemplateDecl()));
1635
1636 Decl *FromTU = getTuDecl(
1637 R"(
1638 template <typename T>
1639 struct B {
1640 void f();
1641 };
1642 )",
1643 Lang_CXX, "input1.cc");
1644 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1645 FromTU, classTemplateDecl(hasName("B")));
1646
1647 Import(FromD, Lang_CXX);
1648
1649 // We should have only one definition.
1650 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1651 [](const ClassTemplateDecl *T) {
1652 return T->isThisDeclarationADefinition();
1653 })
1654 .match(ToTU, classTemplateDecl()));
1655}
1656
1657TEST_P(ASTImporterTestBase,
1658 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1659 Decl *ToTU = getToTuDecl(
1660 R"(
1661 struct B {
1662 void f();
1663 };
1664
1665 struct B;
1666 )",
1667 Lang_CXX);
1668 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001669 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001670
1671 Decl *FromTU = getTuDecl(
1672 R"(
1673 struct B {
1674 void f();
1675 };
1676 )",
1677 Lang_CXX, "input1.cc");
1678 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1679 FromTU, cxxRecordDecl(hasName("B")));
1680
1681 Import(FromD, Lang_CXX);
1682
1683 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001684 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001685}
1686
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001687static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1688 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1689 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1690 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1691 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1692}
1693static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1694 SourceManager &SM1, SourceManager &SM2) {
1695 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1696 FullSourceLoc{ Range2.getBegin(), SM2 });
1697 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1698 FullSourceLoc{ Range2.getEnd(), SM2 });
1699}
1700TEST_P(ASTImporterTestBase, ImportSourceLocs) {
1701 Decl *FromTU = getTuDecl(
1702 R"(
1703 #define MFOO(arg) arg = arg + 1
1704
1705 void foo() {
1706 int a = 5;
1707 MFOO(a);
1708 }
1709 )",
1710 Lang_CXX);
1711 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1712 auto ToD = Import(FromD, Lang_CXX);
1713
1714 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1715 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1716 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1717 auto FromRHS =
1718 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1719
1720 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1721 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1722 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1723 FromSM);
1724 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1725 FromSM);
1726 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1727 FromSM);
1728}
1729
Rafael Stahla0010472018-07-09 08:40:17 +00001730TEST_P(ASTImporterTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001731 Decl *FromTU = getTuDecl(
1732 R"(
1733 #define FUNC_INT void declToImport
1734 #define FUNC FUNC_INT
1735 FUNC(int a);
1736 )",
1737 Lang_CXX);
1738 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1739 auto ToD = Import(FromD, Lang_CXX);
1740
1741 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1742 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1743 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1744 FromSM);
1745}
1746
Gabor Marton9581c332018-05-23 13:53:36 +00001747TEST_P(
1748 ASTImporterTestBase,
1749 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1750{
1751 Decl *ToTU = getToTuDecl(
1752 R"(
1753 template <typename T>
1754 struct B;
1755
1756 template <>
1757 struct B<int> {};
1758
1759 template <>
1760 struct B<int>;
1761 )",
1762 Lang_CXX);
1763 // We should have only one definition.
1764 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1765 [](const ClassTemplateSpecializationDecl *T) {
1766 return T->isThisDeclarationADefinition();
1767 })
1768 .match(ToTU, classTemplateSpecializationDecl()));
1769
1770 Decl *FromTU = getTuDecl(
1771 R"(
1772 template <typename T>
1773 struct B;
1774
1775 template <>
1776 struct B<int> {};
1777 )",
1778 Lang_CXX, "input1.cc");
1779 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1780 FromTU, classTemplateSpecializationDecl(hasName("B")));
1781
1782 Import(FromD, Lang_CXX);
1783
1784 // We should have only one definition.
1785 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1786 [](const ClassTemplateSpecializationDecl *T) {
1787 return T->isThisDeclarationADefinition();
1788 })
1789 .match(ToTU, classTemplateSpecializationDecl()));
1790}
1791
Gabor Marton0bebf952018-07-05 09:51:13 +00001792TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
1793 Decl *FromTU = getTuDecl(
1794 R"(
1795 struct { int a; int b; } object0 = { 2, 3 };
1796 struct { int x; int y; int z; } object1;
1797 )",
1798 Lang_CXX, "input0.cc");
1799
Gabor Marton0bebf952018-07-05 09:51:13 +00001800 auto *Obj0 =
1801 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1802 auto *From0 = getRecordDecl(Obj0);
1803 auto *Obj1 =
1804 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1805 auto *From1 = getRecordDecl(Obj1);
1806
1807 auto *To0 = Import(From0, Lang_CXX);
1808 auto *To1 = Import(From1, Lang_CXX);
1809
1810 EXPECT_TRUE(To0);
1811 EXPECT_TRUE(To1);
1812 EXPECT_NE(To0, To1);
1813 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1814}
1815
Gabor Marton26f72a92018-07-12 09:42:05 +00001816TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
1817 auto Pattern = varDecl(hasName("x"));
1818 VarDecl *Imported1;
1819 {
1820 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1821 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1822 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1823 }
1824 VarDecl *Imported2;
1825 {
1826 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1827 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1828 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1829 }
1830 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1831 EXPECT_FALSE(Imported2->isUsed(false));
1832 {
1833 Decl *FromTU =
1834 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
1835 auto *FromD =
1836 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1837 Import(FromD, Lang_CXX);
1838 }
1839 EXPECT_TRUE(Imported2->isUsed(false));
1840}
1841
1842TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
1843 auto Pattern = varDecl(hasName("x"));
1844
1845 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1846 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1847
1848 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1849
1850 ASSERT_FALSE(Imported1->isUsed(false));
1851
1852 FromD->setIsUsed();
1853 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1854
1855 EXPECT_EQ(Imported1, Imported2);
1856 EXPECT_TRUE(Imported2->isUsed(false));
1857}
1858
Peter Szecsidedda6f2018-03-30 22:03:29 +00001859struct ImportFunctions : ASTImporterTestBase {};
1860
1861TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001862 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1863 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1864 auto Pattern = functionDecl(hasName("f"));
1865 FunctionDecl *FromD = // Definition
1866 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1867
1868 Decl *ImportedD = Import(FromD, Lang_CXX);
1869 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1870
Gabor Marton5254e642018-06-27 13:32:50 +00001871 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001872 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1873}
1874
1875TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1876 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1877 auto Pattern = functionDecl(hasName("f"));
1878 FunctionDecl *FromD =
1879 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1880
1881 Decl *ImportedD = Import(FromD, Lang_CXX);
1882 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1883
1884 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1885 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1886}
1887
Gabor Marton5254e642018-06-27 13:32:50 +00001888TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001889 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1890 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001891 auto *From =
1892 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001893
Gabor Marton5254e642018-06-27 13:32:50 +00001894 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001895 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1896
Gabor Marton5254e642018-06-27 13:32:50 +00001897 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1898 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1899 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1900 EXPECT_TRUE(ImportedD == To0);
1901 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1902 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1903 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001904}
1905
1906TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1907 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1908 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001909 auto *From =
1910 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001911
Gabor Marton5254e642018-06-27 13:32:50 +00001912 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001913 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1914
Gabor Marton5254e642018-06-27 13:32:50 +00001915 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1916 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1917 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1918 EXPECT_TRUE(ImportedD == To1);
1919 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1920 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1921 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001922}
1923
1924TEST_P(ImportFunctions, ImportPrototypes) {
1925 auto Pattern = functionDecl(hasName("f"));
1926
1927 Decl *ImportedD;
1928 {
1929 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001930 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001931
1932 ImportedD = Import(FromD, Lang_CXX);
1933 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001934 {
1935 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001936 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1937 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001938 }
1939
Gabor Marton5254e642018-06-27 13:32:50 +00001940 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1941
1942 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1943 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1944 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1945 EXPECT_TRUE(ImportedD == To0);
1946 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1947 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1948 EXPECT_EQ(To1->getPreviousDecl(), To0);
1949}
1950
1951TEST_P(ImportFunctions, ImportDefinitions) {
1952 auto Pattern = functionDecl(hasName("f"));
1953
1954 Decl *ImportedD;
1955 {
1956 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1957 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1958 ImportedD = Import(FromD, Lang_CXX);
1959 }
1960 {
1961 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
1962 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1963 Import(FromD, Lang_CXX);
1964 }
1965
1966 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1967
Peter Szecsidedda6f2018-03-30 22:03:29 +00001968 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00001969 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1970 EXPECT_TRUE(ImportedD == To0);
1971 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001972}
1973
1974TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1975 auto Pattern = functionDecl(hasName("f"));
1976
1977 Decl *ImportedD;
1978 {
1979 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001980 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001981 ImportedD = Import(FromD, Lang_CXX);
1982 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001983 {
1984 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001985 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1986 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001987 }
1988
1989 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001990
1991 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1992 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1993 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1994 EXPECT_TRUE(ImportedD == To0);
1995 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
1996 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1997 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001998}
1999
2000TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
2001 auto Pattern = functionDecl(hasName("f"));
2002
2003 {
2004 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
2005 FunctionDecl *FromD =
2006 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2007
2008 Import(FromD, Lang_CXX);
2009 }
2010 {
2011 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
2012 FunctionDecl *FromD =
2013 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2014 Import(FromD, Lang_CXX);
2015 }
2016
2017 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2018 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2019 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002020 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002021 FunctionDecl *DefinitionD =
2022 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2023 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
2024 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
2025}
2026
Gabor Marton5254e642018-06-27 13:32:50 +00002027TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002028 auto Pattern = functionDecl(hasName("f"));
2029
2030 {
2031 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002032 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002033 Import(FromD, Lang_CXX);
2034 }
2035 {
2036 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002037 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002038 Import(FromD, Lang_CXX);
2039 }
2040
2041 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002042
2043 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002044 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002045 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
2046
Peter Szecsidedda6f2018-03-30 22:03:29 +00002047 FunctionDecl *DefinitionD =
2048 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2049 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00002050
2051 EXPECT_TRUE(DefinitionD->getPreviousDecl());
2052 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
2053 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002054}
2055
2056TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2057 auto Code =
2058 R"(
2059 struct B { virtual void f(); };
2060 void B::f() {}
2061 struct D : B { void f(); };
2062 )";
2063 auto Pattern =
2064 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2065 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2066 CXXMethodDecl *Proto =
2067 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2068
2069 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2070 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2071 EXPECT_EQ(To->size_overridden_methods(), 1u);
2072}
2073
2074TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2075 auto Code =
2076 R"(
2077 struct B { virtual void f(); };
2078 void B::f() {}
2079 )";
2080 auto Pattern =
2081 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2082 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2083 CXXMethodDecl *Proto =
2084 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2085 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2086
2087 ASSERT_TRUE(Proto->isVirtual());
2088 ASSERT_TRUE(Def->isVirtual());
2089 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2090 EXPECT_TRUE(To->isVirtual());
2091}
2092
Gabor Marton5254e642018-06-27 13:32:50 +00002093TEST_P(ImportFunctions,
2094 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2095 Decl *ToTU = getToTuDecl(
2096 R"(
2097 void f() {}
2098 void f();
2099 )",
2100 Lang_CXX);
2101 ASSERT_EQ(1u,
2102 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2103 return FD->doesThisDeclarationHaveABody();
2104 }).match(ToTU, functionDecl()));
2105
2106 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2107 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2108
2109 Import(FromD, Lang_CXX);
2110
2111 EXPECT_EQ(1u,
2112 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2113 return FD->doesThisDeclarationHaveABody();
2114 }).match(ToTU, functionDecl()));
2115}
2116
2117struct ImportFriendFunctions : ImportFunctions {};
2118
2119TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2120 auto Pattern = functionDecl(hasName("f"));
2121
2122 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2123 "void f();",
2124 Lang_CXX,
2125 "input0.cc");
2126 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2127
2128 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2129 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2130 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2131 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2132 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2133 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2134 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2135}
2136
2137TEST_P(ImportFriendFunctions,
2138 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2139 auto Pattern = functionDecl(hasName("f"));
2140
2141 Decl *FromTU = getTuDecl("void f();"
2142 "struct X { friend void f(); };",
2143 Lang_CXX, "input0.cc");
2144 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2145
2146 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2147 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2148 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2149 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2150 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2151 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2152 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2153}
2154
2155TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2156 auto Pattern = functionDecl(hasName("f"));
2157
2158 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2159 "void f();",
2160 Lang_CXX,
2161 "input0.cc");
2162 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2163
2164 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2165 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2166 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2167 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2168 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2169 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2170 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2171}
2172
2173TEST_P(ImportFriendFunctions,
2174 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2175 auto Pattern = functionDecl(hasName("f"));
2176
2177 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2178 "void f(){}",
2179 Lang_CXX, "input0.cc");
2180 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2181
2182 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2183 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2184 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2185 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2186 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2187 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2188 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2189}
2190
Gabor Marton26f72a92018-07-12 09:42:05 +00002191// Disabled temporarily, because the new structural equivalence check
2192// (https://reviews.llvm.org/D48628) breaks it.
2193// PreviousDecl is not set because there is no structural match.
2194// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002195TEST_P(ImportFriendFunctions,
2196 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2197 auto Pattern = functionDecl(hasName("f"));
2198
2199 Decl *FromTU = getTuDecl(
2200 R"(
2201 class X;
2202 void f(X *x){}
2203 class X{
2204 friend void f(X *x);
2205 };
2206 )",
2207 Lang_CXX, "input0.cc");
2208 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2209
2210 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2211 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2212 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2213 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2214 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2215 .match(ToTU, friendDecl())
2216 ->getFriendDecl());
2217 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2218 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2219 // The parameters must refer the same type
2220 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2221 (*ImportedD->param_begin())->getOriginalType());
2222}
2223
Gabor Marton26f72a92018-07-12 09:42:05 +00002224// Disabled temporarily, because the new structural equivalence check
2225// (https://reviews.llvm.org/D48628) breaks it.
2226// PreviousDecl is not set because there is no structural match.
2227// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002228TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002229 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002230 auto Pattern = functionDecl(hasName("f"));
2231
2232 Decl *FromTU = getTuDecl(
2233 R"(
2234 class X;
2235 void f(X *x){}
2236 class X{
2237 friend void f(X *x);
2238 };
2239 )",
2240 Lang_CXX, "input0.cc");
2241 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2242
2243 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2244 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2245 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2246 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2247 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2248 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2249
2250 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2251 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2252 // The parameters must refer the same type
2253 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2254 (*ImportedD->param_begin())->getOriginalType());
2255}
2256
2257TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2258 auto Pattern = functionDecl(hasName("f"));
2259
2260 FunctionDecl *ImportedD;
2261 {
2262 Decl *FromTU =
2263 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2264 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2265 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2266 }
2267 FunctionDecl *ImportedD1;
2268 {
2269 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2270 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2271 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2272 }
2273
2274 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2275 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2276 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2277 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2278 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2279}
2280
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002281AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2282 InnerMatcher) {
2283 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2284 return InnerMatcher.matches(*Typedef, Finder, Builder);
2285 return false;
2286}
2287
Gabor Marton19f4f392018-06-25 13:04:37 +00002288TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002289 CodeFiles Samples{{"main.c",
2290 {"void foo();"
2291 "void moo();"
2292 "int main() { foo(); moo(); }",
2293 Lang_C}},
2294
2295 {"foo.c",
2296 {"typedef enum { THING_VALUE } thing_t;"
2297 "void conflict(thing_t type);"
2298 "void foo() { (void)THING_VALUE; }"
2299 "void conflict(thing_t type) {}",
2300 Lang_C}},
2301
2302 {"moo.c",
2303 {"typedef enum { THING_VALUE } thing_t;"
2304 "void conflict(thing_t type);"
2305 "void moo() { conflict(THING_VALUE); }",
2306 Lang_C}}};
2307
2308 auto VerificationMatcher =
2309 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2310 hasTypedefForAnonDecl(hasName("thing_t")));
2311
2312 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2313 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2314
2315 testImportSequence(
2316 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2317 // Just check that there is only one enum decl in the result AST.
2318 "main.c", enumDecl(), VerificationMatcher);
2319
2320 // For different import order, result should be the same.
2321 testImportSequence(
2322 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2323 // Check that there is only one enum decl in the result AST.
2324 "main.c", enumDecl(), VerificationMatcher);
2325}
2326
Peter Szecsice7f3182018-05-07 12:08:27 +00002327const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2328 dependentScopeDeclRefExpr;
2329
Gabor Marton19f4f392018-06-25 13:04:37 +00002330TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002331 MatchVerifier<Decl> Verifier;
2332 testImport("template <typename T> struct S { static T foo; };"
2333 "template <typename T> void declToImport() {"
2334 " (void) S<T>::foo;"
2335 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002336 "void instantiate() { declToImport<int>(); }"
2337 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002338 Lang_CXX11, "", Lang_CXX11, Verifier,
2339 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2340 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2341
2342 testImport("template <typename T> struct S {"
2343 "template<typename S> static void foo(){};"
2344 "};"
2345 "template <typename T> void declToImport() {"
2346 " S<T>::template foo<T>();"
2347 "}"
2348 "void instantiate() { declToImport<int>(); }",
2349 Lang_CXX11, "", Lang_CXX11, Verifier,
2350 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2351 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2352}
2353
2354const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2355 dependentNameType;
2356
Gabor Marton19f4f392018-06-25 13:04:37 +00002357TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002358 MatchVerifier<Decl> Verifier;
2359 testImport("template <typename T> struct declToImport {"
2360 " typedef typename T::type dependent_name;"
2361 "};",
2362 Lang_CXX11, "", Lang_CXX11, Verifier,
2363 classTemplateDecl(has(
2364 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2365}
2366
2367const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
2368 unresolvedMemberExpr;
2369
Gabor Marton19f4f392018-06-25 13:04:37 +00002370TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002371 MatchVerifier<Decl> Verifier;
2372 testImport("struct S { template <typename T> void mem(); };"
2373 "template <typename U> void declToImport() {"
2374 " S s;"
2375 " s.mem<U>();"
2376 "}"
2377 "void instantiate() { declToImport<int>(); }",
2378 Lang_CXX11, "", Lang_CXX11, Verifier,
2379 functionTemplateDecl(has(functionDecl(has(
2380 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2381}
2382
Balazs Keri1d20cc22018-07-16 12:16:39 +00002383class ImportImplicitMethods : public ASTImporterTestBase {
2384public:
2385 static constexpr auto DefaultCode = R"(
2386 struct A { int x; };
2387 void f() {
2388 A a;
2389 A a1(a);
2390 A a2(A{});
2391 a = a1;
2392 a = A{};
2393 a.~A();
2394 })";
2395
2396 template <typename MatcherType>
2397 void testImportOf(
2398 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2399 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2400 }
2401
2402 template <typename MatcherType>
2403 void testNoImportOf(
2404 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2405 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2406 }
2407
2408private:
2409 template <typename MatcherType>
2410 void test(const MatcherType &MethodMatcher,
2411 const char *Code, unsigned int ExpectedCount) {
2412 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2413
2414 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2415 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2416 ToTU, ClassMatcher);
2417
Balazs Keri2f752ba2018-07-16 14:05:18 +00002418 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002419
2420 {
2421 CXXMethodDecl *Method =
2422 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2423 ToClass->removeDecl(Method);
2424 }
2425
Balazs Keri2f752ba2018-07-16 14:05:18 +00002426 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002427
2428 Decl *ImportedClass = nullptr;
2429 {
2430 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2431 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2432 FromTU, ClassMatcher);
2433 ImportedClass = Import(FromClass, Lang_CXX11);
2434 }
2435
2436 EXPECT_EQ(ToClass, ImportedClass);
2437 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2438 ExpectedCount);
2439 }
2440};
2441
2442TEST_P(ImportImplicitMethods, DefaultConstructor) {
2443 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2444}
2445
2446TEST_P(ImportImplicitMethods, CopyConstructor) {
2447 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2448}
2449
2450TEST_P(ImportImplicitMethods, MoveConstructor) {
2451 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2452}
2453
2454TEST_P(ImportImplicitMethods, Destructor) {
2455 testImportOf(cxxDestructorDecl());
2456}
2457
2458TEST_P(ImportImplicitMethods, CopyAssignment) {
2459 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2460}
2461
2462TEST_P(ImportImplicitMethods, MoveAssignment) {
2463 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2464}
2465
2466TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2467 auto Code = R"(
2468 struct A { A() { int x; } };
2469 )";
2470 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2471}
2472
2473TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2474 auto Code = R"(
2475 struct A { A() = default; };
2476 )";
2477 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2478}
2479
2480TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2481 auto Code = R"(
2482 struct A { A() = delete; };
2483 )";
2484 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2485}
2486
2487TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2488 auto Code = R"(
2489 struct A { void f() { } };
2490 )";
2491 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2492}
2493
Balazs Keric7797c42018-07-11 09:37:24 +00002494TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
2495 Decl *ToR1;
2496 {
2497 Decl *FromTU = getTuDecl(
2498 "struct A { };", Lang_CXX, "input0.cc");
2499 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2500 FromTU, cxxRecordDecl(hasName("A")));
2501
2502 ToR1 = Import(FromR, Lang_CXX);
2503 }
2504
2505 Decl *ToR2;
2506 {
2507 Decl *FromTU = getTuDecl(
2508 "struct A { };", Lang_CXX, "input1.cc");
2509 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2510 FromTU, cxxRecordDecl(hasName("A")));
2511
2512 ToR2 = Import(FromR, Lang_CXX);
2513 }
2514
2515 EXPECT_EQ(ToR1, ToR2);
2516}
2517
2518TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
2519 Decl *ToR1;
2520 {
2521 Decl *FromTU = getTuDecl(
2522 "struct A { int x; };", Lang_CXX, "input0.cc");
2523 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2524 FromTU, cxxRecordDecl(hasName("A")));
2525 ToR1 = Import(FromR, Lang_CXX);
2526 }
2527 Decl *ToR2;
2528 {
2529 Decl *FromTU = getTuDecl(
2530 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2531 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2532 FromTU, cxxRecordDecl(hasName("A")));
2533 ToR2 = Import(FromR, Lang_CXX);
2534 }
2535 EXPECT_NE(ToR1, ToR2);
2536}
2537
2538TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
2539 Decl *ToF1;
2540 {
2541 Decl *FromTU = getTuDecl(
2542 "struct A { int x; };", Lang_CXX, "input0.cc");
2543 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2544 FromTU, fieldDecl(hasName("x")));
2545 ToF1 = Import(FromF, Lang_CXX);
2546 }
2547 Decl *ToF2;
2548 {
2549 Decl *FromTU = getTuDecl(
2550 "struct A { int x; };", Lang_CXX, "input1.cc");
2551 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2552 FromTU, fieldDecl(hasName("x")));
2553 ToF2 = Import(FromF, Lang_CXX);
2554 }
2555 EXPECT_EQ(ToF1, ToF2);
2556}
2557
2558TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
2559 Decl *ToF1;
2560 {
2561 Decl *FromTU = getTuDecl(
2562 "struct A { int x; };", Lang_CXX, "input0.cc");
2563 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2564 FromTU, fieldDecl(hasName("x")));
2565 ToF1 = Import(FromF, Lang_CXX);
2566 }
2567 Decl *ToF2;
2568 {
2569 Decl *FromTU = getTuDecl(
2570 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2571 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2572 FromTU, fieldDecl(hasName("x")));
2573 ToF2 = Import(FromF, Lang_CXX);
2574 }
2575 EXPECT_NE(ToF1, ToF2);
2576}
2577
2578TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
2579 Decl *ToM1;
2580 {
2581 Decl *FromTU = getTuDecl(
2582 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2583 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2584 FromTU, functionDecl(hasName("x"), isDefinition()));
2585 ToM1 = Import(FromM, Lang_CXX);
2586 }
2587 Decl *ToM2;
2588 {
2589 Decl *FromTU = getTuDecl(
2590 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2591 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2592 FromTU, functionDecl(hasName("x"), isDefinition()));
2593 ToM2 = Import(FromM, Lang_CXX);
2594 }
2595 EXPECT_EQ(ToM1, ToM2);
2596}
2597
2598TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
2599 Decl *ToM1;
2600 {
2601 Decl *FromTU = getTuDecl(
2602 "struct A { void x(); }; void A::x() { }",
2603 Lang_CXX, "input0.cc");
2604 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2605 FromTU, functionDecl(hasName("x"), isDefinition()));
2606 ToM1 = Import(FromM, Lang_CXX);
2607 }
2608 Decl *ToM2;
2609 {
2610 Decl *FromTU = getTuDecl(
2611 "struct A { void x() const; }; void A::x() const { }",
2612 Lang_CXX, "input1.cc");
2613 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2614 FromTU, functionDecl(hasName("x"), isDefinition()));
2615 ToM2 = Import(FromM, Lang_CXX);
2616 }
2617 EXPECT_NE(ToM1, ToM2);
2618}
2619
Gabor Martonf086fa82018-07-17 12:06:36 +00002620TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
2621 Decl *FromTU = getTuDecl(
2622 R"(
2623 struct A {
2624 struct {
2625 struct A *next;
2626 } entry0;
2627 struct {
2628 struct A *next;
2629 } entry1;
2630 };
2631 )",
2632 Lang_C, "input0.cc");
2633 auto *From =
2634 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
2635
2636 Import(From, Lang_C);
2637
2638 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2639 auto *Entry0 =
2640 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
2641 auto *Entry1 =
2642 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
2643 auto *R0 = getRecordDecl(Entry0);
2644 auto *R1 = getRecordDecl(Entry1);
2645 EXPECT_NE(R0, R1);
2646 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2647 R0, recordDecl(has(fieldDecl(hasName("next"))))));
2648 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2649 R1, recordDecl(has(fieldDecl(hasName("next"))))));
2650}
2651
Balazs Keri2544b4b2018-08-08 09:40:57 +00002652TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
2653 Decl *FromTU = getTuDecl(
2654 R"(
2655 void f(int X, int Y, bool Z) {
2656 (void)[X, Y, Z] { (void)Z; };
2657 }
2658 )",
2659 Lang_CXX11, "input0.cc");
2660 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
2661 FromTU, functionDecl(hasName("f")));
2662 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
2663 EXPECT_TRUE(ToF);
2664
2665 CXXRecordDecl *FromLambda =
2666 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
2667 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
2668
2669 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
2670 EXPECT_TRUE(ToLambda);
2671
2672 // Check if the fields of the lambda class are imported in correct order.
2673 unsigned FromIndex = 0u;
2674 for (auto *FromField : FromLambda->fields()) {
2675 ASSERT_FALSE(FromField->getDeclName());
2676 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
2677 EXPECT_TRUE(ToField);
2678 unsigned ToIndex = ASTImporter::getFieldIndex(ToField);
2679 EXPECT_EQ(ToIndex, FromIndex + 1);
2680 ++FromIndex;
2681 }
2682
2683 EXPECT_EQ(FromIndex, 3u);
2684}
2685
Gabor Marton61d862a2018-05-18 09:08:47 +00002686struct DeclContextTest : ASTImporterTestBase {};
2687
2688TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
2689 Decl *TU = getTuDecl(
2690 R"(
2691 namespace NS {
2692
2693 template <typename T>
2694 struct S {};
2695 template struct S<int>;
2696
2697 inline namespace INS {
2698 template <typename T>
2699 struct S {};
2700 template struct S<int>;
2701 }
2702
2703 }
2704 )", Lang_CXX11, "input0.cc");
2705 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
2706 TU, namespaceDecl());
2707 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2708 TU, classTemplateSpecializationDecl());
2709 ASSERT_TRUE(NS->containsDecl(Spec));
2710
2711 NS->removeDecl(Spec);
2712 EXPECT_FALSE(NS->containsDecl(Spec));
2713}
2714
Gabor Marton5254e642018-06-27 13:32:50 +00002715struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
2716
2717TEST_P(ImportFunctionTemplateSpecializations,
2718 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
2719
2720 Decl *FromTU = getTuDecl(
2721 R"(
2722 template<class T>
2723 int f() { return 0; }
2724 void foo() { f<int>(); }
2725 )",
2726 Lang_CXX, "input0.cc");
2727
2728 // Check that the function template instantiation is NOT the child of the TU.
2729 auto Pattern = translationUnitDecl(
2730 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
2731 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2732
2733 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
2734 FromTU, functionDecl(hasName("foo")));
2735 ASSERT_TRUE(Import(Foo, Lang_CXX));
2736
2737 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2738 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2739}
2740
2741TEST_P(ImportFunctionTemplateSpecializations,
2742 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
2743
2744 Decl *FromTU = getTuDecl(
2745 R"(
2746 template<class T>
2747 int f() { return 0; }
2748 template int f<int>();
2749 )",
2750 Lang_CXX, "input0.cc");
2751
2752 // Check that the function template instantiation is NOT the child of the TU.
2753 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
2754 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
2755 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2756
2757 ASSERT_TRUE(
2758 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
2759
2760 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2761 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2762}
2763
2764TEST_P(ImportFunctionTemplateSpecializations,
2765 TUshouldContainFunctionTemplateSpecialization) {
2766
2767 Decl *FromTU = getTuDecl(
2768 R"(
2769 template<class T>
2770 int f() { return 0; }
2771 template <> int f<int>() { return 4; }
2772 )",
2773 Lang_CXX, "input0.cc");
2774
2775 // Check that the function template specialization is the child of the TU.
2776 auto Specialization =
2777 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2778 auto Pattern = translationUnitDecl(has(Specialization));
2779 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2780
2781 ASSERT_TRUE(
2782 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
2783
2784 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2785 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2786}
2787
2788TEST_P(ImportFunctionTemplateSpecializations,
2789 FunctionTemplateSpecializationRedeclChain) {
2790
2791 Decl *FromTU = getTuDecl(
2792 R"(
2793 template<class T>
2794 int f() { return 0; }
2795 template <> int f<int>() { return 4; }
2796 )",
2797 Lang_CXX, "input0.cc");
2798
2799 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
2800 hasParent(translationUnitDecl()));
2801 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
2802 {
2803 auto *TU = FromTU;
2804 auto *SpecD = FromSpecD;
2805 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2806 TU, functionTemplateDecl());
2807 auto *FirstSpecD = *(TemplateD->spec_begin());
2808 ASSERT_EQ(SpecD, FirstSpecD);
2809 ASSERT_TRUE(SpecD->getPreviousDecl());
2810 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2811 ->doesThisDeclarationHaveABody());
2812 }
2813
2814 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
2815
2816 {
2817 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
2818 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
2819 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2820 TU, functionTemplateDecl());
2821 auto *FirstSpecD = *(TemplateD->spec_begin());
2822 EXPECT_EQ(SpecD, FirstSpecD);
2823 ASSERT_TRUE(SpecD->getPreviousDecl());
2824 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2825 ->doesThisDeclarationHaveABody());
2826 }
2827}
2828
2829TEST_P(ImportFunctionTemplateSpecializations,
2830 MatchNumberOfFunctionTemplateSpecializations) {
2831
2832 Decl *FromTU = getTuDecl(
2833 R"(
2834 template <typename T> constexpr int f() { return 0; }
2835 template <> constexpr int f<int>() { return 4; }
2836 void foo() {
2837 static_assert(f<char>() == 0, "");
2838 static_assert(f<int>() == 4, "");
2839 }
2840 )",
2841 Lang_CXX11, "input0.cc");
2842 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2843 FromTU, functionDecl(hasName("foo")));
2844
2845 Import(FromD, Lang_CXX11);
2846 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2847 EXPECT_EQ(
2848 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
2849 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
2850}
2851
2852TEST_P(ImportFunctionTemplateSpecializations,
2853 ImportPrototypes) {
2854 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2855 auto Code =
2856 R"(
2857 // Proto of the primary template.
2858 template <class T>
2859 void f();
2860 // Proto of the specialization.
2861 template <>
2862 void f<int>();
2863 )";
2864
2865 Decl *ImportedD;
2866 {
2867 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2868 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2869
2870 ImportedD = Import(FromD, Lang_CXX);
2871 }
2872 {
2873 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2874 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2875 Import(FromD, Lang_CXX);
2876 }
2877
2878 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2879
2880 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2881 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2882 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2883 EXPECT_TRUE(ImportedD == To0);
2884 EXPECT_TRUE(ImportedD != To1);
2885 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2886 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2887 // Check that they are part of the same redecl chain.
2888 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
2889}
2890
2891TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
2892 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2893 auto Code =
2894 R"(
2895 // Proto of the primary template.
2896 template <class T>
2897 void f();
2898 // Specialization and definition.
2899 template <>
2900 void f<int>() {}
2901 )";
2902
2903 Decl *ImportedD;
2904 {
2905 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2906 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2907 ImportedD = Import(FromD, Lang_CXX);
2908 }
2909 {
2910 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2911 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2912 Import(FromD, Lang_CXX);
2913 }
2914
2915 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2916
2917 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2918 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2919 EXPECT_TRUE(ImportedD == To0);
2920 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2921
2922 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2923 ToTU, functionTemplateDecl());
2924 auto *FirstSpecD = *(TemplateD->spec_begin());
2925 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
2926}
2927
2928TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
2929 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2930 auto Code =
2931 R"(
2932 // Proto of the primary template.
2933 template <class T>
2934 void f();
2935 // Specialization proto.
2936 template <>
2937 void f<int>();
2938 // Specialization proto.
2939 template <>
2940 void f<int>();
2941 )";
2942
2943 Decl *ImportedD;
2944 {
2945 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2946 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2947 ImportedD = Import(FromD, Lang_CXX);
2948 }
2949
2950 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2951
2952 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2953 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2954 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2955 EXPECT_TRUE(ImportedD == To0);
2956 EXPECT_TRUE(ImportedD != To1);
2957 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2958 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2959 EXPECT_EQ(To1->getPreviousDecl(), To0);
2960}
2961
2962TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
2963 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2964 auto Code =
2965 R"(
2966 // Proto of the primary template.
2967 template <class T>
2968 void f();
2969 // Specialization proto.
2970 template <>
2971 void f<int>();
2972 // Specialization definition.
2973 template <>
2974 void f<int>() {}
2975 )";
2976
2977 Decl *ImportedD;
2978 {
2979 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2980 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2981 ImportedD = Import(FromD, Lang_CXX);
2982 }
2983
2984 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2985
2986 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2987 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2988 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2989 EXPECT_TRUE(ImportedD == To0);
2990 EXPECT_TRUE(ImportedD != To1);
2991 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2992 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2993 EXPECT_EQ(To1->getPreviousDecl(), To0);
2994}
2995
2996TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
2997 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2998 auto Code =
2999 R"(
3000 // Proto of the primary template.
3001 template <class T>
3002 void f();
3003 // Specialization definition.
3004 template <>
3005 void f<int>() {}
3006 // Specialization proto.
3007 template <>
3008 void f<int>();
3009 )";
3010
3011 Decl *ImportedD;
3012 {
3013 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3014 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3015 ImportedD = Import(FromD, Lang_CXX);
3016 }
3017
3018 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3019
3020 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3021 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3022 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3023 EXPECT_TRUE(ImportedD == To0);
3024 EXPECT_TRUE(ImportedD != To1);
3025 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
3026 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3027 EXPECT_EQ(To1->getPreviousDecl(), To0);
3028}
3029
Gabor Marton19f4f392018-06-25 13:04:37 +00003030INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
3031 ::testing::Values(ArgVector()), );
3032
Gabor Marton5254e642018-06-27 13:32:50 +00003033INSTANTIATE_TEST_CASE_P(
3034 ParameterizedTests, CanonicalRedeclChain,
3035 ::testing::Values(ArgVector()),);
3036
Gabor Marton19f4f392018-06-25 13:04:37 +00003037auto DefaultTestValuesForRunOptions = ::testing::Values(
3038 ArgVector(),
3039 ArgVector{"-fdelayed-template-parsing"},
3040 ArgVector{"-fms-compatibility"},
3041 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
3042
3043INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
3044 DefaultTestValuesForRunOptions, );
3045
3046INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
3047 DefaultTestValuesForRunOptions, );
3048
3049INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
3050 DefaultTestValuesForRunOptions, );
3051
3052INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
3053 DefaultTestValuesForRunOptions, );
3054
3055INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
3056 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00003057
Gabor Marton5254e642018-06-27 13:32:50 +00003058INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
3059 DefaultTestValuesForRunOptions, );
3060
3061INSTANTIATE_TEST_CASE_P(ParameterizedTests,
3062 ImportFunctionTemplateSpecializations,
3063 DefaultTestValuesForRunOptions, );
3064
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00003065} // end namespace ast_matchers
3066} // end namespace clang