blob: c59c2cd1253ce86a93ce54ee5a249bd0eb4dfb58 [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
Peter Szecsidedda6f2018-03-30 22:03:29 +0000276// This class provides generic methods to write tests which can check internal
Balazs Keri21f938c2018-07-02 14:14:07 +0000277// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000278// this fixture makes it possible to import from several "From" contexts.
Gabor Marton19f4f392018-06-25 13:04:37 +0000279class ASTImporterTestBase : public ParameterizedTestsFixture {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000280
281 const char *const InputFileName = "input.cc";
282 const char *const OutputFileName = "output.cc";
283
284 // Buffer for the To context, must live in the test scope.
285 std::string ToCode;
286
Gabor Marton26f72a92018-07-12 09:42:05 +0000287 // Represents a "From" translation unit and holds an importer object which we
288 // use to import from this translation unit.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000289 struct TU {
290 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000291 std::string Code;
292 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000293 std::unique_ptr<ASTUnit> Unit;
294 TranslationUnitDecl *TUDecl = nullptr;
Gabor Marton26f72a92018-07-12 09:42:05 +0000295 std::unique_ptr<ASTImporter> Importer;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000296 TU(StringRef Code, StringRef FileName, ArgVector Args)
297 : Code(Code), FileName(FileName),
298 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
299 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000300 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
301 Unit->enableSourceFileDiagnostics();
302 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000303
Gabor Marton6e1510c2018-07-12 11:50:21 +0000304 void lazyInitImporter(ASTUnit *ToAST) {
Gabor Marton26f72a92018-07-12 09:42:05 +0000305 assert(ToAST);
306 if (!Importer) {
307 Importer.reset(new ASTImporter(
308 ToAST->getASTContext(), ToAST->getFileManager(),
309 Unit->getASTContext(), Unit->getFileManager(), false));
310 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000311 assert(&ToAST->getASTContext() == &Importer->getToContext());
312 createVirtualFileIfNeeded(ToAST, FileName, Code);
313 }
314
315 Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
316 lazyInitImporter(ToAST);
Gabor Marton26f72a92018-07-12 09:42:05 +0000317 return Importer->Import(FromDecl);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000318 }
319
320 QualType import(ASTUnit *ToAST, QualType FromType) {
321 lazyInitImporter(ToAST);
322 return Importer->Import(FromType);
Gabor Marton26f72a92018-07-12 09:42:05 +0000323 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000324 };
325
326 // We may have several From contexts and related translation units. In each
327 // AST, the buffers for the source are handled via references and are set
328 // during the creation of the AST. These references must point to a valid
329 // buffer until the AST is alive. Thus, we must use a list in order to avoid
330 // moving of the stored objects because that would mean breaking the
331 // references in the AST. By using a vector a move could happen when the
332 // vector is expanding, with the list we won't have these issues.
333 std::list<TU> FromTUs;
334
Gabor Marton6e1510c2018-07-12 11:50:21 +0000335 void lazyInitToAST(Language ToLang) {
336 if (ToAST)
337 return;
338 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
339 // Build the AST from an empty file.
340 ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
341 ToAST->enableSourceFileDiagnostics();
342 }
343
344 TU *findFromTU(Decl *From) {
345 // Create a virtual file in the To Ctx which corresponds to the file from
346 // which we want to import the `From` Decl. Without this source locations
347 // will be invalid in the ToCtx.
348 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
349 return E.TUDecl == From->getTranslationUnitDecl();
350 });
351 assert(It != FromTUs.end());
352 return &*It;
353 }
354
Peter Szecsidedda6f2018-03-30 22:03:29 +0000355public:
356 // We may have several From context but only one To context.
357 std::unique_ptr<ASTUnit> ToAST;
358
Peter Szecsidedda6f2018-03-30 22:03:29 +0000359 // Creates an AST both for the From and To source code and imports the Decl
360 // of the identifier into the To context.
361 // Must not be called more than once within the same test.
362 std::tuple<Decl *, Decl *>
363 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
364 Language ToLang, StringRef Identifier = DeclToImportID) {
365 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
366 ToArgs = getArgVectorForLanguage(ToLang);
367
368 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
369 TU &FromTU = FromTUs.back();
370
371 ToCode = ToSrcCode;
372 assert(!ToAST);
373 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000374 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000375
Gabor Marton26f72a92018-07-12 09:42:05 +0000376 ASTContext &FromCtx = FromTU.Unit->getASTContext();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000377
378 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
379
Peter Szecsidedda6f2018-03-30 22:03:29 +0000380 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
381 assert(ImportedII && "Declaration with the given identifier "
382 "should be specified in test!");
383 DeclarationName ImportDeclName(ImportedII);
384 SmallVector<NamedDecl *, 4> FoundDecls;
385 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
386 FoundDecls);
387
388 assert(FoundDecls.size() == 1);
389
Gabor Marton26f72a92018-07-12 09:42:05 +0000390 Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
391
Peter Szecsidedda6f2018-03-30 22:03:29 +0000392 assert(Imported);
393 return std::make_tuple(*FoundDecls.begin(), Imported);
394 }
395
Gabor Marton9581c332018-05-23 13:53:36 +0000396 // Creates a TU decl for the given source code which can be used as a From
397 // context. May be called several times in a given test (with different file
398 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000399 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
400 StringRef FileName = "input.cc") {
401 assert(
402 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
403 return E.FileName == FileName;
404 }) == FromTUs.end());
405
406 ArgVector Args = getArgVectorForLanguage(Lang);
407 FromTUs.emplace_back(SrcCode, FileName, Args);
408 TU &Tu = FromTUs.back();
409
410 return Tu.TUDecl;
411 }
412
Gabor Marton9581c332018-05-23 13:53:36 +0000413 // Creates the To context with the given source code and returns the TU decl.
414 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
415 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
416 ToCode = ToSrcCode;
417 assert(!ToAST);
418 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000419 ToAST->enableSourceFileDiagnostics();
Gabor Marton9581c332018-05-23 13:53:36 +0000420
421 return ToAST->getASTContext().getTranslationUnitDecl();
422 }
423
Peter Szecsidedda6f2018-03-30 22:03:29 +0000424 // Import the given Decl into the ToCtx.
425 // May be called several times in a given test.
426 // The different instances of the param From may have different ASTContext.
427 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000428 lazyInitToAST(ToLang);
429 TU *FromTU = findFromTU(From);
430 return FromTU->import(ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000431 }
432
Gabor Marton6e1510c2018-07-12 11:50:21 +0000433 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
434 lazyInitToAST(ToLang);
435 TU *FromTU = findFromTU(TUDecl);
436 return FromTU->import(ToAST.get(), FromType);
437 }
438
Peter Szecsidedda6f2018-03-30 22:03:29 +0000439 ~ASTImporterTestBase() {
440 if (!::testing::Test::HasFailure()) return;
441
442 for (auto &Tu : FromTUs) {
443 assert(Tu.Unit);
444 llvm::errs() << "FromAST:\n";
445 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
446 llvm::errs() << "\n";
447 }
448 if (ToAST) {
449 llvm::errs() << "ToAST:\n";
450 ToAST->getASTContext().getTranslationUnitDecl()->dump();
451 }
452 }
453};
454
Gabor Marton19f4f392018-06-25 13:04:37 +0000455struct ImportExpr : TestImportBase {};
456struct ImportType : TestImportBase {};
457struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000458
Gabor Marton5254e642018-06-27 13:32:50 +0000459struct CanonicalRedeclChain : ASTImporterTestBase {};
460
461TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
462 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
463 auto Pattern = functionDecl(hasName("f"));
464 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
465
466 auto Redecls = getCanonicalForwardRedeclChain(D0);
467 ASSERT_EQ(Redecls.size(), 1u);
468 EXPECT_EQ(D0, Redecls[0]);
469}
470
471TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
472 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
473 auto Pattern = functionDecl(hasName("f"));
474 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
475 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
476 FunctionDecl *D1 = D2->getPreviousDecl();
477
478 auto Redecls = getCanonicalForwardRedeclChain(D0);
479 ASSERT_EQ(Redecls.size(), 3u);
480 EXPECT_EQ(D0, Redecls[0]);
481 EXPECT_EQ(D1, Redecls[1]);
482 EXPECT_EQ(D2, Redecls[2]);
483}
484
485TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
486 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
487 auto Pattern = functionDecl(hasName("f"));
488 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
489 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
490 FunctionDecl *D1 = D2->getPreviousDecl();
491
492 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
493 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
494 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
495
496 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
497 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
498}
499
500
Gabor Marton19f4f392018-06-25 13:04:37 +0000501TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000502 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000503 testImport(
504 "void declToImport() { (void)\"foo\"; }",
505 Lang_CXX, "", Lang_CXX, Verifier,
506 functionDecl(hasDescendant(
507 stringLiteral(hasType(asString("const char [4]"))))));
508 testImport(
509 "void declToImport() { (void)L\"foo\"; }",
510 Lang_CXX, "", Lang_CXX, Verifier,
511 functionDecl(hasDescendant(
512 stringLiteral(hasType(asString("const wchar_t [4]"))))));
513 testImport(
514 "void declToImport() { (void) \"foo\" \"bar\"; }",
515 Lang_CXX, "", Lang_CXX, Verifier,
516 functionDecl(hasDescendant(
517 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000518}
519
Gabor Marton19f4f392018-06-25 13:04:37 +0000520TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000521 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000522 testImport(
523 "void declToImport() { (void)__null; }",
524 Lang_CXX, "", Lang_CXX, Verifier,
525 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000526}
527
Gabor Marton19f4f392018-06-25 13:04:37 +0000528TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000529 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000530 testImport(
531 "void declToImport() { (void)nullptr; }",
532 Lang_CXX11, "", Lang_CXX11, Verifier,
533 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000534}
535
536
Gabor Marton19f4f392018-06-25 13:04:37 +0000537TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000538 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000539 testImport(
540 "void declToImport() { (void)1.0; }",
541 Lang_C, "", Lang_C, Verifier,
542 functionDecl(hasDescendant(
543 floatLiteral(equals(1.0), hasType(asString("double"))))));
544 testImport(
545 "void declToImport() { (void)1.0e-5f; }",
546 Lang_C, "", Lang_C, Verifier,
547 functionDecl(hasDescendant(
548 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000549}
550
Gabor Marton19f4f392018-06-25 13:04:37 +0000551TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000552 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000553 testImport(
554 "void declToImport() {"
555 " struct s { int x; long y; unsigned z; }; "
556 " (void)(struct s){ 42, 0L, 1U }; }",
557 Lang_CXX, "", Lang_CXX, Verifier,
558 functionDecl(hasDescendant(
559 compoundLiteralExpr(
560 hasType(asString("struct s")),
561 has(initListExpr(
562 hasType(asString("struct s")),
563 has(integerLiteral(
564 equals(42), hasType(asString("int")))),
565 has(integerLiteral(
566 equals(0), hasType(asString("long")))),
567 has(integerLiteral(
568 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000569}
570
Gabor Marton19f4f392018-06-25 13:04:37 +0000571TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000572 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000573 testImport(
574 "class declToImport { void f() { (void)this; } };",
575 Lang_CXX, "", Lang_CXX, Verifier,
576 cxxRecordDecl(
577 hasMethod(
578 hasDescendant(
579 cxxThisExpr(
580 hasType(
581 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000582}
583
Gabor Marton19f4f392018-06-25 13:04:37 +0000584TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000585 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000586 testImport(
587 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
588 Lang_C, "", Lang_C, Verifier,
589 functionDecl(hasDescendant(
590 atomicExpr(
591 has(ignoringParenImpCasts(
592 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
593 hasType(asString("int *"))))),
594 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000595}
596
Gabor Marton19f4f392018-06-25 13:04:37 +0000597TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000598 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000599 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000600 "void declToImport() { loop: goto loop; (void)&&loop; }",
601 Lang_C, "", Lang_C, Verifier,
602 functionDecl(
603 hasDescendant(
604 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
605 hasDescendant(
606 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000607}
608
609AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
610 internal::Matcher<NamedDecl>, InnerMatcher) {
611 const NamedDecl *Template = Node.getTemplatedDecl();
612 return Template && InnerMatcher.matches(*Template, Finder, Builder);
613}
614
Gabor Marton19f4f392018-06-25 13:04:37 +0000615TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000616 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000617 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000618 "template<typename T> class dummy { void f() { dummy X(*this); } };"
619 "typedef dummy<int> declToImport;"
620 "template class dummy<int>;",
621 Lang_CXX, "", Lang_CXX, Verifier,
622 typedefDecl(hasType(templateSpecializationType(
623 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
624 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
625 hasName("f"),
626 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
627 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
628 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000629 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000630}
631
Gabor Marton19f4f392018-06-25 13:04:37 +0000632TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000633 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000634 testImport(
635 "void declToImport() { int b; switch (b) { case 1: break; } }",
636 Lang_C, "", Lang_C, Verifier,
637 functionDecl(hasDescendant(
638 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000639}
640
Gabor Marton19f4f392018-06-25 13:04:37 +0000641TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000642 MatchVerifier<Decl> Verifier;
643 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000644 testImport(
645 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
646 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000647 functionDecl(hasDescendant(
648 varDecl(
649 hasName("C"),
650 hasType(asString("int")),
651 hasInitializer(
652 stmtExpr(
653 hasAnySubstatement(declStmt(hasSingleDecl(
654 varDecl(
655 hasName("X"),
656 hasType(asString("int")),
657 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000658 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000659 hasDescendant(
660 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000661}
662
Gabor Marton19f4f392018-06-25 13:04:37 +0000663TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000664 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000665 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000666 "void declToImport() { (void)(true ? 1 : -5); }",
667 Lang_CXX, "", Lang_CXX, Verifier,
668 functionDecl(hasDescendant(
669 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000670 hasCondition(cxxBoolLiteral(equals(true))),
671 hasTrueExpression(integerLiteral(equals(1))),
672 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000673 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
674 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000675}
676
Gabor Marton19f4f392018-06-25 13:04:37 +0000677TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000678 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000679 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000680 "void declToImport() { (void)(1 ?: -5); }",
681 Lang_CXX, "", Lang_CXX, Verifier,
682 functionDecl(hasDescendant(
683 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000684 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000685 implicitCastExpr(
686 hasSourceExpression(opaqueValueExpr(
687 hasSourceExpression(integerLiteral(equals(1))))),
688 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000689 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000690 opaqueValueExpr(
691 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000692 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000693 unaryOperator(
694 hasOperatorName("-"),
695 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000696}
697
Gabor Marton19f4f392018-06-25 13:04:37 +0000698TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000699 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000700 testImport(
701 "void declToImport() {"
702 " struct point { double x; double y; };"
703 " struct point ptarray[10] = "
704 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
705 Lang_C, "", Lang_C, Verifier,
706 functionDecl(hasDescendant(
707 initListExpr(
708 has(designatedInitExpr(
709 designatorCountIs(2),
710 has(floatLiteral(equals(1.0))),
711 has(integerLiteral(equals(2))))),
712 has(designatedInitExpr(
713 designatorCountIs(2),
714 has(floatLiteral(equals(2.0))),
715 has(integerLiteral(equals(2))))),
716 has(designatedInitExpr(
717 designatorCountIs(2),
718 has(floatLiteral(equals(1.0))),
719 has(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000720}
721
722
Gabor Marton19f4f392018-06-25 13:04:37 +0000723TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000724 MatchVerifier<Decl> Verifier;
725 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000726 testImport(
727 "void declToImport() { (void)__func__; }",
728 Lang_CXX, "", Lang_CXX, Verifier,
729 functionDecl(hasDescendant(
730 predefinedExpr(
731 hasType(
732 asString("const char [13]")),
733 has(stringLiteral(hasType(
734 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000735}
736
Gabor Marton19f4f392018-06-25 13:04:37 +0000737TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000738 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000739 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000740 "void declToImport() {"
741 " struct point { double x; double y; };"
742 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
743 " [0].x = 1.0 }; }",
744 Lang_CXX, "", Lang_CXX, Verifier,
745 functionDecl(hasDescendant(
746 initListExpr(
747 has(
748 cxxConstructExpr(
749 requiresZeroInitialization())),
750 has(
751 initListExpr(
752 hasType(asString("struct point")),
753 has(floatLiteral(equals(1.0))),
754 has(implicitValueInitExpr(
755 hasType(asString("double")))))),
756 has(
757 initListExpr(
758 hasType(asString("struct point")),
759 has(floatLiteral(equals(2.0))),
760 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000761}
762
763
Aleksei Sidorina693b372016-09-28 10:16:56 +0000764const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
765
Gabor Marton19f4f392018-06-25 13:04:37 +0000766TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000767 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000768 testImport(
769 "void declToImport(__builtin_va_list list, ...) {"
770 " (void)__builtin_va_arg(list, int); }",
771 Lang_CXX, "", Lang_CXX, Verifier,
772 functionDecl(hasDescendant(
773 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000774}
775
Gabor Marton19f4f392018-06-25 13:04:37 +0000776TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000777 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000778 testImport(
779 "struct C {};"
780 "void declToImport() { C c = C(); }",
781 Lang_CXX, "", Lang_CXX, Verifier,
782 functionDecl(hasDescendant(
783 exprWithCleanups(has(cxxConstructExpr(
784 has(materializeTemporaryExpr(has(implicitCastExpr(
785 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000786}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000787
Gabor Marton19f4f392018-06-25 13:04:37 +0000788TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000789 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000790 testImport(
791 "void declToImport() { typedef _Atomic(int) a_int; }",
792 Lang_CXX11, "", Lang_CXX11, Verifier,
793 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000794}
795
Gabor Marton19f4f392018-06-25 13:04:37 +0000796TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000797 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000798 testImport(
799 "template <typename T> void declToImport() { };",
800 Lang_CXX, "", Lang_CXX, Verifier,
801 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000802}
803
804const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
805 cxxDependentScopeMemberExpr;
806
Gabor Marton19f4f392018-06-25 13:04:37 +0000807TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000808 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000809 testImport(
810 "template <typename T> struct C { T t; };"
811 "template <typename T> void declToImport() {"
812 " C<T> d;"
813 " (void)d.t;"
814 "}"
815 "void instantiate() { declToImport<int>(); }",
816 Lang_CXX, "", Lang_CXX, Verifier,
817 functionTemplateDecl(hasDescendant(
818 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
819 testImport(
820 "template <typename T> struct C { T t; };"
821 "template <typename T> void declToImport() {"
822 " C<T> d;"
823 " (void)(&d)->t;"
824 "}"
825 "void instantiate() { declToImport<int>(); }",
826 Lang_CXX, "", Lang_CXX, Verifier,
827 functionTemplateDecl(hasDescendant(
828 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000829}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000830
Gabor Marton19f4f392018-06-25 13:04:37 +0000831TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000832 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000833 testImport(
834 "template <int K>"
835 "struct dummy { static const int i = K; };"
836 "template <int K> using dummy2 = dummy<K>;"
837 "int declToImport() { return dummy2<3>::i; }",
838 Lang_CXX11, "", Lang_CXX11, Verifier,
839 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000840 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000841 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
842}
843
844const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
845 varTemplateSpecializationDecl;
846
Gabor Marton19f4f392018-06-25 13:04:37 +0000847TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000848 MatchVerifier<Decl> Verifier;
849 testImport(
850 "template <typename T>"
851 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000852 "void declToImport() { (void)pi<int>; }",
853 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000854 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000855 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000856 unless(hasAncestor(translationUnitDecl(has(varDecl(
857 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000858}
859
Gabor Marton19f4f392018-06-25 13:04:37 +0000860TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000861 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000862 testImport(
863 "template <typename... Args>"
864 "struct dummy {"
865 " dummy(Args... args) {}"
866 " static const int i = 4;"
867 "};"
868 "int declToImport() { return dummy<int>::i; }",
869 Lang_CXX11, "", Lang_CXX11, Verifier,
870 functionDecl(hasDescendant(
871 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000872}
873
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000874const internal::VariadicDynCastAllOfMatcher<Type,
875 DependentTemplateSpecializationType>
876 dependentTemplateSpecializationType;
877
Gabor Marton19f4f392018-06-25 13:04:37 +0000878TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000879 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000880 testImport(
881 "template<typename T>"
882 "struct A;"
883 "template<typename T>"
884 "struct declToImport {"
885 " typename A<T>::template B<T> a;"
886 "};",
887 Lang_CXX, "", Lang_CXX, Verifier,
888 classTemplateDecl(has(cxxRecordDecl(has(
889 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000890}
891
892const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
893 sizeOfPackExpr;
894
Gabor Marton19f4f392018-06-25 13:04:37 +0000895TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000896 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000897 testImport(
898 "template <typename... Ts>"
899 "void declToImport() {"
900 " const int i = sizeof...(Ts);"
901 "};"
902 "void g() { declToImport<int>(); }",
903 Lang_CXX11, "", Lang_CXX11, Verifier,
904 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000905 testImport(
906 "template <typename... Ts>"
907 "using X = int[sizeof...(Ts)];"
908 "template <typename... Us>"
909 "struct Y {"
910 " X<Us..., int, double, int, Us...> f;"
911 "};"
912 "Y<float, int> declToImport;",
913 Lang_CXX11, "", Lang_CXX11, Verifier,
914 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
915 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
916}
917
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000918/// \brief Matches __builtin_types_compatible_p:
919/// GNU extension to check equivalent types
920/// Given
921/// \code
922/// __builtin_types_compatible_p(int, int)
923/// \endcode
924// will generate TypeTraitExpr <...> 'int'
925const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
926
Gabor Marton19f4f392018-06-25 13:04:37 +0000927TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000928 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000929 testImport(
930 "void declToImport() { "
931 " (void)__builtin_types_compatible_p(int, int);"
932 "}",
933 Lang_C, "", Lang_C, Verifier,
934 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000935}
936
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000937const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
938
Gabor Marton19f4f392018-06-25 13:04:37 +0000939TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000940 MatchVerifier<Decl> Verifier;
941 testImport(
942 "namespace std { class type_info {}; }"
943 "void declToImport() {"
944 " int x;"
945 " auto a = typeid(int); auto b = typeid(x);"
946 "}",
947 Lang_CXX11, "", Lang_CXX11, Verifier,
948 functionDecl(
949 hasDescendant(varDecl(
950 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
951 hasDescendant(varDecl(
952 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
953}
954
Gabor Marton19f4f392018-06-25 13:04:37 +0000955TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000956 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000957 testImport(
958 "template<typename T> struct declToImport {"
959 " void m() { (void)__is_pod(T); }"
960 "};"
961 "void f() { declToImport<int>().m(); }",
962 Lang_CXX11, "", Lang_CXX11, Verifier,
963 classTemplateDecl(has(cxxRecordDecl(has(
964 functionDecl(hasDescendant(
965 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000966}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000967
Gabor Marton6e1510c2018-07-12 11:50:21 +0000968TEST_P(ImportDecl, ImportRecordDeclInFunc) {
969 MatchVerifier<Decl> Verifier;
970 testImport("int declToImport() { "
971 " struct data_t {int a;int b;};"
972 " struct data_t d;"
973 " return 0;"
974 "}",
975 Lang_C, "", Lang_C, Verifier,
976 functionDecl(hasBody(compoundStmt(
977 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
978}
979
980TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
981 Decl *FromTU = getTuDecl("int declToImport() { "
982 " struct data_t {int a;int b;};"
983 " struct data_t d;"
984 " return 0;"
985 "}",
986 Lang_C, "input.c");
987 auto FromVar =
988 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
989 ASSERT_TRUE(FromVar);
990 auto ToType =
991 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
992 EXPECT_FALSE(ToType.isNull());
993}
994
995TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
996 // This construct is not supported by ASTImporter.
997 Decl *FromTU =
998 getTuDecl("int declToImport(struct data_t{int a;int b;} *d){ return 0; }",
999 Lang_C, "input.c");
1000 auto From = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1001 ASSERT_TRUE(From);
1002 auto To = Import(From, Lang_C);
1003 EXPECT_EQ(To, nullptr);
1004}
1005
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001006const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1007 cxxPseudoDestructorExpr;
1008
Gabor Marton19f4f392018-06-25 13:04:37 +00001009TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001010 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001011 testImport(
1012 "typedef int T;"
1013 "void declToImport(int *p) {"
1014 " T t;"
1015 " p->T::~T();"
1016 "}",
1017 Lang_CXX, "", Lang_CXX, Verifier,
1018 functionDecl(hasDescendant(
1019 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001020}
1021
Gabor Marton19f4f392018-06-25 13:04:37 +00001022TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001023 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001024 testImport(
1025 "namespace foo { int bar; }"
1026 "void declToImport() { using foo::bar; }",
1027 Lang_CXX, "", Lang_CXX, Verifier,
1028 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001029}
1030
1031/// \brief Matches shadow declarations introduced into a scope by a
1032/// (resolved) using declaration.
1033///
1034/// Given
1035/// \code
1036/// namespace n { int f; }
1037/// namespace declToImport { using n::f; }
1038/// \endcode
1039/// usingShadowDecl()
1040/// matches \code f \endcode
1041const internal::VariadicDynCastAllOfMatcher<Decl,
1042 UsingShadowDecl> usingShadowDecl;
1043
Gabor Marton19f4f392018-06-25 13:04:37 +00001044TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001045 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001046 testImport(
1047 "namespace foo { int bar; }"
1048 "namespace declToImport { using foo::bar; }",
1049 Lang_CXX, "", Lang_CXX, Verifier,
1050 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001051}
1052
Gabor Marton19f4f392018-06-25 13:04:37 +00001053TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001054 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001055 testImport(
1056 "template<typename T> int foo();"
1057 "template <typename T> void declToImport() {"
1058 " (void)::foo<T>;"
1059 " (void)::template foo<T>;"
1060 "}"
1061 "void instantiate() { declToImport<int>(); }",
1062 Lang_CXX, "", Lang_CXX, Verifier,
1063 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001064}
1065
Gabor Marton19f4f392018-06-25 13:04:37 +00001066TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001067 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001068 testImport(
1069 "template <typename T> struct C { T t; };"
1070 "template <typename T> void declToImport() {"
1071 " C<T> d;"
1072 " d.t = T();"
1073 "}"
1074 "void instantiate() { declToImport<int>(); }",
1075 Lang_CXX, "", Lang_CXX, Verifier,
1076 functionTemplateDecl(hasDescendant(
1077 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1078 testImport(
1079 "template <typename T> struct C { T t; };"
1080 "template <typename T> void declToImport() {"
1081 " C<T> d;"
1082 " (&d)->t = T();"
1083 "}"
1084 "void instantiate() { declToImport<int>(); }",
1085 Lang_CXX, "", Lang_CXX, Verifier,
1086 functionTemplateDecl(hasDescendant(
1087 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001088}
1089
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001090/// Check that function "declToImport()" (which is the templated function
1091/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1092/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001093TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001094 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001095 testImport(
1096 "template <typename T> void declToImport() { T a = 1; }"
1097 "void instantiate() { declToImport<int>(); }",
1098 Lang_CXX, "", Lang_CXX, Verifier,
1099 functionTemplateDecl(hasAncestor(translationUnitDecl(
1100 unless(has(functionDecl(hasName("declToImport"))))))));
1101 testImport(
1102 "template <typename T> struct declToImport { T t; };"
1103 "void instantiate() { declToImport<int>(); }",
1104 Lang_CXX, "", Lang_CXX, Verifier,
1105 classTemplateDecl(hasAncestor(translationUnitDecl(
1106 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001107}
1108
Gabor Marton19f4f392018-06-25 13:04:37 +00001109TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001110 MatchVerifier<Decl> Verifier;
1111 auto Code =
1112 R"s(
1113 struct declToImport {
1114 template <typename T0> struct X;
1115 template <typename T0> struct X<T0 *> {};
1116 };
1117 )s";
1118 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1119 recordDecl(has(classTemplateDecl()),
1120 has(classTemplateSpecializationDecl())));
1121}
1122
Gabor Marton19f4f392018-06-25 13:04:37 +00001123TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001124 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001125 testImport(
1126 "class declToImport {"
1127 " void f() { *this = declToImport(); }"
1128 "};",
1129 Lang_CXX, "", Lang_CXX, Verifier,
1130 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1131 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001132}
1133
Gabor Marton19f4f392018-06-25 13:04:37 +00001134TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001135 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001136 testImport(
1137 "template<typename T, int Size> class declToImport {"
1138 " T data[Size];"
1139 "};",
1140 Lang_CXX, "", Lang_CXX, Verifier,
1141 classTemplateDecl(has(cxxRecordDecl(
1142 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001143}
1144
Gabor Martona0df7a92018-05-30 09:19:26 +00001145TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1146 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1147 auto From =
1148 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1149 ASSERT_TRUE(From);
1150 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1151 ASSERT_TRUE(To);
1152 Decl *ToTemplated = To->getTemplatedDecl();
1153 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1154 EXPECT_TRUE(ToTemplated1);
1155 EXPECT_EQ(ToTemplated1, ToTemplated);
1156}
1157
Gabor Marton26f72a92018-07-12 09:42:05 +00001158TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001159 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1160 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1161 FromTU, functionTemplateDecl());
1162 ASSERT_TRUE(From);
1163 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1164 ASSERT_TRUE(To);
1165 Decl *ToTemplated = To->getTemplatedDecl();
1166 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1167 EXPECT_TRUE(ToTemplated1);
1168 EXPECT_EQ(ToTemplated1, ToTemplated);
1169}
1170
1171TEST_P(ASTImporterTestBase,
1172 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1173 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1174 auto FromFT =
1175 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1176 ASSERT_TRUE(FromFT);
1177
1178 auto ToTemplated =
1179 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1180 EXPECT_TRUE(ToTemplated);
1181 auto ToTU = ToTemplated->getTranslationUnitDecl();
1182 auto ToFT =
1183 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1184 EXPECT_TRUE(ToFT);
1185}
1186
1187TEST_P(ASTImporterTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001188 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001189 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1190 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1191 FromTU, functionTemplateDecl());
1192 ASSERT_TRUE(FromFT);
1193
1194 auto ToTemplated =
1195 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1196 EXPECT_TRUE(ToTemplated);
1197 auto ToTU = ToTemplated->getTranslationUnitDecl();
1198 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1199 ToTU, functionTemplateDecl());
1200 EXPECT_TRUE(ToFT);
1201}
1202
Gabor Martona0df7a92018-05-30 09:19:26 +00001203TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1204 auto Code =
1205 R"(
1206 namespace x {
1207 template<class X> struct S1{};
1208 template<class X> struct S2{};
1209 template<class X> struct S3{};
1210 }
1211 )";
1212 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1213 auto FromNs =
1214 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1215 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1216 ASSERT_TRUE(ToNs);
1217 auto From =
1218 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1219 classTemplateDecl(
1220 hasName("S2")));
1221 auto To =
1222 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1223 classTemplateDecl(
1224 hasName("S2")));
1225 ASSERT_TRUE(From);
1226 ASSERT_TRUE(To);
1227 auto ToTemplated = To->getTemplatedDecl();
1228 auto ToTemplated1 =
1229 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1230 EXPECT_TRUE(ToTemplated1);
1231 ASSERT_EQ(ToTemplated1, ToTemplated);
1232}
1233
Gabor Marton26f72a92018-07-12 09:42:05 +00001234TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001235 Decl *From, *To;
1236 std::tie(From, To) = getImportedDecl(
1237 R"(
1238 template <typename T> struct X {};
1239
1240 void declToImport(int y, X<int> &x) {}
1241
1242 template <> struct X<int> {
1243 void g() {
1244 X<int> x;
1245 declToImport(0, x);
1246 }
1247 };
1248 )",
1249 Lang_CXX, "", Lang_CXX);
1250
1251 MatchVerifier<Decl> Verifier;
1252 auto Matcher = functionDecl(hasName("declToImport"),
1253 parameterCountIs(2),
1254 hasParameter(0, hasName("y")),
1255 hasParameter(1, hasName("x")),
1256 hasParameter(1, hasType(asString("X<int> &"))));
1257 ASSERT_TRUE(Verifier.match(From, Matcher));
1258 EXPECT_TRUE(Verifier.match(To, Matcher));
1259}
1260
1261TEST_P(ASTImporterTestBase,
1262 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1263 Decl *From, *To;
1264 std::tie(From, To) =
1265 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1266 "void instantiate() { declToImport<int>(); }",
1267 Lang_CXX, "", Lang_CXX);
1268
1269 auto Check = [](Decl *D) -> bool {
1270 auto TU = D->getTranslationUnitDecl();
1271 for (auto Child : TU->decls()) {
1272 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1273 if (FD->getNameAsString() == "declToImport") {
1274 GTEST_NONFATAL_FAILURE_(
1275 "TU should not contain any FunctionDecl with name declToImport");
1276 return false;
1277 }
1278 }
1279 }
1280 return true;
1281 };
1282
1283 ASSERT_TRUE(Check(From));
1284 EXPECT_TRUE(Check(To));
1285}
1286
1287TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1288 Decl *From, *To;
1289 std::tie(From, To) =
1290 getImportedDecl("template <typename T> struct declToImport { T t; };"
1291 "void instantiate() { declToImport<int>(); }",
1292 Lang_CXX, "", Lang_CXX);
1293
1294 auto Check = [](Decl *D) -> bool {
1295 auto TU = D->getTranslationUnitDecl();
1296 for (auto Child : TU->decls()) {
1297 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1298 if (RD->getNameAsString() == "declToImport") {
1299 GTEST_NONFATAL_FAILURE_(
1300 "TU should not contain any CXXRecordDecl with name declToImport");
1301 return false;
1302 }
1303 }
1304 }
1305 return true;
1306 };
1307
1308 ASSERT_TRUE(Check(From));
1309 EXPECT_TRUE(Check(To));
1310}
1311
1312TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1313 Decl *From, *To;
1314 std::tie(From, To) =
1315 getImportedDecl(
1316 "template <typename T> struct X {};"
1317 "template <typename T> using declToImport = X<T>;"
1318 "void instantiate() { declToImport<int> a; }",
1319 Lang_CXX11, "", Lang_CXX11);
1320
1321 auto Check = [](Decl *D) -> bool {
1322 auto TU = D->getTranslationUnitDecl();
1323 for (auto Child : TU->decls()) {
1324 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1325 if (AD->getNameAsString() == "declToImport") {
1326 GTEST_NONFATAL_FAILURE_(
1327 "TU should not contain any TypeAliasDecl with name declToImport");
1328 return false;
1329 }
1330 }
1331 }
1332 return true;
1333 };
1334
1335 ASSERT_TRUE(Check(From));
1336 EXPECT_TRUE(Check(To));
1337}
1338
1339TEST_P(
1340 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001341 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001342
1343 Decl *From, *To;
1344 std::tie(From, To) = getImportedDecl(
1345 R"(
1346 template<class T>
1347 class Base {};
1348 class declToImport : public Base<declToImport> {};
1349 )",
1350 Lang_CXX, "", Lang_CXX);
1351
1352 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1353 auto Pattern =
1354 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1355 ASSERT_TRUE(
1356 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1357 EXPECT_TRUE(
1358 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1359
1360 // Check that the ClassTemplateSpecializationDecl is the child of the
1361 // ClassTemplateDecl.
1362 Pattern = translationUnitDecl(has(classTemplateDecl(
1363 hasName("Base"), has(classTemplateSpecializationDecl()))));
1364 ASSERT_TRUE(
1365 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1366 EXPECT_TRUE(
1367 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1368}
1369
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001370AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1371 size_t Index = 0;
1372 for (FieldDecl *Field : Node.fields()) {
1373 if (Index == Order.size())
1374 return false;
1375 if (Field->getName() != Order[Index])
1376 return false;
1377 ++Index;
1378 }
1379 return Index == Order.size();
1380}
1381
Peter Szecsidedda6f2018-03-30 22:03:29 +00001382TEST_P(ASTImporterTestBase,
1383 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1384 Decl *From, *To;
1385 std::tie(From, To) = getImportedDecl(
1386 R"(
1387 namespace NS {
1388 template<class T>
1389 class X {};
1390 template class X<int>;
1391 }
1392 )",
1393 Lang_CXX, "", Lang_CXX, "NS");
1394
1395 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1396 // ClassTemplateDecl.
1397 auto Pattern = namespaceDecl(has(classTemplateDecl(
1398 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1399 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1400 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1401
1402 // Check that the ClassTemplateSpecializationDecl is the child of the
1403 // NamespaceDecl.
1404 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1405 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1406 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1407}
1408
1409TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1410 Decl *From, *To;
1411 std::tie(From, To) =
1412 getImportedDecl(
1413 "struct declToImport { int a; int b; };",
1414 Lang_CXX11, "", Lang_CXX11);
1415
1416 MatchVerifier<Decl> Verifier;
1417 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1418 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1419}
1420
1421TEST_P(ASTImporterTestBase,
1422 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1423 Decl *From, *To;
1424 std::tie(From, To) = getImportedDecl(
1425 // The original recursive algorithm of ASTImporter first imports 'c' then
1426 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1427 R"s(
1428 struct declToImport {
1429 int a = c + b;
1430 int b = 1;
1431 int c = 2;
1432 };
1433 )s",
1434 Lang_CXX11, "", Lang_CXX11);
1435
1436 MatchVerifier<Decl> Verifier;
1437 ASSERT_TRUE(
1438 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1439 EXPECT_TRUE(
1440 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1441}
1442
Gabor Martonde8bf262018-05-17 09:46:07 +00001443TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001444 Decl *From, *To;
1445 std::tie(From, To) = getImportedDecl(
1446 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001447 struct declToImport {
1448 };
1449 )",
1450 Lang_CXX, "", Lang_CXX);
1451
1452 MatchVerifier<Decl> Verifier;
1453 // Match the implicit Decl.
1454 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1455 ASSERT_TRUE(Verifier.match(From, Matcher));
1456 EXPECT_TRUE(Verifier.match(To, Matcher));
1457}
1458
1459TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1460 Decl *From, *To;
1461 std::tie(From, To) = getImportedDecl(
1462 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001463 template <typename U>
1464 struct declToImport {
1465 };
1466 )",
1467 Lang_CXX, "", Lang_CXX);
1468
1469 MatchVerifier<Decl> Verifier;
1470 // Match the implicit Decl.
1471 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1472 ASSERT_TRUE(Verifier.match(From, Matcher));
1473 EXPECT_TRUE(Verifier.match(To, Matcher));
1474}
1475
1476TEST_P(
1477 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001478 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001479 Decl *From, *To;
1480 std::tie(From, To) = getImportedDecl(
1481 R"(
1482 template<class T>
1483 class Base {};
1484 class declToImport : public Base<declToImport> {};
1485 )",
1486 Lang_CXX, "", Lang_CXX);
1487
1488 auto hasImplicitClass = has(cxxRecordDecl());
1489 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1490 hasName("Base"),
1491 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1492 ASSERT_TRUE(
1493 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1494 EXPECT_TRUE(
1495 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1496}
1497
1498TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1499 Decl *From, *To;
1500 std::tie(From, To) =
1501 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1502
1503 MatchVerifier<Decl> Verifier;
1504 auto Matcher = functionDecl();
1505 ASSERT_TRUE(Verifier.match(From, Matcher));
1506 EXPECT_TRUE(Verifier.match(To, Matcher));
1507 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1508}
1509
Gabor Marton2ae9da32018-05-18 15:46:18 +00001510TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001511 Decl *FromTU = getTuDecl(
1512 R"(
1513 struct X {};
1514 void operator<<(int, X);
1515 )",
1516 Lang_CXX);
1517 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1518 const Decl *To = Import(From, Lang_CXX);
1519 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1520}
1521
1522TEST_P(ASTImporterTestBase,
1523 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1524 Decl *From, *To;
1525 std::tie(From, To) = getImportedDecl(
1526 R"(
1527 template<class T>
1528 class Base { int a; };
1529 class declToImport : Base<declToImport> {};
1530 )",
1531 Lang_CXX, "", Lang_CXX);
1532
1533 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1534 hasName("Base"),
1535 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1536 ASSERT_TRUE(
1537 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1538 EXPECT_TRUE(
1539 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1540}
1541
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001542TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1543 {
1544 Decl *FromTU = getTuDecl(
1545 R"(
1546 template <typename T>
1547 struct B;
1548 )",
1549 Lang_CXX, "input0.cc");
1550 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1551 FromTU, classTemplateDecl(hasName("B")));
1552
1553 Import(FromD, Lang_CXX);
1554 }
1555
1556 {
1557 Decl *FromTU = getTuDecl(
1558 R"(
1559 template <typename T>
1560 struct B {
1561 void f();
1562 };
1563 )",
1564 Lang_CXX, "input1.cc");
1565 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1566 FromTU, functionDecl(hasName("f")));
1567 Import(FromD, Lang_CXX);
1568 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1569 FromTU, classTemplateDecl(hasName("B")));
1570 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1571 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1572 }
1573}
1574
Gabor Marton9581c332018-05-23 13:53:36 +00001575TEST_P(ASTImporterTestBase,
1576 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1577 Decl *ToTU = getToTuDecl(
1578 R"(
1579 template <typename T>
1580 struct B {
1581 void f();
1582 };
1583
1584 template <typename T>
1585 struct B;
1586 )",
1587 Lang_CXX);
1588 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1589 [](const ClassTemplateDecl *T) {
1590 return T->isThisDeclarationADefinition();
1591 })
1592 .match(ToTU, classTemplateDecl()));
1593
1594 Decl *FromTU = getTuDecl(
1595 R"(
1596 template <typename T>
1597 struct B {
1598 void f();
1599 };
1600 )",
1601 Lang_CXX, "input1.cc");
1602 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1603 FromTU, classTemplateDecl(hasName("B")));
1604
1605 Import(FromD, Lang_CXX);
1606
1607 // We should have only one definition.
1608 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1609 [](const ClassTemplateDecl *T) {
1610 return T->isThisDeclarationADefinition();
1611 })
1612 .match(ToTU, classTemplateDecl()));
1613}
1614
1615TEST_P(ASTImporterTestBase,
1616 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1617 Decl *ToTU = getToTuDecl(
1618 R"(
1619 struct B {
1620 void f();
1621 };
1622
1623 struct B;
1624 )",
1625 Lang_CXX);
1626 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001627 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001628
1629 Decl *FromTU = getTuDecl(
1630 R"(
1631 struct B {
1632 void f();
1633 };
1634 )",
1635 Lang_CXX, "input1.cc");
1636 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1637 FromTU, cxxRecordDecl(hasName("B")));
1638
1639 Import(FromD, Lang_CXX);
1640
1641 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001642 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001643}
1644
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001645static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1646 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1647 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1648 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1649 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1650}
1651static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1652 SourceManager &SM1, SourceManager &SM2) {
1653 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1654 FullSourceLoc{ Range2.getBegin(), SM2 });
1655 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1656 FullSourceLoc{ Range2.getEnd(), SM2 });
1657}
1658TEST_P(ASTImporterTestBase, ImportSourceLocs) {
1659 Decl *FromTU = getTuDecl(
1660 R"(
1661 #define MFOO(arg) arg = arg + 1
1662
1663 void foo() {
1664 int a = 5;
1665 MFOO(a);
1666 }
1667 )",
1668 Lang_CXX);
1669 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1670 auto ToD = Import(FromD, Lang_CXX);
1671
1672 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1673 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1674 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1675 auto FromRHS =
1676 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1677
1678 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1679 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1680 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1681 FromSM);
1682 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1683 FromSM);
1684 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1685 FromSM);
1686}
1687
Rafael Stahla0010472018-07-09 08:40:17 +00001688TEST_P(ASTImporterTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001689 Decl *FromTU = getTuDecl(
1690 R"(
1691 #define FUNC_INT void declToImport
1692 #define FUNC FUNC_INT
1693 FUNC(int a);
1694 )",
1695 Lang_CXX);
1696 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1697 auto ToD = Import(FromD, Lang_CXX);
1698
1699 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1700 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1701 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1702 FromSM);
1703}
1704
Gabor Marton9581c332018-05-23 13:53:36 +00001705TEST_P(
1706 ASTImporterTestBase,
1707 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1708{
1709 Decl *ToTU = getToTuDecl(
1710 R"(
1711 template <typename T>
1712 struct B;
1713
1714 template <>
1715 struct B<int> {};
1716
1717 template <>
1718 struct B<int>;
1719 )",
1720 Lang_CXX);
1721 // We should have only one definition.
1722 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1723 [](const ClassTemplateSpecializationDecl *T) {
1724 return T->isThisDeclarationADefinition();
1725 })
1726 .match(ToTU, classTemplateSpecializationDecl()));
1727
1728 Decl *FromTU = getTuDecl(
1729 R"(
1730 template <typename T>
1731 struct B;
1732
1733 template <>
1734 struct B<int> {};
1735 )",
1736 Lang_CXX, "input1.cc");
1737 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1738 FromTU, classTemplateSpecializationDecl(hasName("B")));
1739
1740 Import(FromD, Lang_CXX);
1741
1742 // We should have only one definition.
1743 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1744 [](const ClassTemplateSpecializationDecl *T) {
1745 return T->isThisDeclarationADefinition();
1746 })
1747 .match(ToTU, classTemplateSpecializationDecl()));
1748}
1749
Gabor Marton0bebf952018-07-05 09:51:13 +00001750TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
1751 Decl *FromTU = getTuDecl(
1752 R"(
1753 struct { int a; int b; } object0 = { 2, 3 };
1754 struct { int x; int y; int z; } object1;
1755 )",
1756 Lang_CXX, "input0.cc");
1757
1758 auto getRecordDecl = [](VarDecl *VD) {
1759 auto *ET = cast<ElaboratedType>(VD->getType().getTypePtr());
1760 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
1761 };
1762
1763 auto *Obj0 =
1764 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1765 auto *From0 = getRecordDecl(Obj0);
1766 auto *Obj1 =
1767 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1768 auto *From1 = getRecordDecl(Obj1);
1769
1770 auto *To0 = Import(From0, Lang_CXX);
1771 auto *To1 = Import(From1, Lang_CXX);
1772
1773 EXPECT_TRUE(To0);
1774 EXPECT_TRUE(To1);
1775 EXPECT_NE(To0, To1);
1776 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1777}
1778
Gabor Marton26f72a92018-07-12 09:42:05 +00001779TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
1780 auto Pattern = varDecl(hasName("x"));
1781 VarDecl *Imported1;
1782 {
1783 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1784 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1785 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1786 }
1787 VarDecl *Imported2;
1788 {
1789 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1790 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1791 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1792 }
1793 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1794 EXPECT_FALSE(Imported2->isUsed(false));
1795 {
1796 Decl *FromTU =
1797 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
1798 auto *FromD =
1799 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1800 Import(FromD, Lang_CXX);
1801 }
1802 EXPECT_TRUE(Imported2->isUsed(false));
1803}
1804
1805TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
1806 auto Pattern = varDecl(hasName("x"));
1807
1808 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1809 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1810
1811 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1812
1813 ASSERT_FALSE(Imported1->isUsed(false));
1814
1815 FromD->setIsUsed();
1816 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1817
1818 EXPECT_EQ(Imported1, Imported2);
1819 EXPECT_TRUE(Imported2->isUsed(false));
1820}
1821
Peter Szecsidedda6f2018-03-30 22:03:29 +00001822struct ImportFunctions : ASTImporterTestBase {};
1823
1824TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001825 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1826 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1827 auto Pattern = functionDecl(hasName("f"));
1828 FunctionDecl *FromD = // Definition
1829 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1830
1831 Decl *ImportedD = Import(FromD, Lang_CXX);
1832 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1833
Gabor Marton5254e642018-06-27 13:32:50 +00001834 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001835 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1836}
1837
1838TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1839 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1840 auto Pattern = functionDecl(hasName("f"));
1841 FunctionDecl *FromD =
1842 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1843
1844 Decl *ImportedD = Import(FromD, Lang_CXX);
1845 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1846
1847 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1848 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1849}
1850
Gabor Marton5254e642018-06-27 13:32:50 +00001851TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001852 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1853 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001854 auto *From =
1855 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001856
Gabor Marton5254e642018-06-27 13:32:50 +00001857 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001858 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1859
Gabor Marton5254e642018-06-27 13:32:50 +00001860 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1861 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1862 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1863 EXPECT_TRUE(ImportedD == To0);
1864 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1865 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1866 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001867}
1868
1869TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1870 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1871 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001872 auto *From =
1873 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001874
Gabor Marton5254e642018-06-27 13:32:50 +00001875 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001876 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1877
Gabor Marton5254e642018-06-27 13:32:50 +00001878 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1879 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1880 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1881 EXPECT_TRUE(ImportedD == To1);
1882 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1883 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1884 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001885}
1886
1887TEST_P(ImportFunctions, ImportPrototypes) {
1888 auto Pattern = functionDecl(hasName("f"));
1889
1890 Decl *ImportedD;
1891 {
1892 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001893 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001894
1895 ImportedD = Import(FromD, Lang_CXX);
1896 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001897 {
1898 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001899 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1900 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001901 }
1902
Gabor Marton5254e642018-06-27 13:32:50 +00001903 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1904
1905 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1906 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1907 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1908 EXPECT_TRUE(ImportedD == To0);
1909 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1910 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1911 EXPECT_EQ(To1->getPreviousDecl(), To0);
1912}
1913
1914TEST_P(ImportFunctions, ImportDefinitions) {
1915 auto Pattern = functionDecl(hasName("f"));
1916
1917 Decl *ImportedD;
1918 {
1919 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1920 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1921 ImportedD = Import(FromD, Lang_CXX);
1922 }
1923 {
1924 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
1925 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1926 Import(FromD, Lang_CXX);
1927 }
1928
1929 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1930
Peter Szecsidedda6f2018-03-30 22:03:29 +00001931 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00001932 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1933 EXPECT_TRUE(ImportedD == To0);
1934 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001935}
1936
1937TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1938 auto Pattern = functionDecl(hasName("f"));
1939
1940 Decl *ImportedD;
1941 {
1942 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001943 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001944 ImportedD = Import(FromD, Lang_CXX);
1945 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001946 {
1947 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001948 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1949 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001950 }
1951
1952 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001953
1954 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1955 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1956 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1957 EXPECT_TRUE(ImportedD == To0);
1958 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
1959 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1960 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001961}
1962
1963TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1964 auto Pattern = functionDecl(hasName("f"));
1965
1966 {
1967 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1968 FunctionDecl *FromD =
1969 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1970
1971 Import(FromD, Lang_CXX);
1972 }
1973 {
1974 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1975 FunctionDecl *FromD =
1976 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1977 Import(FromD, Lang_CXX);
1978 }
1979
1980 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1981 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1982 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00001983 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001984 FunctionDecl *DefinitionD =
1985 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1986 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1987 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1988}
1989
Gabor Marton5254e642018-06-27 13:32:50 +00001990TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001991 auto Pattern = functionDecl(hasName("f"));
1992
1993 {
1994 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001995 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001996 Import(FromD, Lang_CXX);
1997 }
1998 {
1999 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002000 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002001 Import(FromD, Lang_CXX);
2002 }
2003
2004 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002005
2006 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002007 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002008 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
2009
Peter Szecsidedda6f2018-03-30 22:03:29 +00002010 FunctionDecl *DefinitionD =
2011 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2012 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00002013
2014 EXPECT_TRUE(DefinitionD->getPreviousDecl());
2015 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
2016 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002017}
2018
2019TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2020 auto Code =
2021 R"(
2022 struct B { virtual void f(); };
2023 void B::f() {}
2024 struct D : B { void f(); };
2025 )";
2026 auto Pattern =
2027 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2028 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2029 CXXMethodDecl *Proto =
2030 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2031
2032 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2033 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2034 EXPECT_EQ(To->size_overridden_methods(), 1u);
2035}
2036
2037TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2038 auto Code =
2039 R"(
2040 struct B { virtual void f(); };
2041 void B::f() {}
2042 )";
2043 auto Pattern =
2044 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2045 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2046 CXXMethodDecl *Proto =
2047 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2048 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2049
2050 ASSERT_TRUE(Proto->isVirtual());
2051 ASSERT_TRUE(Def->isVirtual());
2052 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2053 EXPECT_TRUE(To->isVirtual());
2054}
2055
Gabor Marton5254e642018-06-27 13:32:50 +00002056TEST_P(ImportFunctions,
2057 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2058 Decl *ToTU = getToTuDecl(
2059 R"(
2060 void f() {}
2061 void f();
2062 )",
2063 Lang_CXX);
2064 ASSERT_EQ(1u,
2065 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2066 return FD->doesThisDeclarationHaveABody();
2067 }).match(ToTU, functionDecl()));
2068
2069 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2070 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2071
2072 Import(FromD, Lang_CXX);
2073
2074 EXPECT_EQ(1u,
2075 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2076 return FD->doesThisDeclarationHaveABody();
2077 }).match(ToTU, functionDecl()));
2078}
2079
2080struct ImportFriendFunctions : ImportFunctions {};
2081
2082TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2083 auto Pattern = functionDecl(hasName("f"));
2084
2085 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2086 "void f();",
2087 Lang_CXX,
2088 "input0.cc");
2089 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2090
2091 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2092 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2093 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2094 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2095 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2096 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2097 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2098}
2099
2100TEST_P(ImportFriendFunctions,
2101 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2102 auto Pattern = functionDecl(hasName("f"));
2103
2104 Decl *FromTU = getTuDecl("void f();"
2105 "struct X { friend void f(); };",
2106 Lang_CXX, "input0.cc");
2107 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2108
2109 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2110 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2111 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2112 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2113 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2114 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2115 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2116}
2117
2118TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2119 auto Pattern = functionDecl(hasName("f"));
2120
2121 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2122 "void f();",
2123 Lang_CXX,
2124 "input0.cc");
2125 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2126
2127 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2128 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2129 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2130 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2131 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2132 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2133 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2134}
2135
2136TEST_P(ImportFriendFunctions,
2137 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2138 auto Pattern = functionDecl(hasName("f"));
2139
2140 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2141 "void f(){}",
2142 Lang_CXX, "input0.cc");
2143 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2144
2145 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2146 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2147 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2148 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2149 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2150 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2151 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2152}
2153
Gabor Marton26f72a92018-07-12 09:42:05 +00002154// Disabled temporarily, because the new structural equivalence check
2155// (https://reviews.llvm.org/D48628) breaks it.
2156// PreviousDecl is not set because there is no structural match.
2157// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002158TEST_P(ImportFriendFunctions,
2159 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2160 auto Pattern = functionDecl(hasName("f"));
2161
2162 Decl *FromTU = getTuDecl(
2163 R"(
2164 class X;
2165 void f(X *x){}
2166 class X{
2167 friend void f(X *x);
2168 };
2169 )",
2170 Lang_CXX, "input0.cc");
2171 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2172
2173 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2174 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2175 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2176 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2177 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2178 .match(ToTU, friendDecl())
2179 ->getFriendDecl());
2180 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2181 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2182 // The parameters must refer the same type
2183 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2184 (*ImportedD->param_begin())->getOriginalType());
2185}
2186
Gabor Marton26f72a92018-07-12 09:42:05 +00002187// Disabled temporarily, because the new structural equivalence check
2188// (https://reviews.llvm.org/D48628) breaks it.
2189// PreviousDecl is not set because there is no structural match.
2190// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002191TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002192 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002193 auto Pattern = functionDecl(hasName("f"));
2194
2195 Decl *FromTU = getTuDecl(
2196 R"(
2197 class X;
2198 void f(X *x){}
2199 class X{
2200 friend void f(X *x);
2201 };
2202 )",
2203 Lang_CXX, "input0.cc");
2204 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2205
2206 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2207 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2208 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2209 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2210 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2211 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2212
2213 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2214 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2215 // The parameters must refer the same type
2216 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2217 (*ImportedD->param_begin())->getOriginalType());
2218}
2219
2220TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2221 auto Pattern = functionDecl(hasName("f"));
2222
2223 FunctionDecl *ImportedD;
2224 {
2225 Decl *FromTU =
2226 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2227 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2228 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2229 }
2230 FunctionDecl *ImportedD1;
2231 {
2232 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2233 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2234 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2235 }
2236
2237 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2238 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2239 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2240 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2241 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2242}
2243
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002244AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2245 InnerMatcher) {
2246 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2247 return InnerMatcher.matches(*Typedef, Finder, Builder);
2248 return false;
2249}
2250
Gabor Marton19f4f392018-06-25 13:04:37 +00002251TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002252 CodeFiles Samples{{"main.c",
2253 {"void foo();"
2254 "void moo();"
2255 "int main() { foo(); moo(); }",
2256 Lang_C}},
2257
2258 {"foo.c",
2259 {"typedef enum { THING_VALUE } thing_t;"
2260 "void conflict(thing_t type);"
2261 "void foo() { (void)THING_VALUE; }"
2262 "void conflict(thing_t type) {}",
2263 Lang_C}},
2264
2265 {"moo.c",
2266 {"typedef enum { THING_VALUE } thing_t;"
2267 "void conflict(thing_t type);"
2268 "void moo() { conflict(THING_VALUE); }",
2269 Lang_C}}};
2270
2271 auto VerificationMatcher =
2272 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2273 hasTypedefForAnonDecl(hasName("thing_t")));
2274
2275 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2276 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2277
2278 testImportSequence(
2279 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2280 // Just check that there is only one enum decl in the result AST.
2281 "main.c", enumDecl(), VerificationMatcher);
2282
2283 // For different import order, result should be the same.
2284 testImportSequence(
2285 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2286 // Check that there is only one enum decl in the result AST.
2287 "main.c", enumDecl(), VerificationMatcher);
2288}
2289
Peter Szecsice7f3182018-05-07 12:08:27 +00002290const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2291 dependentScopeDeclRefExpr;
2292
Gabor Marton19f4f392018-06-25 13:04:37 +00002293TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002294 MatchVerifier<Decl> Verifier;
2295 testImport("template <typename T> struct S { static T foo; };"
2296 "template <typename T> void declToImport() {"
2297 " (void) S<T>::foo;"
2298 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002299 "void instantiate() { declToImport<int>(); }"
2300 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002301 Lang_CXX11, "", Lang_CXX11, Verifier,
2302 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2303 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2304
2305 testImport("template <typename T> struct S {"
2306 "template<typename S> static void foo(){};"
2307 "};"
2308 "template <typename T> void declToImport() {"
2309 " S<T>::template foo<T>();"
2310 "}"
2311 "void instantiate() { declToImport<int>(); }",
2312 Lang_CXX11, "", Lang_CXX11, Verifier,
2313 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2314 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2315}
2316
2317const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2318 dependentNameType;
2319
Gabor Marton19f4f392018-06-25 13:04:37 +00002320TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002321 MatchVerifier<Decl> Verifier;
2322 testImport("template <typename T> struct declToImport {"
2323 " typedef typename T::type dependent_name;"
2324 "};",
2325 Lang_CXX11, "", Lang_CXX11, Verifier,
2326 classTemplateDecl(has(
2327 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2328}
2329
2330const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
2331 unresolvedMemberExpr;
2332
Gabor Marton19f4f392018-06-25 13:04:37 +00002333TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002334 MatchVerifier<Decl> Verifier;
2335 testImport("struct S { template <typename T> void mem(); };"
2336 "template <typename U> void declToImport() {"
2337 " S s;"
2338 " s.mem<U>();"
2339 "}"
2340 "void instantiate() { declToImport<int>(); }",
2341 Lang_CXX11, "", Lang_CXX11, Verifier,
2342 functionTemplateDecl(has(functionDecl(has(
2343 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2344}
2345
Balazs Keri1d20cc22018-07-16 12:16:39 +00002346class ImportImplicitMethods : public ASTImporterTestBase {
2347public:
2348 static constexpr auto DefaultCode = R"(
2349 struct A { int x; };
2350 void f() {
2351 A a;
2352 A a1(a);
2353 A a2(A{});
2354 a = a1;
2355 a = A{};
2356 a.~A();
2357 })";
2358
2359 template <typename MatcherType>
2360 void testImportOf(
2361 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2362 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2363 }
2364
2365 template <typename MatcherType>
2366 void testNoImportOf(
2367 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2368 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2369 }
2370
2371private:
2372 template <typename MatcherType>
2373 void test(const MatcherType &MethodMatcher,
2374 const char *Code, unsigned int ExpectedCount) {
2375 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2376
2377 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2378 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2379 ToTU, ClassMatcher);
2380
Balazs Keri2f752ba2018-07-16 14:05:18 +00002381 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002382
2383 {
2384 CXXMethodDecl *Method =
2385 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2386 ToClass->removeDecl(Method);
2387 }
2388
Balazs Keri2f752ba2018-07-16 14:05:18 +00002389 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002390
2391 Decl *ImportedClass = nullptr;
2392 {
2393 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2394 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2395 FromTU, ClassMatcher);
2396 ImportedClass = Import(FromClass, Lang_CXX11);
2397 }
2398
2399 EXPECT_EQ(ToClass, ImportedClass);
2400 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2401 ExpectedCount);
2402 }
2403};
2404
2405TEST_P(ImportImplicitMethods, DefaultConstructor) {
2406 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2407}
2408
2409TEST_P(ImportImplicitMethods, CopyConstructor) {
2410 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2411}
2412
2413TEST_P(ImportImplicitMethods, MoveConstructor) {
2414 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2415}
2416
2417TEST_P(ImportImplicitMethods, Destructor) {
2418 testImportOf(cxxDestructorDecl());
2419}
2420
2421TEST_P(ImportImplicitMethods, CopyAssignment) {
2422 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2423}
2424
2425TEST_P(ImportImplicitMethods, MoveAssignment) {
2426 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2427}
2428
2429TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2430 auto Code = R"(
2431 struct A { A() { int x; } };
2432 )";
2433 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2434}
2435
2436TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2437 auto Code = R"(
2438 struct A { A() = default; };
2439 )";
2440 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2441}
2442
2443TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2444 auto Code = R"(
2445 struct A { A() = delete; };
2446 )";
2447 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2448}
2449
2450TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2451 auto Code = R"(
2452 struct A { void f() { } };
2453 )";
2454 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2455}
2456
Balazs Keric7797c42018-07-11 09:37:24 +00002457TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
2458 Decl *ToR1;
2459 {
2460 Decl *FromTU = getTuDecl(
2461 "struct A { };", Lang_CXX, "input0.cc");
2462 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2463 FromTU, cxxRecordDecl(hasName("A")));
2464
2465 ToR1 = Import(FromR, Lang_CXX);
2466 }
2467
2468 Decl *ToR2;
2469 {
2470 Decl *FromTU = getTuDecl(
2471 "struct A { };", Lang_CXX, "input1.cc");
2472 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2473 FromTU, cxxRecordDecl(hasName("A")));
2474
2475 ToR2 = Import(FromR, Lang_CXX);
2476 }
2477
2478 EXPECT_EQ(ToR1, ToR2);
2479}
2480
2481TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
2482 Decl *ToR1;
2483 {
2484 Decl *FromTU = getTuDecl(
2485 "struct A { int x; };", Lang_CXX, "input0.cc");
2486 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2487 FromTU, cxxRecordDecl(hasName("A")));
2488 ToR1 = Import(FromR, Lang_CXX);
2489 }
2490 Decl *ToR2;
2491 {
2492 Decl *FromTU = getTuDecl(
2493 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2494 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2495 FromTU, cxxRecordDecl(hasName("A")));
2496 ToR2 = Import(FromR, Lang_CXX);
2497 }
2498 EXPECT_NE(ToR1, ToR2);
2499}
2500
2501TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
2502 Decl *ToF1;
2503 {
2504 Decl *FromTU = getTuDecl(
2505 "struct A { int x; };", Lang_CXX, "input0.cc");
2506 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2507 FromTU, fieldDecl(hasName("x")));
2508 ToF1 = Import(FromF, Lang_CXX);
2509 }
2510 Decl *ToF2;
2511 {
2512 Decl *FromTU = getTuDecl(
2513 "struct A { int x; };", Lang_CXX, "input1.cc");
2514 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2515 FromTU, fieldDecl(hasName("x")));
2516 ToF2 = Import(FromF, Lang_CXX);
2517 }
2518 EXPECT_EQ(ToF1, ToF2);
2519}
2520
2521TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
2522 Decl *ToF1;
2523 {
2524 Decl *FromTU = getTuDecl(
2525 "struct A { int x; };", Lang_CXX, "input0.cc");
2526 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2527 FromTU, fieldDecl(hasName("x")));
2528 ToF1 = Import(FromF, Lang_CXX);
2529 }
2530 Decl *ToF2;
2531 {
2532 Decl *FromTU = getTuDecl(
2533 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2534 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2535 FromTU, fieldDecl(hasName("x")));
2536 ToF2 = Import(FromF, Lang_CXX);
2537 }
2538 EXPECT_NE(ToF1, ToF2);
2539}
2540
2541TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
2542 Decl *ToM1;
2543 {
2544 Decl *FromTU = getTuDecl(
2545 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2546 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2547 FromTU, functionDecl(hasName("x"), isDefinition()));
2548 ToM1 = Import(FromM, Lang_CXX);
2549 }
2550 Decl *ToM2;
2551 {
2552 Decl *FromTU = getTuDecl(
2553 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2554 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2555 FromTU, functionDecl(hasName("x"), isDefinition()));
2556 ToM2 = Import(FromM, Lang_CXX);
2557 }
2558 EXPECT_EQ(ToM1, ToM2);
2559}
2560
2561TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
2562 Decl *ToM1;
2563 {
2564 Decl *FromTU = getTuDecl(
2565 "struct A { void x(); }; void A::x() { }",
2566 Lang_CXX, "input0.cc");
2567 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2568 FromTU, functionDecl(hasName("x"), isDefinition()));
2569 ToM1 = Import(FromM, Lang_CXX);
2570 }
2571 Decl *ToM2;
2572 {
2573 Decl *FromTU = getTuDecl(
2574 "struct A { void x() const; }; void A::x() const { }",
2575 Lang_CXX, "input1.cc");
2576 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2577 FromTU, functionDecl(hasName("x"), isDefinition()));
2578 ToM2 = Import(FromM, Lang_CXX);
2579 }
2580 EXPECT_NE(ToM1, ToM2);
2581}
2582
Gabor Marton61d862a2018-05-18 09:08:47 +00002583struct DeclContextTest : ASTImporterTestBase {};
2584
2585TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
2586 Decl *TU = getTuDecl(
2587 R"(
2588 namespace NS {
2589
2590 template <typename T>
2591 struct S {};
2592 template struct S<int>;
2593
2594 inline namespace INS {
2595 template <typename T>
2596 struct S {};
2597 template struct S<int>;
2598 }
2599
2600 }
2601 )", Lang_CXX11, "input0.cc");
2602 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
2603 TU, namespaceDecl());
2604 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2605 TU, classTemplateSpecializationDecl());
2606 ASSERT_TRUE(NS->containsDecl(Spec));
2607
2608 NS->removeDecl(Spec);
2609 EXPECT_FALSE(NS->containsDecl(Spec));
2610}
2611
Gabor Marton5254e642018-06-27 13:32:50 +00002612struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
2613
2614TEST_P(ImportFunctionTemplateSpecializations,
2615 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
2616
2617 Decl *FromTU = getTuDecl(
2618 R"(
2619 template<class T>
2620 int f() { return 0; }
2621 void foo() { f<int>(); }
2622 )",
2623 Lang_CXX, "input0.cc");
2624
2625 // Check that the function template instantiation is NOT the child of the TU.
2626 auto Pattern = translationUnitDecl(
2627 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
2628 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2629
2630 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
2631 FromTU, functionDecl(hasName("foo")));
2632 ASSERT_TRUE(Import(Foo, Lang_CXX));
2633
2634 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2635 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2636}
2637
2638TEST_P(ImportFunctionTemplateSpecializations,
2639 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
2640
2641 Decl *FromTU = getTuDecl(
2642 R"(
2643 template<class T>
2644 int f() { return 0; }
2645 template int f<int>();
2646 )",
2647 Lang_CXX, "input0.cc");
2648
2649 // Check that the function template instantiation is NOT the child of the TU.
2650 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
2651 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
2652 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2653
2654 ASSERT_TRUE(
2655 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
2656
2657 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2658 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2659}
2660
2661TEST_P(ImportFunctionTemplateSpecializations,
2662 TUshouldContainFunctionTemplateSpecialization) {
2663
2664 Decl *FromTU = getTuDecl(
2665 R"(
2666 template<class T>
2667 int f() { return 0; }
2668 template <> int f<int>() { return 4; }
2669 )",
2670 Lang_CXX, "input0.cc");
2671
2672 // Check that the function template specialization is the child of the TU.
2673 auto Specialization =
2674 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2675 auto Pattern = translationUnitDecl(has(Specialization));
2676 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2677
2678 ASSERT_TRUE(
2679 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
2680
2681 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2682 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2683}
2684
2685TEST_P(ImportFunctionTemplateSpecializations,
2686 FunctionTemplateSpecializationRedeclChain) {
2687
2688 Decl *FromTU = getTuDecl(
2689 R"(
2690 template<class T>
2691 int f() { return 0; }
2692 template <> int f<int>() { return 4; }
2693 )",
2694 Lang_CXX, "input0.cc");
2695
2696 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
2697 hasParent(translationUnitDecl()));
2698 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
2699 {
2700 auto *TU = FromTU;
2701 auto *SpecD = FromSpecD;
2702 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2703 TU, functionTemplateDecl());
2704 auto *FirstSpecD = *(TemplateD->spec_begin());
2705 ASSERT_EQ(SpecD, FirstSpecD);
2706 ASSERT_TRUE(SpecD->getPreviousDecl());
2707 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2708 ->doesThisDeclarationHaveABody());
2709 }
2710
2711 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
2712
2713 {
2714 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
2715 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
2716 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2717 TU, functionTemplateDecl());
2718 auto *FirstSpecD = *(TemplateD->spec_begin());
2719 EXPECT_EQ(SpecD, FirstSpecD);
2720 ASSERT_TRUE(SpecD->getPreviousDecl());
2721 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2722 ->doesThisDeclarationHaveABody());
2723 }
2724}
2725
2726TEST_P(ImportFunctionTemplateSpecializations,
2727 MatchNumberOfFunctionTemplateSpecializations) {
2728
2729 Decl *FromTU = getTuDecl(
2730 R"(
2731 template <typename T> constexpr int f() { return 0; }
2732 template <> constexpr int f<int>() { return 4; }
2733 void foo() {
2734 static_assert(f<char>() == 0, "");
2735 static_assert(f<int>() == 4, "");
2736 }
2737 )",
2738 Lang_CXX11, "input0.cc");
2739 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2740 FromTU, functionDecl(hasName("foo")));
2741
2742 Import(FromD, Lang_CXX11);
2743 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2744 EXPECT_EQ(
2745 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
2746 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
2747}
2748
2749TEST_P(ImportFunctionTemplateSpecializations,
2750 ImportPrototypes) {
2751 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2752 auto Code =
2753 R"(
2754 // Proto of the primary template.
2755 template <class T>
2756 void f();
2757 // Proto of the specialization.
2758 template <>
2759 void f<int>();
2760 )";
2761
2762 Decl *ImportedD;
2763 {
2764 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2765 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2766
2767 ImportedD = Import(FromD, Lang_CXX);
2768 }
2769 {
2770 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2771 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2772 Import(FromD, Lang_CXX);
2773 }
2774
2775 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2776
2777 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2778 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2779 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2780 EXPECT_TRUE(ImportedD == To0);
2781 EXPECT_TRUE(ImportedD != To1);
2782 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2783 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2784 // Check that they are part of the same redecl chain.
2785 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
2786}
2787
2788TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
2789 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2790 auto Code =
2791 R"(
2792 // Proto of the primary template.
2793 template <class T>
2794 void f();
2795 // Specialization and definition.
2796 template <>
2797 void f<int>() {}
2798 )";
2799
2800 Decl *ImportedD;
2801 {
2802 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2803 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2804 ImportedD = Import(FromD, Lang_CXX);
2805 }
2806 {
2807 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2808 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2809 Import(FromD, Lang_CXX);
2810 }
2811
2812 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2813
2814 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2815 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2816 EXPECT_TRUE(ImportedD == To0);
2817 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2818
2819 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2820 ToTU, functionTemplateDecl());
2821 auto *FirstSpecD = *(TemplateD->spec_begin());
2822 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
2823}
2824
2825TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
2826 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2827 auto Code =
2828 R"(
2829 // Proto of the primary template.
2830 template <class T>
2831 void f();
2832 // Specialization proto.
2833 template <>
2834 void f<int>();
2835 // Specialization proto.
2836 template <>
2837 void f<int>();
2838 )";
2839
2840 Decl *ImportedD;
2841 {
2842 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2843 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2844 ImportedD = Import(FromD, Lang_CXX);
2845 }
2846
2847 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2848
2849 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2850 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2851 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2852 EXPECT_TRUE(ImportedD == To0);
2853 EXPECT_TRUE(ImportedD != To1);
2854 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2855 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2856 EXPECT_EQ(To1->getPreviousDecl(), To0);
2857}
2858
2859TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
2860 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2861 auto Code =
2862 R"(
2863 // Proto of the primary template.
2864 template <class T>
2865 void f();
2866 // Specialization proto.
2867 template <>
2868 void f<int>();
2869 // Specialization definition.
2870 template <>
2871 void f<int>() {}
2872 )";
2873
2874 Decl *ImportedD;
2875 {
2876 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2877 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2878 ImportedD = Import(FromD, Lang_CXX);
2879 }
2880
2881 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2882
2883 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2884 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2885 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2886 EXPECT_TRUE(ImportedD == To0);
2887 EXPECT_TRUE(ImportedD != To1);
2888 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2889 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2890 EXPECT_EQ(To1->getPreviousDecl(), To0);
2891}
2892
2893TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
2894 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2895 auto Code =
2896 R"(
2897 // Proto of the primary template.
2898 template <class T>
2899 void f();
2900 // Specialization definition.
2901 template <>
2902 void f<int>() {}
2903 // Specialization proto.
2904 template <>
2905 void f<int>();
2906 )";
2907
2908 Decl *ImportedD;
2909 {
2910 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2911 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2912 ImportedD = Import(FromD, Lang_CXX);
2913 }
2914
2915 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2916
2917 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2918 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2919 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2920 EXPECT_TRUE(ImportedD == To0);
2921 EXPECT_TRUE(ImportedD != To1);
2922 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2923 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2924 EXPECT_EQ(To1->getPreviousDecl(), To0);
2925}
2926
Gabor Marton19f4f392018-06-25 13:04:37 +00002927INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
2928 ::testing::Values(ArgVector()), );
2929
Gabor Marton5254e642018-06-27 13:32:50 +00002930INSTANTIATE_TEST_CASE_P(
2931 ParameterizedTests, CanonicalRedeclChain,
2932 ::testing::Values(ArgVector()),);
2933
Gabor Marton19f4f392018-06-25 13:04:37 +00002934auto DefaultTestValuesForRunOptions = ::testing::Values(
2935 ArgVector(),
2936 ArgVector{"-fdelayed-template-parsing"},
2937 ArgVector{"-fms-compatibility"},
2938 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
2939
2940INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
2941 DefaultTestValuesForRunOptions, );
2942
2943INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
2944 DefaultTestValuesForRunOptions, );
2945
2946INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
2947 DefaultTestValuesForRunOptions, );
2948
2949INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
2950 DefaultTestValuesForRunOptions, );
2951
2952INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
2953 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00002954
Gabor Marton5254e642018-06-27 13:32:50 +00002955INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
2956 DefaultTestValuesForRunOptions, );
2957
2958INSTANTIATE_TEST_CASE_P(ParameterizedTests,
2959 ImportFunctionTemplateSpecializations,
2960 DefaultTestValuesForRunOptions, );
2961
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00002962} // end namespace ast_matchers
2963} // end namespace clang