blob: 96a8d43cdf1ce64c3dafb1be9d4fdbddd669cfd6 [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Tests for the correct import of AST nodes from one AST context to another.
11//
12//===----------------------------------------------------------------------===//
13
Aleksei Sidorin8fc85102018-01-26 11:36:54 +000014#include "MatchVerifier.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000015#include "clang/AST/ASTContext.h"
16#include "clang/AST/ASTImporter.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000017#include "clang/ASTMatchers/ASTMatchFinder.h"
18#include "clang/ASTMatchers/ASTMatchers.h"
19#include "clang/Tooling/Tooling.h"
Peter Szecsidedda6f2018-03-30 22:03:29 +000020
21#include "DeclMatcher.h"
Gabor Marton1f667532018-05-24 08:41:07 +000022#include "Language.h"
Gabor Marton5254e642018-06-27 13:32:50 +000023#include "gmock/gmock.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000024#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000025
26namespace clang {
27namespace ast_matchers {
28
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000029using internal::Matcher;
30using internal::BindableMatcher;
31using llvm::StringMap;
32
Peter Szecsidedda6f2018-03-30 22:03:29 +000033// Creates a virtual file and assigns that to the context of given AST. If the
34// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000035static void
36createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
37 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000038 assert(ToAST);
39 ASTContext &ToCtx = ToAST->getASTContext();
40 auto *OFS = static_cast<vfs::OverlayFileSystem *>(
41 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
42 auto *MFS =
43 static_cast<vfs::InMemoryFileSystem *>(OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000044 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000045}
46
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000047static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
48 StringRef Code) {
49 return createVirtualFileIfNeeded(ToAST, FileName,
50 llvm::MemoryBuffer::getMemBuffer(Code));
51}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000052
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000053const StringRef DeclToImportID = "declToImport";
54const StringRef DeclToVerifyID = "declToVerify";
55
Gabor Marton19f4f392018-06-25 13:04:37 +000056// Common base for the different families of ASTImporter tests that are
57// parameterized on the compiler options which may result a different AST. E.g.
58// -fms-compatibility or -fdelayed-template-parsing.
59struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000060
Gabor Marton19f4f392018-06-25 13:04:37 +000061 // Returns the argument vector used for a specific language option, this set
62 // can be tweaked by the test parameters.
63 ArgVector getArgVectorForLanguage(Language Lang) const {
64 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
65 ArgVector ExtraArgs = GetParam();
66 for (const auto &Arg : ExtraArgs) {
67 Args.push_back(Arg);
68 }
69 return Args;
70 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000071
Gabor Marton19f4f392018-06-25 13:04:37 +000072};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000073
Gabor Marton19f4f392018-06-25 13:04:37 +000074// Base class for those tests which use the family of `testImport` functions.
75class TestImportBase : public ParameterizedTestsFixture {
Adam Baloghe4192a82018-06-15 06:45:39 +000076
Gabor Marton19f4f392018-06-25 13:04:37 +000077 template <typename NodeType>
78 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
79 NodeType Node) {
80 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000081
Gabor Marton19f4f392018-06-25 13:04:37 +000082 // Add 'From' file to virtual file system so importer can 'find' it
83 // while importing SourceLocations. It is safe to add same file multiple
84 // times - it just isn't replaced.
85 StringRef FromFileName = From->getMainFileName();
86 createVirtualFileIfNeeded(To, FromFileName,
87 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000088
Gabor Marton19f4f392018-06-25 13:04:37 +000089 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000090
Gabor Marton19f4f392018-06-25 13:04:37 +000091 // This should dump source locations and assert if some source locations
92 // were not imported.
93 SmallString<1024> ImportChecker;
94 llvm::raw_svector_ostream ToNothing(ImportChecker);
95 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000096
Gabor Marton19f4f392018-06-25 13:04:37 +000097 // This traverses the AST to catch certain bugs like poorly or not
98 // implemented subtrees.
99 Imported->dump(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000100
Gabor Marton19f4f392018-06-25 13:04:37 +0000101 return Imported;
102 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000103
Gabor Marton19f4f392018-06-25 13:04:37 +0000104 template <typename NodeType>
105 testing::AssertionResult
106 testImport(const std::string &FromCode, const ArgVector &FromArgs,
107 const std::string &ToCode, const ArgVector &ToArgs,
108 MatchVerifier<NodeType> &Verifier,
109 const BindableMatcher<NodeType> &SearchMatcher,
110 const BindableMatcher<NodeType> &VerificationMatcher) {
111 const char *const InputFileName = "input.cc";
112 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000113
Gabor Marton19f4f392018-06-25 13:04:37 +0000114 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
115 FromCode, FromArgs, InputFileName),
116 ToAST = tooling::buildASTFromCodeWithArgs(
117 ToCode, ToArgs, OutputFileName);
118
119 ASTContext &FromCtx = FromAST->getASTContext(),
120 &ToCtx = ToAST->getASTContext();
121
122 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
123 FromAST->getFileManager(), false);
124
125 auto FoundNodes = match(SearchMatcher, FromCtx);
126 if (FoundNodes.size() != 1)
127 return testing::AssertionFailure()
128 << "Multiple potential nodes were found!";
129
130 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
131 if (!ToImport)
132 return testing::AssertionFailure() << "Node type mismatch!";
133
134 // Sanity check: the node being imported should match in the same way as
135 // the result node.
136 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
137 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
138
139 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
140 if (!Imported)
141 return testing::AssertionFailure() << "Import failed, nullptr returned!";
142
143 return Verifier.match(Imported, WrapperMatcher);
144 }
145
146 template <typename NodeType>
147 testing::AssertionResult
148 testImport(const std::string &FromCode, const ArgVector &FromArgs,
149 const std::string &ToCode, const ArgVector &ToArgs,
150 MatchVerifier<NodeType> &Verifier,
151 const BindableMatcher<NodeType> &VerificationMatcher) {
152 return testImport(
153 FromCode, FromArgs, ToCode, ToArgs, Verifier,
154 translationUnitDecl(
155 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
156 VerificationMatcher);
157 }
158
159public:
160
161 /// Test how AST node named "declToImport" located in the translation unit
162 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
163 /// The verification is done by running AMatcher over the imported node.
164 template <typename NodeType, typename MatcherType>
165 void testImport(const std::string &FromCode, Language FromLang,
166 const std::string &ToCode, Language ToLang,
167 MatchVerifier<NodeType> &Verifier,
168 const MatcherType &AMatcher) {
169 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
170 ToArgs = getArgVectorForLanguage(ToLang);
171 EXPECT_TRUE(
172 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
173 }
174
175 struct ImportAction {
176 StringRef FromFilename;
177 StringRef ToFilename;
178 // FIXME: Generalize this to support other node kinds.
179 BindableMatcher<Decl> ImportPredicate;
180
181 ImportAction(StringRef FromFilename, StringRef ToFilename,
182 DeclarationMatcher ImportPredicate)
183 : FromFilename(FromFilename), ToFilename(ToFilename),
184 ImportPredicate(ImportPredicate) {}
185
186 ImportAction(StringRef FromFilename, StringRef ToFilename,
187 const std::string &DeclName)
188 : FromFilename(FromFilename), ToFilename(ToFilename),
189 ImportPredicate(namedDecl(hasName(DeclName))) {}
190 };
191
192 using SingleASTUnit = std::unique_ptr<ASTUnit>;
193 using AllASTUnits = StringMap<SingleASTUnit>;
194
195 struct CodeEntry {
196 std::string CodeSample;
197 Language Lang;
198 };
199
200 using CodeFiles = StringMap<CodeEntry>;
201
202 /// Builds an ASTUnit for one potential compile options set.
203 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
204 ArgVector Args = getArgVectorForLanguage(CE.Lang);
205 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
206 EXPECT_TRUE(AST.get());
207 return AST;
208 }
209
210 /// Test an arbitrary sequence of imports for a set of given in-memory files.
211 /// The verification is done by running VerificationMatcher against a
212 /// specified AST node inside of one of given files.
213 /// \param CodeSamples Map whose key is the file name and the value is the
214 /// file content.
215 /// \param ImportActions Sequence of imports. Each import in sequence
216 /// specifies "from file" and "to file" and a matcher that is used for
217 /// searching a declaration for import in "from file".
218 /// \param FileForFinalCheck Name of virtual file for which the final check is
219 /// applied.
220 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
221 /// FileForFinalCheck for which the verification will be done.
222 /// \param VerificationMatcher Matcher that will be used for verification
223 /// after all imports in sequence are done.
224 void testImportSequence(const CodeFiles &CodeSamples,
225 const std::vector<ImportAction> &ImportActions,
226 StringRef FileForFinalCheck,
227 BindableMatcher<Decl> FinalSelectPredicate,
228 BindableMatcher<Decl> VerificationMatcher) {
229 AllASTUnits AllASTs;
230 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
231 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
232
233 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
234 if (!AllASTs.count(Filename)) {
235 auto Found = CodeSamples.find(Filename);
236 assert(Found != CodeSamples.end() && "Wrong file for import!");
237 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
238 }
239 };
240
241 for (const ImportAction &Action : ImportActions) {
242 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
243 GenASTsIfNeeded(FromFile);
244 GenASTsIfNeeded(ToFile);
245
246 ASTUnit *From = AllASTs[FromFile].get();
247 ASTUnit *To = AllASTs[ToFile].get();
248
249 // Create a new importer if needed.
250 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
251 if (!ImporterRef)
252 ImporterRef.reset(new ASTImporter(
253 To->getASTContext(), To->getFileManager(), From->getASTContext(),
254 From->getFileManager(), false));
255
256 // Find the declaration and import it.
257 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
258 From->getASTContext());
259 EXPECT_TRUE(FoundDecl.size() == 1);
260 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
261 auto Imported = importNode(From, To, *ImporterRef, ToImport);
262 EXPECT_TRUE(Imported);
263 }
264
265 // Find the declaration and import it.
266 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
267 AllASTs[FileForFinalCheck]->getASTContext());
268 EXPECT_TRUE(FoundDecl.size() == 1);
269 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
270 MatchVerifier<Decl> Verifier;
271 EXPECT_TRUE(
272 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
273 }
274};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000275
Gabor Martonf086fa82018-07-17 12:06:36 +0000276template <typename T> RecordDecl *getRecordDecl(T *D) {
277 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
278 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000279}
Gabor Martonf086fa82018-07-17 12:06:36 +0000280
Peter Szecsidedda6f2018-03-30 22:03:29 +0000281// This class provides generic methods to write tests which can check internal
Balazs Keri21f938c2018-07-02 14:14:07 +0000282// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000283// this fixture makes it possible to import from several "From" contexts.
Gabor Marton19f4f392018-06-25 13:04:37 +0000284class ASTImporterTestBase : public ParameterizedTestsFixture {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000285
286 const char *const InputFileName = "input.cc";
287 const char *const OutputFileName = "output.cc";
288
289 // Buffer for the To context, must live in the test scope.
290 std::string ToCode;
291
Gabor Marton26f72a92018-07-12 09:42:05 +0000292 // Represents a "From" translation unit and holds an importer object which we
293 // use to import from this translation unit.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000294 struct TU {
295 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000296 std::string Code;
297 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000298 std::unique_ptr<ASTUnit> Unit;
299 TranslationUnitDecl *TUDecl = nullptr;
Gabor Marton26f72a92018-07-12 09:42:05 +0000300 std::unique_ptr<ASTImporter> Importer;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000301 TU(StringRef Code, StringRef FileName, ArgVector Args)
302 : Code(Code), FileName(FileName),
303 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
304 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000305 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
306 Unit->enableSourceFileDiagnostics();
307 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000308
Gabor Marton6e1510c2018-07-12 11:50:21 +0000309 void lazyInitImporter(ASTUnit *ToAST) {
Gabor Marton26f72a92018-07-12 09:42:05 +0000310 assert(ToAST);
311 if (!Importer) {
312 Importer.reset(new ASTImporter(
313 ToAST->getASTContext(), ToAST->getFileManager(),
314 Unit->getASTContext(), Unit->getFileManager(), false));
315 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000316 assert(&ToAST->getASTContext() == &Importer->getToContext());
317 createVirtualFileIfNeeded(ToAST, FileName, Code);
318 }
319
320 Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
321 lazyInitImporter(ToAST);
Gabor Marton26f72a92018-07-12 09:42:05 +0000322 return Importer->Import(FromDecl);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000323 }
324
325 QualType import(ASTUnit *ToAST, QualType FromType) {
326 lazyInitImporter(ToAST);
327 return Importer->Import(FromType);
Gabor Marton26f72a92018-07-12 09:42:05 +0000328 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000329 };
330
331 // We may have several From contexts and related translation units. In each
332 // AST, the buffers for the source are handled via references and are set
333 // during the creation of the AST. These references must point to a valid
334 // buffer until the AST is alive. Thus, we must use a list in order to avoid
335 // moving of the stored objects because that would mean breaking the
336 // references in the AST. By using a vector a move could happen when the
337 // vector is expanding, with the list we won't have these issues.
338 std::list<TU> FromTUs;
339
Gabor Marton6e1510c2018-07-12 11:50:21 +0000340 void lazyInitToAST(Language ToLang) {
341 if (ToAST)
342 return;
343 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
344 // Build the AST from an empty file.
345 ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
346 ToAST->enableSourceFileDiagnostics();
347 }
348
349 TU *findFromTU(Decl *From) {
350 // Create a virtual file in the To Ctx which corresponds to the file from
351 // which we want to import the `From` Decl. Without this source locations
352 // will be invalid in the ToCtx.
353 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
354 return E.TUDecl == From->getTranslationUnitDecl();
355 });
356 assert(It != FromTUs.end());
357 return &*It;
358 }
359
Peter Szecsidedda6f2018-03-30 22:03:29 +0000360public:
361 // We may have several From context but only one To context.
362 std::unique_ptr<ASTUnit> ToAST;
363
Peter Szecsidedda6f2018-03-30 22:03:29 +0000364 // Creates an AST both for the From and To source code and imports the Decl
365 // of the identifier into the To context.
366 // Must not be called more than once within the same test.
367 std::tuple<Decl *, Decl *>
368 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
369 Language ToLang, StringRef Identifier = DeclToImportID) {
370 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
371 ToArgs = getArgVectorForLanguage(ToLang);
372
373 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
374 TU &FromTU = FromTUs.back();
375
376 ToCode = ToSrcCode;
377 assert(!ToAST);
378 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000379 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000380
Gabor Marton26f72a92018-07-12 09:42:05 +0000381 ASTContext &FromCtx = FromTU.Unit->getASTContext();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000382
383 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
384
Peter Szecsidedda6f2018-03-30 22:03:29 +0000385 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
386 assert(ImportedII && "Declaration with the given identifier "
387 "should be specified in test!");
388 DeclarationName ImportDeclName(ImportedII);
389 SmallVector<NamedDecl *, 4> FoundDecls;
390 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
391 FoundDecls);
392
393 assert(FoundDecls.size() == 1);
394
Gabor Marton26f72a92018-07-12 09:42:05 +0000395 Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
396
Peter Szecsidedda6f2018-03-30 22:03:29 +0000397 assert(Imported);
398 return std::make_tuple(*FoundDecls.begin(), Imported);
399 }
400
Gabor Marton9581c332018-05-23 13:53:36 +0000401 // Creates a TU decl for the given source code which can be used as a From
402 // context. May be called several times in a given test (with different file
403 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000404 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
405 StringRef FileName = "input.cc") {
406 assert(
407 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
408 return E.FileName == FileName;
409 }) == FromTUs.end());
410
411 ArgVector Args = getArgVectorForLanguage(Lang);
412 FromTUs.emplace_back(SrcCode, FileName, Args);
413 TU &Tu = FromTUs.back();
414
415 return Tu.TUDecl;
416 }
417
Gabor Marton9581c332018-05-23 13:53:36 +0000418 // Creates the To context with the given source code and returns the TU decl.
419 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
420 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
421 ToCode = ToSrcCode;
422 assert(!ToAST);
423 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000424 ToAST->enableSourceFileDiagnostics();
Gabor Marton9581c332018-05-23 13:53:36 +0000425
426 return ToAST->getASTContext().getTranslationUnitDecl();
427 }
428
Peter Szecsidedda6f2018-03-30 22:03:29 +0000429 // Import the given Decl into the ToCtx.
430 // May be called several times in a given test.
431 // The different instances of the param From may have different ASTContext.
432 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000433 lazyInitToAST(ToLang);
434 TU *FromTU = findFromTU(From);
435 return FromTU->import(ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000436 }
437
Gabor Marton6e1510c2018-07-12 11:50:21 +0000438 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
439 lazyInitToAST(ToLang);
440 TU *FromTU = findFromTU(TUDecl);
441 return FromTU->import(ToAST.get(), FromType);
442 }
443
Peter Szecsidedda6f2018-03-30 22:03:29 +0000444 ~ASTImporterTestBase() {
445 if (!::testing::Test::HasFailure()) return;
446
447 for (auto &Tu : FromTUs) {
448 assert(Tu.Unit);
449 llvm::errs() << "FromAST:\n";
450 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
451 llvm::errs() << "\n";
452 }
453 if (ToAST) {
454 llvm::errs() << "ToAST:\n";
455 ToAST->getASTContext().getTranslationUnitDecl()->dump();
456 }
457 }
458};
459
Gabor Marton19f4f392018-06-25 13:04:37 +0000460struct ImportExpr : TestImportBase {};
461struct ImportType : TestImportBase {};
462struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000463
Gabor Marton5254e642018-06-27 13:32:50 +0000464struct CanonicalRedeclChain : ASTImporterTestBase {};
465
466TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
467 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
468 auto Pattern = functionDecl(hasName("f"));
469 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
470
471 auto Redecls = getCanonicalForwardRedeclChain(D0);
472 ASSERT_EQ(Redecls.size(), 1u);
473 EXPECT_EQ(D0, Redecls[0]);
474}
475
476TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
477 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
478 auto Pattern = functionDecl(hasName("f"));
479 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
480 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
481 FunctionDecl *D1 = D2->getPreviousDecl();
482
483 auto Redecls = getCanonicalForwardRedeclChain(D0);
484 ASSERT_EQ(Redecls.size(), 3u);
485 EXPECT_EQ(D0, Redecls[0]);
486 EXPECT_EQ(D1, Redecls[1]);
487 EXPECT_EQ(D2, Redecls[2]);
488}
489
490TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
491 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
492 auto Pattern = functionDecl(hasName("f"));
493 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
494 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
495 FunctionDecl *D1 = D2->getPreviousDecl();
496
497 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
498 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
499 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
500
501 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
502 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
503}
504
505
Gabor Marton19f4f392018-06-25 13:04:37 +0000506TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000507 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000508 testImport(
509 "void declToImport() { (void)\"foo\"; }",
510 Lang_CXX, "", Lang_CXX, Verifier,
511 functionDecl(hasDescendant(
512 stringLiteral(hasType(asString("const char [4]"))))));
513 testImport(
514 "void declToImport() { (void)L\"foo\"; }",
515 Lang_CXX, "", Lang_CXX, Verifier,
516 functionDecl(hasDescendant(
517 stringLiteral(hasType(asString("const wchar_t [4]"))))));
518 testImport(
519 "void declToImport() { (void) \"foo\" \"bar\"; }",
520 Lang_CXX, "", Lang_CXX, Verifier,
521 functionDecl(hasDescendant(
522 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000523}
524
Gabor Marton19f4f392018-06-25 13:04:37 +0000525TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000526 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000527 testImport(
528 "void declToImport() { (void)__null; }",
529 Lang_CXX, "", Lang_CXX, Verifier,
530 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000531}
532
Gabor Marton19f4f392018-06-25 13:04:37 +0000533TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000534 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000535 testImport(
536 "void declToImport() { (void)nullptr; }",
537 Lang_CXX11, "", Lang_CXX11, Verifier,
538 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000539}
540
541
Gabor Marton19f4f392018-06-25 13:04:37 +0000542TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000543 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000544 testImport(
545 "void declToImport() { (void)1.0; }",
546 Lang_C, "", Lang_C, Verifier,
547 functionDecl(hasDescendant(
548 floatLiteral(equals(1.0), hasType(asString("double"))))));
549 testImport(
550 "void declToImport() { (void)1.0e-5f; }",
551 Lang_C, "", Lang_C, Verifier,
552 functionDecl(hasDescendant(
553 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000554}
555
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000556TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
557 MatchVerifier<Decl> Verifier;
558 testImport(
559 "void declToImport() { (void)1.0i; }",
560 Lang_CXX14, "", Lang_CXX14, Verifier,
561 functionDecl(hasDescendant(imaginaryLiteral())));
562}
563
Gabor Marton19f4f392018-06-25 13:04:37 +0000564TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000565 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000566 testImport(
567 "void declToImport() {"
568 " struct s { int x; long y; unsigned z; }; "
569 " (void)(struct s){ 42, 0L, 1U }; }",
570 Lang_CXX, "", Lang_CXX, Verifier,
571 functionDecl(hasDescendant(
572 compoundLiteralExpr(
573 hasType(asString("struct s")),
574 has(initListExpr(
575 hasType(asString("struct s")),
576 has(integerLiteral(
577 equals(42), hasType(asString("int")))),
578 has(integerLiteral(
579 equals(0), hasType(asString("long")))),
580 has(integerLiteral(
581 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000582}
583
Gabor Marton19f4f392018-06-25 13:04:37 +0000584TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000585 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000586 testImport(
587 "class declToImport { void f() { (void)this; } };",
588 Lang_CXX, "", Lang_CXX, Verifier,
589 cxxRecordDecl(
590 hasMethod(
591 hasDescendant(
592 cxxThisExpr(
593 hasType(
594 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000595}
596
Gabor Marton19f4f392018-06-25 13:04:37 +0000597TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000598 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000599 testImport(
600 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
601 Lang_C, "", Lang_C, Verifier,
602 functionDecl(hasDescendant(
603 atomicExpr(
604 has(ignoringParenImpCasts(
605 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
606 hasType(asString("int *"))))),
607 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000608}
609
Gabor Marton19f4f392018-06-25 13:04:37 +0000610TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000611 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000612 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000613 "void declToImport() { loop: goto loop; (void)&&loop; }",
614 Lang_C, "", Lang_C, Verifier,
615 functionDecl(
616 hasDescendant(
617 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
618 hasDescendant(
619 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000620}
621
622AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
623 internal::Matcher<NamedDecl>, InnerMatcher) {
624 const NamedDecl *Template = Node.getTemplatedDecl();
625 return Template && InnerMatcher.matches(*Template, Finder, Builder);
626}
627
Gabor Marton19f4f392018-06-25 13:04:37 +0000628TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000629 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000630 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000631 "template<typename T> class dummy { void f() { dummy X(*this); } };"
632 "typedef dummy<int> declToImport;"
633 "template class dummy<int>;",
634 Lang_CXX, "", Lang_CXX, Verifier,
635 typedefDecl(hasType(templateSpecializationType(
636 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
637 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
638 hasName("f"),
639 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
640 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
641 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000642 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000643}
644
Gabor Marton19f4f392018-06-25 13:04:37 +0000645TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000646 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000647 testImport(
648 "void declToImport() { int b; switch (b) { case 1: break; } }",
649 Lang_C, "", Lang_C, Verifier,
650 functionDecl(hasDescendant(
651 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000652}
653
Gabor Marton19f4f392018-06-25 13:04:37 +0000654TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000655 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000656 testImport(
657 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
658 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000659 functionDecl(hasDescendant(
660 varDecl(
661 hasName("C"),
662 hasType(asString("int")),
663 hasInitializer(
664 stmtExpr(
665 hasAnySubstatement(declStmt(hasSingleDecl(
666 varDecl(
667 hasName("X"),
668 hasType(asString("int")),
669 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000670 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000671 hasDescendant(
672 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000673}
674
Gabor Marton19f4f392018-06-25 13:04:37 +0000675TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000676 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000677 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000678 "void declToImport() { (void)(true ? 1 : -5); }",
679 Lang_CXX, "", Lang_CXX, Verifier,
680 functionDecl(hasDescendant(
681 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000682 hasCondition(cxxBoolLiteral(equals(true))),
683 hasTrueExpression(integerLiteral(equals(1))),
684 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000685 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
686 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000687}
688
Gabor Marton19f4f392018-06-25 13:04:37 +0000689TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000690 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000691 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000692 "void declToImport() { (void)(1 ?: -5); }",
693 Lang_CXX, "", Lang_CXX, Verifier,
694 functionDecl(hasDescendant(
695 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000696 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000697 implicitCastExpr(
698 hasSourceExpression(opaqueValueExpr(
699 hasSourceExpression(integerLiteral(equals(1))))),
700 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000701 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000702 opaqueValueExpr(
703 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000704 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000705 unaryOperator(
706 hasOperatorName("-"),
707 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000708}
709
Gabor Marton19f4f392018-06-25 13:04:37 +0000710TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000711 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000712 testImport(
713 "void declToImport() {"
714 " struct point { double x; double y; };"
715 " struct point ptarray[10] = "
716 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
717 Lang_C, "", Lang_C, Verifier,
718 functionDecl(hasDescendant(
719 initListExpr(
720 has(designatedInitExpr(
721 designatorCountIs(2),
722 has(floatLiteral(equals(1.0))),
723 has(integerLiteral(equals(2))))),
724 has(designatedInitExpr(
725 designatorCountIs(2),
726 has(floatLiteral(equals(2.0))),
727 has(integerLiteral(equals(2))))),
728 has(designatedInitExpr(
729 designatorCountIs(2),
730 has(floatLiteral(equals(1.0))),
731 has(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000732}
733
734
Gabor Marton19f4f392018-06-25 13:04:37 +0000735TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000736 MatchVerifier<Decl> Verifier;
737 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000738 testImport(
739 "void declToImport() { (void)__func__; }",
740 Lang_CXX, "", Lang_CXX, Verifier,
741 functionDecl(hasDescendant(
742 predefinedExpr(
743 hasType(
744 asString("const char [13]")),
745 has(stringLiteral(hasType(
746 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000747}
748
Gabor Marton19f4f392018-06-25 13:04:37 +0000749TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000750 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000751 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000752 "void declToImport() {"
753 " struct point { double x; double y; };"
754 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
755 " [0].x = 1.0 }; }",
756 Lang_CXX, "", Lang_CXX, Verifier,
757 functionDecl(hasDescendant(
758 initListExpr(
759 has(
760 cxxConstructExpr(
761 requiresZeroInitialization())),
762 has(
763 initListExpr(
764 hasType(asString("struct point")),
765 has(floatLiteral(equals(1.0))),
766 has(implicitValueInitExpr(
767 hasType(asString("double")))))),
768 has(
769 initListExpr(
770 hasType(asString("struct point")),
771 has(floatLiteral(equals(2.0))),
772 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000773}
774
775
Aleksei Sidorina693b372016-09-28 10:16:56 +0000776const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
777
Gabor Marton19f4f392018-06-25 13:04:37 +0000778TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000779 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000780 testImport(
781 "void declToImport(__builtin_va_list list, ...) {"
782 " (void)__builtin_va_arg(list, int); }",
783 Lang_CXX, "", Lang_CXX, Verifier,
784 functionDecl(hasDescendant(
785 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000786}
787
Gabor Marton19f4f392018-06-25 13:04:37 +0000788TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000789 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000790 testImport(
791 "struct C {};"
792 "void declToImport() { C c = C(); }",
793 Lang_CXX, "", Lang_CXX, Verifier,
794 functionDecl(hasDescendant(
795 exprWithCleanups(has(cxxConstructExpr(
796 has(materializeTemporaryExpr(has(implicitCastExpr(
797 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000798}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000799
Gabor Marton19f4f392018-06-25 13:04:37 +0000800TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000801 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000802 testImport(
803 "void declToImport() { typedef _Atomic(int) a_int; }",
804 Lang_CXX11, "", Lang_CXX11, Verifier,
805 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000806}
807
Gabor Marton19f4f392018-06-25 13:04:37 +0000808TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000809 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000810 testImport(
811 "template <typename T> void declToImport() { };",
812 Lang_CXX, "", Lang_CXX, Verifier,
813 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000814}
815
Gabor Marton19f4f392018-06-25 13:04:37 +0000816TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000817 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000818 testImport(
819 "template <typename T> struct C { T t; };"
820 "template <typename T> void declToImport() {"
821 " C<T> d;"
822 " (void)d.t;"
823 "}"
824 "void instantiate() { declToImport<int>(); }",
825 Lang_CXX, "", Lang_CXX, Verifier,
826 functionTemplateDecl(hasDescendant(
827 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
828 testImport(
829 "template <typename T> struct C { T t; };"
830 "template <typename T> void declToImport() {"
831 " C<T> d;"
832 " (void)(&d)->t;"
833 "}"
834 "void instantiate() { declToImport<int>(); }",
835 Lang_CXX, "", Lang_CXX, Verifier,
836 functionTemplateDecl(hasDescendant(
837 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000838}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000839
Gabor Marton19f4f392018-06-25 13:04:37 +0000840TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000841 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000842 testImport(
843 "template <int K>"
844 "struct dummy { static const int i = K; };"
845 "template <int K> using dummy2 = dummy<K>;"
846 "int declToImport() { return dummy2<3>::i; }",
847 Lang_CXX11, "", Lang_CXX11, Verifier,
848 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000849 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000850 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
851}
852
853const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
854 varTemplateSpecializationDecl;
855
Gabor Marton19f4f392018-06-25 13:04:37 +0000856TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000857 MatchVerifier<Decl> Verifier;
858 testImport(
859 "template <typename T>"
860 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000861 "void declToImport() { (void)pi<int>; }",
862 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000863 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000864 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000865 unless(hasAncestor(translationUnitDecl(has(varDecl(
866 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000867}
868
Gabor Marton19f4f392018-06-25 13:04:37 +0000869TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000870 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000871 testImport(
872 "template <typename... Args>"
873 "struct dummy {"
874 " dummy(Args... args) {}"
875 " static const int i = 4;"
876 "};"
877 "int declToImport() { return dummy<int>::i; }",
878 Lang_CXX11, "", Lang_CXX11, Verifier,
879 functionDecl(hasDescendant(
880 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000881}
882
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000883const internal::VariadicDynCastAllOfMatcher<Type,
884 DependentTemplateSpecializationType>
885 dependentTemplateSpecializationType;
886
Gabor Marton19f4f392018-06-25 13:04:37 +0000887TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000888 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000889 testImport(
890 "template<typename T>"
891 "struct A;"
892 "template<typename T>"
893 "struct declToImport {"
894 " typename A<T>::template B<T> a;"
895 "};",
896 Lang_CXX, "", Lang_CXX, Verifier,
897 classTemplateDecl(has(cxxRecordDecl(has(
898 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000899}
900
901const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
902 sizeOfPackExpr;
903
Gabor Marton19f4f392018-06-25 13:04:37 +0000904TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000905 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000906 testImport(
907 "template <typename... Ts>"
908 "void declToImport() {"
909 " const int i = sizeof...(Ts);"
910 "};"
911 "void g() { declToImport<int>(); }",
912 Lang_CXX11, "", Lang_CXX11, Verifier,
913 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000914 testImport(
915 "template <typename... Ts>"
916 "using X = int[sizeof...(Ts)];"
917 "template <typename... Us>"
918 "struct Y {"
919 " X<Us..., int, double, int, Us...> f;"
920 "};"
921 "Y<float, int> declToImport;",
922 Lang_CXX11, "", Lang_CXX11, Verifier,
923 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
924 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
925}
926
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000927/// \brief Matches __builtin_types_compatible_p:
928/// GNU extension to check equivalent types
929/// Given
930/// \code
931/// __builtin_types_compatible_p(int, int)
932/// \endcode
933// will generate TypeTraitExpr <...> 'int'
934const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
935
Gabor Marton19f4f392018-06-25 13:04:37 +0000936TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000937 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000938 testImport(
939 "void declToImport() { "
940 " (void)__builtin_types_compatible_p(int, int);"
941 "}",
942 Lang_C, "", Lang_C, Verifier,
943 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000944}
945
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000946const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
947
Gabor Marton19f4f392018-06-25 13:04:37 +0000948TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000949 MatchVerifier<Decl> Verifier;
950 testImport(
951 "namespace std { class type_info {}; }"
952 "void declToImport() {"
953 " int x;"
954 " auto a = typeid(int); auto b = typeid(x);"
955 "}",
956 Lang_CXX11, "", Lang_CXX11, Verifier,
957 functionDecl(
958 hasDescendant(varDecl(
959 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
960 hasDescendant(varDecl(
961 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
962}
963
Gabor Marton19f4f392018-06-25 13:04:37 +0000964TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000965 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000966 testImport(
967 "template<typename T> struct declToImport {"
968 " void m() { (void)__is_pod(T); }"
969 "};"
970 "void f() { declToImport<int>().m(); }",
971 Lang_CXX11, "", Lang_CXX11, Verifier,
972 classTemplateDecl(has(cxxRecordDecl(has(
973 functionDecl(hasDescendant(
974 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000975}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000976
Gabor Marton6e1510c2018-07-12 11:50:21 +0000977TEST_P(ImportDecl, ImportRecordDeclInFunc) {
978 MatchVerifier<Decl> Verifier;
979 testImport("int declToImport() { "
980 " struct data_t {int a;int b;};"
981 " struct data_t d;"
982 " return 0;"
983 "}",
984 Lang_C, "", Lang_C, Verifier,
985 functionDecl(hasBody(compoundStmt(
986 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
987}
988
989TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
990 Decl *FromTU = getTuDecl("int declToImport() { "
991 " struct data_t {int a;int b;};"
992 " struct data_t d;"
993 " return 0;"
994 "}",
995 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +0000996 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +0000997 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
998 ASSERT_TRUE(FromVar);
999 auto ToType =
1000 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
1001 EXPECT_FALSE(ToType.isNull());
1002}
1003
1004TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
1005 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +00001006 Decl *FromTU = getTuDecl(
1007 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1008 Lang_C, "input.c");
1009 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1010 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001011 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001012 auto *To = Import(From, Lang_C);
1013 EXPECT_EQ(To, nullptr);
1014}
1015
1016TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncFromMacro) {
1017 Decl *FromTU = getTuDecl(
1018 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1019 "int declToImport(){ return NONAME_SIZEOF(int); }",
1020 Lang_C, "input.c");
1021 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1022 FromTU, functionDecl(hasName("declToImport")));
1023 ASSERT_TRUE(From);
1024 auto *To = Import(From, Lang_C);
1025 ASSERT_TRUE(To);
1026 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1027 To, functionDecl(hasName("declToImport"),
1028 hasDescendant(unaryExprOrTypeTraitExpr()))));
1029}
1030
1031TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParamsFromMacro) {
1032 // This construct is not supported by ASTImporter.
1033 Decl *FromTU = getTuDecl(
1034 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1035 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1036 Lang_C, "input.c");
1037 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1038 FromTU, functionDecl(hasName("declToImport")));
1039 ASSERT_TRUE(From);
1040 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001041 EXPECT_EQ(To, nullptr);
1042}
1043
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001044const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1045 cxxPseudoDestructorExpr;
1046
Gabor Marton19f4f392018-06-25 13:04:37 +00001047TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001048 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001049 testImport(
1050 "typedef int T;"
1051 "void declToImport(int *p) {"
1052 " T t;"
1053 " p->T::~T();"
1054 "}",
1055 Lang_CXX, "", Lang_CXX, Verifier,
1056 functionDecl(hasDescendant(
1057 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001058}
1059
Gabor Marton19f4f392018-06-25 13:04:37 +00001060TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001061 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001062 testImport(
1063 "namespace foo { int bar; }"
1064 "void declToImport() { using foo::bar; }",
1065 Lang_CXX, "", Lang_CXX, Verifier,
1066 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001067}
1068
1069/// \brief Matches shadow declarations introduced into a scope by a
1070/// (resolved) using declaration.
1071///
1072/// Given
1073/// \code
1074/// namespace n { int f; }
1075/// namespace declToImport { using n::f; }
1076/// \endcode
1077/// usingShadowDecl()
1078/// matches \code f \endcode
1079const internal::VariadicDynCastAllOfMatcher<Decl,
1080 UsingShadowDecl> usingShadowDecl;
1081
Gabor Marton19f4f392018-06-25 13:04:37 +00001082TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001083 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001084 testImport(
1085 "namespace foo { int bar; }"
1086 "namespace declToImport { using foo::bar; }",
1087 Lang_CXX, "", Lang_CXX, Verifier,
1088 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001089}
1090
Gabor Marton19f4f392018-06-25 13:04:37 +00001091TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001092 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001093 testImport(
1094 "template<typename T> int foo();"
1095 "template <typename T> void declToImport() {"
1096 " (void)::foo<T>;"
1097 " (void)::template foo<T>;"
1098 "}"
1099 "void instantiate() { declToImport<int>(); }",
1100 Lang_CXX, "", Lang_CXX, Verifier,
1101 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001102}
1103
Gabor Marton19f4f392018-06-25 13:04:37 +00001104TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001105 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001106 testImport(
1107 "template <typename T> struct C { T t; };"
1108 "template <typename T> void declToImport() {"
1109 " C<T> d;"
1110 " d.t = T();"
1111 "}"
1112 "void instantiate() { declToImport<int>(); }",
1113 Lang_CXX, "", Lang_CXX, Verifier,
1114 functionTemplateDecl(hasDescendant(
1115 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1116 testImport(
1117 "template <typename T> struct C { T t; };"
1118 "template <typename T> void declToImport() {"
1119 " C<T> d;"
1120 " (&d)->t = T();"
1121 "}"
1122 "void instantiate() { declToImport<int>(); }",
1123 Lang_CXX, "", Lang_CXX, Verifier,
1124 functionTemplateDecl(hasDescendant(
1125 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001126}
1127
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001128/// Check that function "declToImport()" (which is the templated function
1129/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1130/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001131TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001132 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001133 testImport(
1134 "template <typename T> void declToImport() { T a = 1; }"
1135 "void instantiate() { declToImport<int>(); }",
1136 Lang_CXX, "", Lang_CXX, Verifier,
1137 functionTemplateDecl(hasAncestor(translationUnitDecl(
1138 unless(has(functionDecl(hasName("declToImport"))))))));
1139 testImport(
1140 "template <typename T> struct declToImport { T t; };"
1141 "void instantiate() { declToImport<int>(); }",
1142 Lang_CXX, "", Lang_CXX, Verifier,
1143 classTemplateDecl(hasAncestor(translationUnitDecl(
1144 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001145}
1146
Gabor Marton19f4f392018-06-25 13:04:37 +00001147TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001148 MatchVerifier<Decl> Verifier;
1149 auto Code =
1150 R"s(
1151 struct declToImport {
1152 template <typename T0> struct X;
1153 template <typename T0> struct X<T0 *> {};
1154 };
1155 )s";
1156 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1157 recordDecl(has(classTemplateDecl()),
1158 has(classTemplateSpecializationDecl())));
1159}
1160
Gabor Marton19f4f392018-06-25 13:04:37 +00001161TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001162 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001163 testImport(
1164 "class declToImport {"
1165 " void f() { *this = declToImport(); }"
1166 "};",
1167 Lang_CXX, "", Lang_CXX, Verifier,
1168 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1169 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001170}
1171
Gabor Marton19f4f392018-06-25 13:04:37 +00001172TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001173 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001174 testImport(
1175 "template<typename T, int Size> class declToImport {"
1176 " T data[Size];"
1177 "};",
1178 Lang_CXX, "", Lang_CXX, Verifier,
1179 classTemplateDecl(has(cxxRecordDecl(
1180 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001181}
1182
Gabor Martona0df7a92018-05-30 09:19:26 +00001183TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1184 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1185 auto From =
1186 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1187 ASSERT_TRUE(From);
1188 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1189 ASSERT_TRUE(To);
1190 Decl *ToTemplated = To->getTemplatedDecl();
1191 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1192 EXPECT_TRUE(ToTemplated1);
1193 EXPECT_EQ(ToTemplated1, ToTemplated);
1194}
1195
Gabor Marton26f72a92018-07-12 09:42:05 +00001196TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001197 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1198 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1199 FromTU, functionTemplateDecl());
1200 ASSERT_TRUE(From);
1201 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1202 ASSERT_TRUE(To);
1203 Decl *ToTemplated = To->getTemplatedDecl();
1204 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1205 EXPECT_TRUE(ToTemplated1);
1206 EXPECT_EQ(ToTemplated1, ToTemplated);
1207}
1208
1209TEST_P(ASTImporterTestBase,
1210 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1211 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1212 auto FromFT =
1213 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1214 ASSERT_TRUE(FromFT);
1215
1216 auto ToTemplated =
1217 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1218 EXPECT_TRUE(ToTemplated);
1219 auto ToTU = ToTemplated->getTranslationUnitDecl();
1220 auto ToFT =
1221 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1222 EXPECT_TRUE(ToFT);
1223}
1224
1225TEST_P(ASTImporterTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001226 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001227 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1228 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1229 FromTU, functionTemplateDecl());
1230 ASSERT_TRUE(FromFT);
1231
1232 auto ToTemplated =
1233 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1234 EXPECT_TRUE(ToTemplated);
1235 auto ToTU = ToTemplated->getTranslationUnitDecl();
1236 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1237 ToTU, functionTemplateDecl());
1238 EXPECT_TRUE(ToFT);
1239}
1240
Gabor Martona0df7a92018-05-30 09:19:26 +00001241TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1242 auto Code =
1243 R"(
1244 namespace x {
1245 template<class X> struct S1{};
1246 template<class X> struct S2{};
1247 template<class X> struct S3{};
1248 }
1249 )";
1250 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1251 auto FromNs =
1252 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1253 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1254 ASSERT_TRUE(ToNs);
1255 auto From =
1256 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1257 classTemplateDecl(
1258 hasName("S2")));
1259 auto To =
1260 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1261 classTemplateDecl(
1262 hasName("S2")));
1263 ASSERT_TRUE(From);
1264 ASSERT_TRUE(To);
1265 auto ToTemplated = To->getTemplatedDecl();
1266 auto ToTemplated1 =
1267 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1268 EXPECT_TRUE(ToTemplated1);
1269 ASSERT_EQ(ToTemplated1, ToTemplated);
1270}
1271
Gabor Marton26f72a92018-07-12 09:42:05 +00001272TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001273 Decl *From, *To;
1274 std::tie(From, To) = getImportedDecl(
1275 R"(
1276 template <typename T> struct X {};
1277
1278 void declToImport(int y, X<int> &x) {}
1279
1280 template <> struct X<int> {
1281 void g() {
1282 X<int> x;
1283 declToImport(0, x);
1284 }
1285 };
1286 )",
1287 Lang_CXX, "", Lang_CXX);
1288
1289 MatchVerifier<Decl> Verifier;
1290 auto Matcher = functionDecl(hasName("declToImport"),
1291 parameterCountIs(2),
1292 hasParameter(0, hasName("y")),
1293 hasParameter(1, hasName("x")),
1294 hasParameter(1, hasType(asString("X<int> &"))));
1295 ASSERT_TRUE(Verifier.match(From, Matcher));
1296 EXPECT_TRUE(Verifier.match(To, Matcher));
1297}
1298
1299TEST_P(ASTImporterTestBase,
1300 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1301 Decl *From, *To;
1302 std::tie(From, To) =
1303 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1304 "void instantiate() { declToImport<int>(); }",
1305 Lang_CXX, "", Lang_CXX);
1306
1307 auto Check = [](Decl *D) -> bool {
1308 auto TU = D->getTranslationUnitDecl();
1309 for (auto Child : TU->decls()) {
1310 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1311 if (FD->getNameAsString() == "declToImport") {
1312 GTEST_NONFATAL_FAILURE_(
1313 "TU should not contain any FunctionDecl with name declToImport");
1314 return false;
1315 }
1316 }
1317 }
1318 return true;
1319 };
1320
1321 ASSERT_TRUE(Check(From));
1322 EXPECT_TRUE(Check(To));
1323}
1324
1325TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1326 Decl *From, *To;
1327 std::tie(From, To) =
1328 getImportedDecl("template <typename T> struct declToImport { T t; };"
1329 "void instantiate() { declToImport<int>(); }",
1330 Lang_CXX, "", Lang_CXX);
1331
1332 auto Check = [](Decl *D) -> bool {
1333 auto TU = D->getTranslationUnitDecl();
1334 for (auto Child : TU->decls()) {
1335 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1336 if (RD->getNameAsString() == "declToImport") {
1337 GTEST_NONFATAL_FAILURE_(
1338 "TU should not contain any CXXRecordDecl with name declToImport");
1339 return false;
1340 }
1341 }
1342 }
1343 return true;
1344 };
1345
1346 ASSERT_TRUE(Check(From));
1347 EXPECT_TRUE(Check(To));
1348}
1349
1350TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1351 Decl *From, *To;
1352 std::tie(From, To) =
1353 getImportedDecl(
1354 "template <typename T> struct X {};"
1355 "template <typename T> using declToImport = X<T>;"
1356 "void instantiate() { declToImport<int> a; }",
1357 Lang_CXX11, "", Lang_CXX11);
1358
1359 auto Check = [](Decl *D) -> bool {
1360 auto TU = D->getTranslationUnitDecl();
1361 for (auto Child : TU->decls()) {
1362 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1363 if (AD->getNameAsString() == "declToImport") {
1364 GTEST_NONFATAL_FAILURE_(
1365 "TU should not contain any TypeAliasDecl with name declToImport");
1366 return false;
1367 }
1368 }
1369 }
1370 return true;
1371 };
1372
1373 ASSERT_TRUE(Check(From));
1374 EXPECT_TRUE(Check(To));
1375}
1376
1377TEST_P(
1378 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001379 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001380
1381 Decl *From, *To;
1382 std::tie(From, To) = getImportedDecl(
1383 R"(
1384 template<class T>
1385 class Base {};
1386 class declToImport : public Base<declToImport> {};
1387 )",
1388 Lang_CXX, "", Lang_CXX);
1389
1390 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1391 auto Pattern =
1392 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1393 ASSERT_TRUE(
1394 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1395 EXPECT_TRUE(
1396 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1397
1398 // Check that the ClassTemplateSpecializationDecl is the child of the
1399 // ClassTemplateDecl.
1400 Pattern = translationUnitDecl(has(classTemplateDecl(
1401 hasName("Base"), has(classTemplateSpecializationDecl()))));
1402 ASSERT_TRUE(
1403 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1404 EXPECT_TRUE(
1405 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1406}
1407
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001408AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1409 size_t Index = 0;
1410 for (FieldDecl *Field : Node.fields()) {
1411 if (Index == Order.size())
1412 return false;
1413 if (Field->getName() != Order[Index])
1414 return false;
1415 ++Index;
1416 }
1417 return Index == Order.size();
1418}
1419
Peter Szecsidedda6f2018-03-30 22:03:29 +00001420TEST_P(ASTImporterTestBase,
1421 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1422 Decl *From, *To;
1423 std::tie(From, To) = getImportedDecl(
1424 R"(
1425 namespace NS {
1426 template<class T>
1427 class X {};
1428 template class X<int>;
1429 }
1430 )",
1431 Lang_CXX, "", Lang_CXX, "NS");
1432
1433 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1434 // ClassTemplateDecl.
1435 auto Pattern = namespaceDecl(has(classTemplateDecl(
1436 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1437 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1438 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1439
1440 // Check that the ClassTemplateSpecializationDecl is the child of the
1441 // NamespaceDecl.
1442 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1443 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1444 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1445}
1446
1447TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1448 Decl *From, *To;
1449 std::tie(From, To) =
1450 getImportedDecl(
1451 "struct declToImport { int a; int b; };",
1452 Lang_CXX11, "", Lang_CXX11);
1453
1454 MatchVerifier<Decl> Verifier;
1455 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1456 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1457}
1458
1459TEST_P(ASTImporterTestBase,
1460 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1461 Decl *From, *To;
1462 std::tie(From, To) = getImportedDecl(
1463 // The original recursive algorithm of ASTImporter first imports 'c' then
1464 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1465 R"s(
1466 struct declToImport {
1467 int a = c + b;
1468 int b = 1;
1469 int c = 2;
1470 };
1471 )s",
1472 Lang_CXX11, "", Lang_CXX11);
1473
1474 MatchVerifier<Decl> Verifier;
1475 ASSERT_TRUE(
1476 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1477 EXPECT_TRUE(
1478 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1479}
1480
Gabor Martonde8bf262018-05-17 09:46:07 +00001481TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001482 Decl *From, *To;
1483 std::tie(From, To) = getImportedDecl(
1484 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001485 struct declToImport {
1486 };
1487 )",
1488 Lang_CXX, "", Lang_CXX);
1489
1490 MatchVerifier<Decl> Verifier;
1491 // Match the implicit Decl.
1492 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1493 ASSERT_TRUE(Verifier.match(From, Matcher));
1494 EXPECT_TRUE(Verifier.match(To, Matcher));
1495}
1496
1497TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1498 Decl *From, *To;
1499 std::tie(From, To) = getImportedDecl(
1500 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001501 template <typename U>
1502 struct declToImport {
1503 };
1504 )",
1505 Lang_CXX, "", Lang_CXX);
1506
1507 MatchVerifier<Decl> Verifier;
1508 // Match the implicit Decl.
1509 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1510 ASSERT_TRUE(Verifier.match(From, Matcher));
1511 EXPECT_TRUE(Verifier.match(To, Matcher));
1512}
1513
1514TEST_P(
1515 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001516 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001517 Decl *From, *To;
1518 std::tie(From, To) = getImportedDecl(
1519 R"(
1520 template<class T>
1521 class Base {};
1522 class declToImport : public Base<declToImport> {};
1523 )",
1524 Lang_CXX, "", Lang_CXX);
1525
1526 auto hasImplicitClass = has(cxxRecordDecl());
1527 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1528 hasName("Base"),
1529 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1530 ASSERT_TRUE(
1531 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1532 EXPECT_TRUE(
1533 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1534}
1535
1536TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1537 Decl *From, *To;
1538 std::tie(From, To) =
1539 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1540
1541 MatchVerifier<Decl> Verifier;
1542 auto Matcher = functionDecl();
1543 ASSERT_TRUE(Verifier.match(From, Matcher));
1544 EXPECT_TRUE(Verifier.match(To, Matcher));
1545 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1546}
1547
Gabor Marton2ae9da32018-05-18 15:46:18 +00001548TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001549 Decl *FromTU = getTuDecl(
1550 R"(
1551 struct X {};
1552 void operator<<(int, X);
1553 )",
1554 Lang_CXX);
1555 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1556 const Decl *To = Import(From, Lang_CXX);
1557 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1558}
1559
1560TEST_P(ASTImporterTestBase,
1561 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1562 Decl *From, *To;
1563 std::tie(From, To) = getImportedDecl(
1564 R"(
1565 template<class T>
1566 class Base { int a; };
1567 class declToImport : Base<declToImport> {};
1568 )",
1569 Lang_CXX, "", Lang_CXX);
1570
1571 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1572 hasName("Base"),
1573 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1574 ASSERT_TRUE(
1575 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1576 EXPECT_TRUE(
1577 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1578}
1579
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001580TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1581 {
1582 Decl *FromTU = getTuDecl(
1583 R"(
1584 template <typename T>
1585 struct B;
1586 )",
1587 Lang_CXX, "input0.cc");
1588 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1589 FromTU, classTemplateDecl(hasName("B")));
1590
1591 Import(FromD, Lang_CXX);
1592 }
1593
1594 {
1595 Decl *FromTU = getTuDecl(
1596 R"(
1597 template <typename T>
1598 struct B {
1599 void f();
1600 };
1601 )",
1602 Lang_CXX, "input1.cc");
1603 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1604 FromTU, functionDecl(hasName("f")));
1605 Import(FromD, Lang_CXX);
1606 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1607 FromTU, classTemplateDecl(hasName("B")));
1608 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1609 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1610 }
1611}
1612
Gabor Marton9581c332018-05-23 13:53:36 +00001613TEST_P(ASTImporterTestBase,
1614 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1615 Decl *ToTU = getToTuDecl(
1616 R"(
1617 template <typename T>
1618 struct B {
1619 void f();
1620 };
1621
1622 template <typename T>
1623 struct B;
1624 )",
1625 Lang_CXX);
1626 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1627 [](const ClassTemplateDecl *T) {
1628 return T->isThisDeclarationADefinition();
1629 })
1630 .match(ToTU, classTemplateDecl()));
1631
1632 Decl *FromTU = getTuDecl(
1633 R"(
1634 template <typename T>
1635 struct B {
1636 void f();
1637 };
1638 )",
1639 Lang_CXX, "input1.cc");
1640 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1641 FromTU, classTemplateDecl(hasName("B")));
1642
1643 Import(FromD, Lang_CXX);
1644
1645 // We should have only one definition.
1646 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1647 [](const ClassTemplateDecl *T) {
1648 return T->isThisDeclarationADefinition();
1649 })
1650 .match(ToTU, classTemplateDecl()));
1651}
1652
1653TEST_P(ASTImporterTestBase,
1654 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1655 Decl *ToTU = getToTuDecl(
1656 R"(
1657 struct B {
1658 void f();
1659 };
1660
1661 struct B;
1662 )",
1663 Lang_CXX);
1664 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001665 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001666
1667 Decl *FromTU = getTuDecl(
1668 R"(
1669 struct B {
1670 void f();
1671 };
1672 )",
1673 Lang_CXX, "input1.cc");
1674 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1675 FromTU, cxxRecordDecl(hasName("B")));
1676
1677 Import(FromD, Lang_CXX);
1678
1679 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001680 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001681}
1682
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001683static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1684 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1685 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1686 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1687 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1688}
1689static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1690 SourceManager &SM1, SourceManager &SM2) {
1691 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1692 FullSourceLoc{ Range2.getBegin(), SM2 });
1693 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1694 FullSourceLoc{ Range2.getEnd(), SM2 });
1695}
1696TEST_P(ASTImporterTestBase, ImportSourceLocs) {
1697 Decl *FromTU = getTuDecl(
1698 R"(
1699 #define MFOO(arg) arg = arg + 1
1700
1701 void foo() {
1702 int a = 5;
1703 MFOO(a);
1704 }
1705 )",
1706 Lang_CXX);
1707 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1708 auto ToD = Import(FromD, Lang_CXX);
1709
1710 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1711 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1712 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1713 auto FromRHS =
1714 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1715
1716 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1717 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1718 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1719 FromSM);
1720 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1721 FromSM);
1722 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1723 FromSM);
1724}
1725
Rafael Stahla0010472018-07-09 08:40:17 +00001726TEST_P(ASTImporterTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001727 Decl *FromTU = getTuDecl(
1728 R"(
1729 #define FUNC_INT void declToImport
1730 #define FUNC FUNC_INT
1731 FUNC(int a);
1732 )",
1733 Lang_CXX);
1734 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1735 auto ToD = Import(FromD, Lang_CXX);
1736
1737 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1738 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1739 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1740 FromSM);
1741}
1742
Gabor Marton9581c332018-05-23 13:53:36 +00001743TEST_P(
1744 ASTImporterTestBase,
1745 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1746{
1747 Decl *ToTU = getToTuDecl(
1748 R"(
1749 template <typename T>
1750 struct B;
1751
1752 template <>
1753 struct B<int> {};
1754
1755 template <>
1756 struct B<int>;
1757 )",
1758 Lang_CXX);
1759 // We should have only one definition.
1760 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1761 [](const ClassTemplateSpecializationDecl *T) {
1762 return T->isThisDeclarationADefinition();
1763 })
1764 .match(ToTU, classTemplateSpecializationDecl()));
1765
1766 Decl *FromTU = getTuDecl(
1767 R"(
1768 template <typename T>
1769 struct B;
1770
1771 template <>
1772 struct B<int> {};
1773 )",
1774 Lang_CXX, "input1.cc");
1775 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1776 FromTU, classTemplateSpecializationDecl(hasName("B")));
1777
1778 Import(FromD, Lang_CXX);
1779
1780 // We should have only one definition.
1781 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1782 [](const ClassTemplateSpecializationDecl *T) {
1783 return T->isThisDeclarationADefinition();
1784 })
1785 .match(ToTU, classTemplateSpecializationDecl()));
1786}
1787
Gabor Marton0bebf952018-07-05 09:51:13 +00001788TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
1789 Decl *FromTU = getTuDecl(
1790 R"(
1791 struct { int a; int b; } object0 = { 2, 3 };
1792 struct { int x; int y; int z; } object1;
1793 )",
1794 Lang_CXX, "input0.cc");
1795
Gabor Marton0bebf952018-07-05 09:51:13 +00001796 auto *Obj0 =
1797 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1798 auto *From0 = getRecordDecl(Obj0);
1799 auto *Obj1 =
1800 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1801 auto *From1 = getRecordDecl(Obj1);
1802
1803 auto *To0 = Import(From0, Lang_CXX);
1804 auto *To1 = Import(From1, Lang_CXX);
1805
1806 EXPECT_TRUE(To0);
1807 EXPECT_TRUE(To1);
1808 EXPECT_NE(To0, To1);
1809 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1810}
1811
Gabor Marton26f72a92018-07-12 09:42:05 +00001812TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
1813 auto Pattern = varDecl(hasName("x"));
1814 VarDecl *Imported1;
1815 {
1816 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1817 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1818 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1819 }
1820 VarDecl *Imported2;
1821 {
1822 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1823 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1824 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1825 }
1826 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1827 EXPECT_FALSE(Imported2->isUsed(false));
1828 {
1829 Decl *FromTU =
1830 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
1831 auto *FromD =
1832 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1833 Import(FromD, Lang_CXX);
1834 }
1835 EXPECT_TRUE(Imported2->isUsed(false));
1836}
1837
1838TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
1839 auto Pattern = varDecl(hasName("x"));
1840
1841 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1842 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1843
1844 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1845
1846 ASSERT_FALSE(Imported1->isUsed(false));
1847
1848 FromD->setIsUsed();
1849 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1850
1851 EXPECT_EQ(Imported1, Imported2);
1852 EXPECT_TRUE(Imported2->isUsed(false));
1853}
1854
Peter Szecsidedda6f2018-03-30 22:03:29 +00001855struct ImportFunctions : ASTImporterTestBase {};
1856
1857TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001858 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1859 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1860 auto Pattern = functionDecl(hasName("f"));
1861 FunctionDecl *FromD = // Definition
1862 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1863
1864 Decl *ImportedD = Import(FromD, Lang_CXX);
1865 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1866
Gabor Marton5254e642018-06-27 13:32:50 +00001867 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001868 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1869}
1870
1871TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1872 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1873 auto Pattern = functionDecl(hasName("f"));
1874 FunctionDecl *FromD =
1875 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1876
1877 Decl *ImportedD = Import(FromD, Lang_CXX);
1878 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1879
1880 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1881 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1882}
1883
Gabor Marton5254e642018-06-27 13:32:50 +00001884TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001885 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1886 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001887 auto *From =
1888 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001889
Gabor Marton5254e642018-06-27 13:32:50 +00001890 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001891 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1892
Gabor Marton5254e642018-06-27 13:32:50 +00001893 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1894 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1895 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1896 EXPECT_TRUE(ImportedD == To0);
1897 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1898 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1899 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001900}
1901
1902TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1903 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1904 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001905 auto *From =
1906 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001907
Gabor Marton5254e642018-06-27 13:32:50 +00001908 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001909 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1910
Gabor Marton5254e642018-06-27 13:32:50 +00001911 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1912 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1913 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1914 EXPECT_TRUE(ImportedD == To1);
1915 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1916 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1917 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001918}
1919
1920TEST_P(ImportFunctions, ImportPrototypes) {
1921 auto Pattern = functionDecl(hasName("f"));
1922
1923 Decl *ImportedD;
1924 {
1925 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001926 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001927
1928 ImportedD = Import(FromD, Lang_CXX);
1929 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001930 {
1931 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001932 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1933 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001934 }
1935
Gabor Marton5254e642018-06-27 13:32:50 +00001936 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1937
1938 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1939 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1940 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1941 EXPECT_TRUE(ImportedD == To0);
1942 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1943 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1944 EXPECT_EQ(To1->getPreviousDecl(), To0);
1945}
1946
1947TEST_P(ImportFunctions, ImportDefinitions) {
1948 auto Pattern = functionDecl(hasName("f"));
1949
1950 Decl *ImportedD;
1951 {
1952 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1953 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1954 ImportedD = Import(FromD, Lang_CXX);
1955 }
1956 {
1957 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
1958 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1959 Import(FromD, Lang_CXX);
1960 }
1961
1962 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1963
Peter Szecsidedda6f2018-03-30 22:03:29 +00001964 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00001965 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1966 EXPECT_TRUE(ImportedD == To0);
1967 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001968}
1969
1970TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1971 auto Pattern = functionDecl(hasName("f"));
1972
1973 Decl *ImportedD;
1974 {
1975 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001976 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001977 ImportedD = Import(FromD, Lang_CXX);
1978 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001979 {
1980 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001981 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1982 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001983 }
1984
1985 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001986
1987 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1988 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1989 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1990 EXPECT_TRUE(ImportedD == To0);
1991 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
1992 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1993 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001994}
1995
1996TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1997 auto Pattern = functionDecl(hasName("f"));
1998
1999 {
2000 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
2001 FunctionDecl *FromD =
2002 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2003
2004 Import(FromD, Lang_CXX);
2005 }
2006 {
2007 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
2008 FunctionDecl *FromD =
2009 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2010 Import(FromD, Lang_CXX);
2011 }
2012
2013 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2014 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2015 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002016 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002017 FunctionDecl *DefinitionD =
2018 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2019 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
2020 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
2021}
2022
Gabor Marton5254e642018-06-27 13:32:50 +00002023TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002024 auto Pattern = functionDecl(hasName("f"));
2025
2026 {
2027 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002028 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002029 Import(FromD, Lang_CXX);
2030 }
2031 {
2032 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002033 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002034 Import(FromD, Lang_CXX);
2035 }
2036
2037 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002038
2039 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002040 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002041 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
2042
Peter Szecsidedda6f2018-03-30 22:03:29 +00002043 FunctionDecl *DefinitionD =
2044 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2045 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00002046
2047 EXPECT_TRUE(DefinitionD->getPreviousDecl());
2048 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
2049 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002050}
2051
2052TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2053 auto Code =
2054 R"(
2055 struct B { virtual void f(); };
2056 void B::f() {}
2057 struct D : B { void f(); };
2058 )";
2059 auto Pattern =
2060 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2061 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2062 CXXMethodDecl *Proto =
2063 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2064
2065 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2066 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2067 EXPECT_EQ(To->size_overridden_methods(), 1u);
2068}
2069
2070TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2071 auto Code =
2072 R"(
2073 struct B { virtual void f(); };
2074 void B::f() {}
2075 )";
2076 auto Pattern =
2077 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2078 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2079 CXXMethodDecl *Proto =
2080 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2081 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2082
2083 ASSERT_TRUE(Proto->isVirtual());
2084 ASSERT_TRUE(Def->isVirtual());
2085 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2086 EXPECT_TRUE(To->isVirtual());
2087}
2088
Gabor Marton5254e642018-06-27 13:32:50 +00002089TEST_P(ImportFunctions,
2090 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2091 Decl *ToTU = getToTuDecl(
2092 R"(
2093 void f() {}
2094 void f();
2095 )",
2096 Lang_CXX);
2097 ASSERT_EQ(1u,
2098 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2099 return FD->doesThisDeclarationHaveABody();
2100 }).match(ToTU, functionDecl()));
2101
2102 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2103 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2104
2105 Import(FromD, Lang_CXX);
2106
2107 EXPECT_EQ(1u,
2108 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2109 return FD->doesThisDeclarationHaveABody();
2110 }).match(ToTU, functionDecl()));
2111}
2112
2113struct ImportFriendFunctions : ImportFunctions {};
2114
2115TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2116 auto Pattern = functionDecl(hasName("f"));
2117
2118 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2119 "void f();",
2120 Lang_CXX,
2121 "input0.cc");
2122 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2123
2124 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2125 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2126 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2127 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2128 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2129 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2130 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2131}
2132
2133TEST_P(ImportFriendFunctions,
2134 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2135 auto Pattern = functionDecl(hasName("f"));
2136
2137 Decl *FromTU = getTuDecl("void f();"
2138 "struct X { friend void f(); };",
2139 Lang_CXX, "input0.cc");
2140 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2141
2142 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2143 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2144 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2145 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2146 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2147 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2148 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2149}
2150
2151TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2152 auto Pattern = functionDecl(hasName("f"));
2153
2154 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2155 "void f();",
2156 Lang_CXX,
2157 "input0.cc");
2158 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2159
2160 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2161 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2162 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2163 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2164 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2165 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2166 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2167}
2168
2169TEST_P(ImportFriendFunctions,
2170 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2171 auto Pattern = functionDecl(hasName("f"));
2172
2173 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2174 "void f(){}",
2175 Lang_CXX, "input0.cc");
2176 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2177
2178 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2179 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2180 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2181 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2182 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2183 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2184 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
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,
2192 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2193 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 = FirstDeclMatcher<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_TRUE(ImportedD->doesThisDeclarationHaveABody());
2210 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2211 .match(ToTU, friendDecl())
2212 ->getFriendDecl());
2213 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2214 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2215 // The parameters must refer the same type
2216 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2217 (*ImportedD->param_begin())->getOriginalType());
2218}
2219
Gabor Marton26f72a92018-07-12 09:42:05 +00002220// Disabled temporarily, because the new structural equivalence check
2221// (https://reviews.llvm.org/D48628) breaks it.
2222// PreviousDecl is not set because there is no structural match.
2223// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002224TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002225 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002226 auto Pattern = functionDecl(hasName("f"));
2227
2228 Decl *FromTU = getTuDecl(
2229 R"(
2230 class X;
2231 void f(X *x){}
2232 class X{
2233 friend void f(X *x);
2234 };
2235 )",
2236 Lang_CXX, "input0.cc");
2237 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2238
2239 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2240 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2241 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2242 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2243 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2244 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2245
2246 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2247 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2248 // The parameters must refer the same type
2249 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2250 (*ImportedD->param_begin())->getOriginalType());
2251}
2252
2253TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2254 auto Pattern = functionDecl(hasName("f"));
2255
2256 FunctionDecl *ImportedD;
2257 {
2258 Decl *FromTU =
2259 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2260 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2261 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2262 }
2263 FunctionDecl *ImportedD1;
2264 {
2265 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2266 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2267 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2268 }
2269
2270 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2271 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2272 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2273 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2274 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2275}
2276
Balazs Keri89632b82018-08-21 14:32:21 +00002277TEST_P(ImportFriendFunctions, Lookup) {
2278 auto FunctionPattern = functionDecl(hasName("f"));
2279 auto ClassPattern = cxxRecordDecl(hasName("X"));
2280
2281 TranslationUnitDecl *FromTU =
2282 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2283 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2284 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2285 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2286 {
2287 auto FromName = FromD->getDeclName();
2288 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2289 auto LookupRes = Class->noload_lookup(FromName);
2290 ASSERT_EQ(LookupRes.size(), 0u);
2291 LookupRes = FromTU->noload_lookup(FromName);
2292 ASSERT_EQ(LookupRes.size(), 1u);
2293 }
2294
2295 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2296 auto ToName = ToD->getDeclName();
2297
2298 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2299 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2300 auto LookupRes = Class->noload_lookup(ToName);
2301 EXPECT_EQ(LookupRes.size(), 0u);
2302 LookupRes = ToTU->noload_lookup(ToName);
2303 EXPECT_EQ(LookupRes.size(), 1u);
2304
2305 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2306 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2307 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2308 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2309}
2310
2311TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2312 auto FunctionPattern = functionDecl(hasName("f"));
2313 auto ClassPattern = cxxRecordDecl(hasName("X"));
2314
2315 TranslationUnitDecl *FromTU = getTuDecl(
2316 "struct X { friend void f(); };"
2317 // This proto decl makes f available to normal
2318 // lookup, otherwise it is hidden.
2319 // Normal C++ lookup (implemented in
2320 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2321 // returns the found `NamedDecl` only if the set IDNS is matched
2322 "void f();",
2323 Lang_CXX, "input0.cc");
2324 auto *FromFriend =
2325 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2326 auto *FromNormal =
2327 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2328 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2329 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2330 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2331 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2332
2333 auto FromName = FromFriend->getDeclName();
2334 auto *FromClass =
2335 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2336 auto LookupRes = FromClass->noload_lookup(FromName);
2337 ASSERT_EQ(LookupRes.size(), 0u);
2338 LookupRes = FromTU->noload_lookup(FromName);
2339 ASSERT_EQ(LookupRes.size(), 1u);
2340
2341 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2342 auto ToName = ToFriend->getDeclName();
2343
2344 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2345 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2346 LookupRes = ToClass->noload_lookup(ToName);
2347 EXPECT_EQ(LookupRes.size(), 0u);
2348 LookupRes = ToTU->noload_lookup(ToName);
2349 // Test is disabled because this result is 2.
2350 EXPECT_EQ(LookupRes.size(), 1u);
2351
2352 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2353 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2354 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2355 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2356 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2357 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2358 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2359}
2360
2361TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2362 auto FunctionPattern = functionDecl(hasName("f"));
2363 auto ClassPattern = cxxRecordDecl(hasName("X"));
2364
2365 TranslationUnitDecl *FromTU = getTuDecl(
2366 "void f();"
2367 "struct X { friend void f(); };",
2368 Lang_CXX, "input0.cc");
2369 auto *FromNormal =
2370 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2371 auto *FromFriend =
2372 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2373 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2374 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2375 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2376 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2377
2378 auto FromName = FromNormal->getDeclName();
2379 auto *FromClass =
2380 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2381 auto LookupRes = FromClass->noload_lookup(FromName);
2382 ASSERT_EQ(LookupRes.size(), 0u);
2383 LookupRes = FromTU->noload_lookup(FromName);
2384 ASSERT_EQ(LookupRes.size(), 1u);
2385
2386 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2387 auto ToName = ToNormal->getDeclName();
2388 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2389
2390 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2391 LookupRes = ToClass->noload_lookup(ToName);
2392 EXPECT_EQ(LookupRes.size(), 0u);
2393 LookupRes = ToTU->noload_lookup(ToName);
2394 EXPECT_EQ(LookupRes.size(), 1u);
2395
2396 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2397 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2398 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2399 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2400 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2401 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2402 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2403}
2404
2405TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2406 auto Pattern = functionDecl(hasName("f"));
2407
2408 TranslationUnitDecl *FromNormalTU =
2409 getTuDecl("void f();", Lang_CXX, "input0.cc");
2410 auto *FromNormalF =
2411 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2412 TranslationUnitDecl *FromFriendTU =
2413 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2414 auto *FromFriendF =
2415 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2416 auto FromNormalName = FromNormalF->getDeclName();
2417 auto FromFriendName = FromFriendF->getDeclName();
2418
2419 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2420 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2421 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2422 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2423 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2424 ASSERT_EQ(LookupRes.size(), 1u);
2425 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2426 ASSERT_EQ(LookupRes.size(), 1u);
2427
2428 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2429 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2430 auto ToName = ToNormalF->getDeclName();
2431 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2432 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2433 LookupRes = ToTU->noload_lookup(ToName);
2434 EXPECT_EQ(LookupRes.size(), 1u);
2435 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2436
2437 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2438 LookupRes = ToTU->noload_lookup(ToName);
2439 EXPECT_EQ(LookupRes.size(), 1u);
2440 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2441
2442 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2443 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2444
2445 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2446 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2447}
2448
2449TEST_P(ImportFriendFunctions, ImportFriendList) {
2450 TranslationUnitDecl *FromTU = getTuDecl(
2451 "struct X { friend void f(); };"
2452 "void f();",
2453 Lang_CXX, "input0.cc");
2454 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2455 FromTU, functionDecl(hasName("f")));
2456
2457 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2458 FromTU, cxxRecordDecl(hasName("X")));
2459 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2460 auto FromFriends = FromClass->friends();
2461 unsigned int FrN = 0;
2462 for (auto Fr : FromFriends) {
2463 ASSERT_EQ(Fr, FromFriend);
2464 ++FrN;
2465 }
2466 ASSERT_EQ(FrN, 1u);
2467
2468 Import(FromFriendF, Lang_CXX);
2469 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2470 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2471 ToTU, cxxRecordDecl(hasName("X")));
2472 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2473 auto ToFriends = ToClass->friends();
2474 FrN = 0;
2475 for (auto Fr : ToFriends) {
2476 EXPECT_EQ(Fr, ToFriend);
2477 ++FrN;
2478 }
2479 EXPECT_EQ(FrN, 1u);
2480}
2481
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002482AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2483 InnerMatcher) {
2484 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2485 return InnerMatcher.matches(*Typedef, Finder, Builder);
2486 return false;
2487}
2488
Gabor Marton19f4f392018-06-25 13:04:37 +00002489TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002490 CodeFiles Samples{{"main.c",
2491 {"void foo();"
2492 "void moo();"
2493 "int main() { foo(); moo(); }",
2494 Lang_C}},
2495
2496 {"foo.c",
2497 {"typedef enum { THING_VALUE } thing_t;"
2498 "void conflict(thing_t type);"
2499 "void foo() { (void)THING_VALUE; }"
2500 "void conflict(thing_t type) {}",
2501 Lang_C}},
2502
2503 {"moo.c",
2504 {"typedef enum { THING_VALUE } thing_t;"
2505 "void conflict(thing_t type);"
2506 "void moo() { conflict(THING_VALUE); }",
2507 Lang_C}}};
2508
2509 auto VerificationMatcher =
2510 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2511 hasTypedefForAnonDecl(hasName("thing_t")));
2512
2513 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2514 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2515
2516 testImportSequence(
2517 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2518 // Just check that there is only one enum decl in the result AST.
2519 "main.c", enumDecl(), VerificationMatcher);
2520
2521 // For different import order, result should be the same.
2522 testImportSequence(
2523 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2524 // Check that there is only one enum decl in the result AST.
2525 "main.c", enumDecl(), VerificationMatcher);
2526}
2527
Peter Szecsice7f3182018-05-07 12:08:27 +00002528const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2529 dependentScopeDeclRefExpr;
2530
Gabor Marton19f4f392018-06-25 13:04:37 +00002531TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002532 MatchVerifier<Decl> Verifier;
2533 testImport("template <typename T> struct S { static T foo; };"
2534 "template <typename T> void declToImport() {"
2535 " (void) S<T>::foo;"
2536 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002537 "void instantiate() { declToImport<int>(); }"
2538 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002539 Lang_CXX11, "", Lang_CXX11, Verifier,
2540 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2541 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2542
2543 testImport("template <typename T> struct S {"
2544 "template<typename S> static void foo(){};"
2545 "};"
2546 "template <typename T> void declToImport() {"
2547 " S<T>::template foo<T>();"
2548 "}"
2549 "void instantiate() { declToImport<int>(); }",
2550 Lang_CXX11, "", Lang_CXX11, Verifier,
2551 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2552 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2553}
2554
2555const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2556 dependentNameType;
2557
Gabor Marton19f4f392018-06-25 13:04:37 +00002558TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002559 MatchVerifier<Decl> Verifier;
2560 testImport("template <typename T> struct declToImport {"
2561 " typedef typename T::type dependent_name;"
2562 "};",
2563 Lang_CXX11, "", Lang_CXX11, Verifier,
2564 classTemplateDecl(has(
2565 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2566}
2567
Gabor Marton19f4f392018-06-25 13:04:37 +00002568TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002569 MatchVerifier<Decl> Verifier;
2570 testImport("struct S { template <typename T> void mem(); };"
2571 "template <typename U> void declToImport() {"
2572 " S s;"
2573 " s.mem<U>();"
2574 "}"
2575 "void instantiate() { declToImport<int>(); }",
2576 Lang_CXX11, "", Lang_CXX11, Verifier,
2577 functionTemplateDecl(has(functionDecl(has(
2578 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2579}
2580
Balazs Keri1d20cc22018-07-16 12:16:39 +00002581class ImportImplicitMethods : public ASTImporterTestBase {
2582public:
2583 static constexpr auto DefaultCode = R"(
2584 struct A { int x; };
2585 void f() {
2586 A a;
2587 A a1(a);
2588 A a2(A{});
2589 a = a1;
2590 a = A{};
2591 a.~A();
2592 })";
2593
2594 template <typename MatcherType>
2595 void testImportOf(
2596 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2597 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2598 }
2599
2600 template <typename MatcherType>
2601 void testNoImportOf(
2602 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2603 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2604 }
2605
2606private:
2607 template <typename MatcherType>
2608 void test(const MatcherType &MethodMatcher,
2609 const char *Code, unsigned int ExpectedCount) {
2610 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2611
2612 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2613 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2614 ToTU, ClassMatcher);
2615
Balazs Keri2f752ba2018-07-16 14:05:18 +00002616 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002617
2618 {
2619 CXXMethodDecl *Method =
2620 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2621 ToClass->removeDecl(Method);
2622 }
2623
Balazs Keri2f752ba2018-07-16 14:05:18 +00002624 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002625
2626 Decl *ImportedClass = nullptr;
2627 {
2628 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2629 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2630 FromTU, ClassMatcher);
2631 ImportedClass = Import(FromClass, Lang_CXX11);
2632 }
2633
2634 EXPECT_EQ(ToClass, ImportedClass);
2635 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2636 ExpectedCount);
2637 }
2638};
2639
2640TEST_P(ImportImplicitMethods, DefaultConstructor) {
2641 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2642}
2643
2644TEST_P(ImportImplicitMethods, CopyConstructor) {
2645 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2646}
2647
2648TEST_P(ImportImplicitMethods, MoveConstructor) {
2649 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2650}
2651
2652TEST_P(ImportImplicitMethods, Destructor) {
2653 testImportOf(cxxDestructorDecl());
2654}
2655
2656TEST_P(ImportImplicitMethods, CopyAssignment) {
2657 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2658}
2659
2660TEST_P(ImportImplicitMethods, MoveAssignment) {
2661 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2662}
2663
2664TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2665 auto Code = R"(
2666 struct A { A() { int x; } };
2667 )";
2668 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2669}
2670
2671TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2672 auto Code = R"(
2673 struct A { A() = default; };
2674 )";
2675 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2676}
2677
2678TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2679 auto Code = R"(
2680 struct A { A() = delete; };
2681 )";
2682 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2683}
2684
2685TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2686 auto Code = R"(
2687 struct A { void f() { } };
2688 )";
2689 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2690}
2691
Balazs Keric7797c42018-07-11 09:37:24 +00002692TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
2693 Decl *ToR1;
2694 {
2695 Decl *FromTU = getTuDecl(
2696 "struct A { };", Lang_CXX, "input0.cc");
2697 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2698 FromTU, cxxRecordDecl(hasName("A")));
2699
2700 ToR1 = Import(FromR, Lang_CXX);
2701 }
2702
2703 Decl *ToR2;
2704 {
2705 Decl *FromTU = getTuDecl(
2706 "struct A { };", Lang_CXX, "input1.cc");
2707 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2708 FromTU, cxxRecordDecl(hasName("A")));
2709
2710 ToR2 = Import(FromR, Lang_CXX);
2711 }
2712
2713 EXPECT_EQ(ToR1, ToR2);
2714}
2715
2716TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
2717 Decl *ToR1;
2718 {
2719 Decl *FromTU = getTuDecl(
2720 "struct A { int x; };", Lang_CXX, "input0.cc");
2721 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2722 FromTU, cxxRecordDecl(hasName("A")));
2723 ToR1 = Import(FromR, Lang_CXX);
2724 }
2725 Decl *ToR2;
2726 {
2727 Decl *FromTU = getTuDecl(
2728 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2729 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2730 FromTU, cxxRecordDecl(hasName("A")));
2731 ToR2 = Import(FromR, Lang_CXX);
2732 }
2733 EXPECT_NE(ToR1, ToR2);
2734}
2735
2736TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
2737 Decl *ToF1;
2738 {
2739 Decl *FromTU = getTuDecl(
2740 "struct A { int x; };", Lang_CXX, "input0.cc");
2741 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2742 FromTU, fieldDecl(hasName("x")));
2743 ToF1 = Import(FromF, Lang_CXX);
2744 }
2745 Decl *ToF2;
2746 {
2747 Decl *FromTU = getTuDecl(
2748 "struct A { int x; };", Lang_CXX, "input1.cc");
2749 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2750 FromTU, fieldDecl(hasName("x")));
2751 ToF2 = Import(FromF, Lang_CXX);
2752 }
2753 EXPECT_EQ(ToF1, ToF2);
2754}
2755
2756TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
2757 Decl *ToF1;
2758 {
2759 Decl *FromTU = getTuDecl(
2760 "struct A { int x; };", Lang_CXX, "input0.cc");
2761 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2762 FromTU, fieldDecl(hasName("x")));
2763 ToF1 = Import(FromF, Lang_CXX);
2764 }
2765 Decl *ToF2;
2766 {
2767 Decl *FromTU = getTuDecl(
2768 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2769 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2770 FromTU, fieldDecl(hasName("x")));
2771 ToF2 = Import(FromF, Lang_CXX);
2772 }
2773 EXPECT_NE(ToF1, ToF2);
2774}
2775
2776TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
2777 Decl *ToM1;
2778 {
2779 Decl *FromTU = getTuDecl(
2780 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2781 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2782 FromTU, functionDecl(hasName("x"), isDefinition()));
2783 ToM1 = Import(FromM, Lang_CXX);
2784 }
2785 Decl *ToM2;
2786 {
2787 Decl *FromTU = getTuDecl(
2788 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2789 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2790 FromTU, functionDecl(hasName("x"), isDefinition()));
2791 ToM2 = Import(FromM, Lang_CXX);
2792 }
2793 EXPECT_EQ(ToM1, ToM2);
2794}
2795
2796TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
2797 Decl *ToM1;
2798 {
2799 Decl *FromTU = getTuDecl(
2800 "struct A { void x(); }; void A::x() { }",
2801 Lang_CXX, "input0.cc");
2802 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2803 FromTU, functionDecl(hasName("x"), isDefinition()));
2804 ToM1 = Import(FromM, Lang_CXX);
2805 }
2806 Decl *ToM2;
2807 {
2808 Decl *FromTU = getTuDecl(
2809 "struct A { void x() const; }; void A::x() const { }",
2810 Lang_CXX, "input1.cc");
2811 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2812 FromTU, functionDecl(hasName("x"), isDefinition()));
2813 ToM2 = Import(FromM, Lang_CXX);
2814 }
2815 EXPECT_NE(ToM1, ToM2);
2816}
2817
Gabor Martonf086fa82018-07-17 12:06:36 +00002818TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
2819 Decl *FromTU = getTuDecl(
2820 R"(
2821 struct A {
2822 struct {
2823 struct A *next;
2824 } entry0;
2825 struct {
2826 struct A *next;
2827 } entry1;
2828 };
2829 )",
2830 Lang_C, "input0.cc");
2831 auto *From =
2832 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
2833
2834 Import(From, Lang_C);
2835
2836 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2837 auto *Entry0 =
2838 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
2839 auto *Entry1 =
2840 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
2841 auto *R0 = getRecordDecl(Entry0);
2842 auto *R1 = getRecordDecl(Entry1);
2843 EXPECT_NE(R0, R1);
2844 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2845 R0, recordDecl(has(fieldDecl(hasName("next"))))));
2846 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2847 R1, recordDecl(has(fieldDecl(hasName("next"))))));
2848}
2849
Balazs Keri2544b4b2018-08-08 09:40:57 +00002850TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
2851 Decl *FromTU = getTuDecl(
2852 R"(
2853 void f(int X, int Y, bool Z) {
2854 (void)[X, Y, Z] { (void)Z; };
2855 }
2856 )",
2857 Lang_CXX11, "input0.cc");
2858 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
2859 FromTU, functionDecl(hasName("f")));
2860 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
2861 EXPECT_TRUE(ToF);
2862
2863 CXXRecordDecl *FromLambda =
2864 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
2865 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
2866
2867 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
2868 EXPECT_TRUE(ToLambda);
2869
2870 // Check if the fields of the lambda class are imported in correct order.
2871 unsigned FromIndex = 0u;
2872 for (auto *FromField : FromLambda->fields()) {
2873 ASSERT_FALSE(FromField->getDeclName());
2874 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
2875 EXPECT_TRUE(ToField);
2876 unsigned ToIndex = ASTImporter::getFieldIndex(ToField);
2877 EXPECT_EQ(ToIndex, FromIndex + 1);
2878 ++FromIndex;
2879 }
2880
2881 EXPECT_EQ(FromIndex, 3u);
2882}
2883
Balazs Keri0c23dc52018-08-13 13:08:37 +00002884TEST_P(
2885 ASTImporterTestBase,
2886 ImportOfFriendRecordDoesNotMergeDefinition) {
2887 Decl *FromTU = getTuDecl(
2888 R"(
2889 class A {
2890 template <int I> class F {};
2891 class X {
2892 template <int I> friend class F;
2893 };
2894 };
2895 )",
2896 Lang_CXX, "input0.cc");
2897
2898 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2899 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
2900 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
2901 FromTU, cxxRecordDecl(hasName("F")));
2902
2903 ASSERT_TRUE(FromClass);
2904 ASSERT_TRUE(FromFriendClass);
2905 ASSERT_NE(FromClass, FromFriendClass);
2906 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
2907 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
2908 ASSERT_EQ(
2909 FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
2910 FromClass->getDescribedClassTemplate());
2911
2912 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
2913 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
2914
2915 EXPECT_TRUE(ToClass);
2916 EXPECT_TRUE(ToFriendClass);
2917 EXPECT_NE(ToClass, ToFriendClass);
2918 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
2919 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
2920 EXPECT_EQ(
2921 ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
2922 ToClass->getDescribedClassTemplate());
2923}
2924
2925TEST_P(
2926 ASTImporterTestBase,
2927 ImportOfRecursiveFriendClass) {
2928 Decl *FromTu = getTuDecl(
2929 R"(
2930 class declToImport {
2931 friend class declToImport;
2932 };
2933 )",
2934 Lang_CXX, "input.cc");
2935
2936 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
2937 FromTu, cxxRecordDecl(hasName("declToImport")));
2938 auto *ToD = Import(FromD, Lang_CXX);
2939 auto Pattern = cxxRecordDecl(hasName("declToImport"), has(friendDecl()));
2940 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
2941 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
2942}
2943
2944TEST_P(
2945 ASTImporterTestBase,
2946 ImportOfRecursiveFriendClassTemplate) {
2947 Decl *FromTu = getTuDecl(
2948 R"(
2949 template <class A> class declToImport {
2950 template <class A1> friend class declToImport;
2951 };
2952 )",
2953 Lang_CXX, "input.cc");
2954
2955 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
2956 FromTu, classTemplateDecl(hasName("declToImport")));
2957 auto *ToD = Import(FromD, Lang_CXX);
Gabor Marton42e15de2018-08-22 11:52:14 +00002958
Balazs Keri0c23dc52018-08-13 13:08:37 +00002959 auto Pattern = classTemplateDecl(
2960 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
2961 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
2962 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
Gabor Marton42e15de2018-08-22 11:52:14 +00002963
Balazs Keri0c23dc52018-08-13 13:08:37 +00002964 auto *Class =
2965 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
2966 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
2967 EXPECT_NE(Friend->getFriendDecl(), Class);
2968 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
2969}
2970
Gabor Marton42e15de2018-08-22 11:52:14 +00002971TEST_P(ASTImporterTestBase, MergeFieldDeclsOfClassTemplateSpecialization) {
2972 std::string ClassTemplate =
2973 R"(
2974 template <typename T>
2975 struct X {
2976 int a{0}; // FieldDecl with InitListExpr
2977 X(char) : a(3) {} // (1)
2978 X(int) {} // (2)
2979 };
2980 )";
2981 Decl *ToTU = getToTuDecl(ClassTemplate +
2982 R"(
2983 void foo() {
2984 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
2985 X<char> xc('c');
2986 }
2987 )", Lang_CXX11);
2988 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2989 ToTU, classTemplateSpecializationDecl(hasName("X")));
2990 // FieldDecl without InitlistExpr:
2991 auto *ToField = *ToSpec->field_begin();
2992 ASSERT_TRUE(ToField);
2993 ASSERT_FALSE(ToField->getInClassInitializer());
2994 Decl *FromTU = getTuDecl(ClassTemplate +
2995 R"(
2996 void bar() {
2997 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
2998 X<char> xc(1);
2999 }
3000 )", Lang_CXX11);
3001 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3002 FromTU, classTemplateSpecializationDecl(hasName("X")));
3003 // FieldDecl with InitlistExpr:
3004 auto *FromField = *FromSpec->field_begin();
3005 ASSERT_TRUE(FromField);
3006 ASSERT_TRUE(FromField->getInClassInitializer());
3007
3008 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3009 ASSERT_TRUE(ImportedSpec);
3010 EXPECT_EQ(ImportedSpec, ToSpec);
3011 // After the import, the FieldDecl has to be merged, thus it should have the
3012 // InitListExpr.
3013 EXPECT_TRUE(ToField->getInClassInitializer());
3014}
3015
3016TEST_P(ASTImporterTestBase, MergeFunctionOfClassTemplateSpecialization) {
3017 std::string ClassTemplate =
3018 R"(
3019 template <typename T>
3020 struct X {
3021 void f() {}
3022 void g() {}
3023 };
3024 )";
3025 Decl *ToTU = getToTuDecl(ClassTemplate +
3026 R"(
3027 void foo() {
3028 X<char> x;
3029 x.f();
3030 }
3031 )", Lang_CXX11);
3032 Decl *FromTU = getTuDecl(ClassTemplate +
3033 R"(
3034 void bar() {
3035 X<char> x;
3036 x.g();
3037 }
3038 )", Lang_CXX11);
3039 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3040 FromTU, classTemplateSpecializationDecl(hasName("X")));
3041 auto FunPattern = functionDecl(hasName("g"),
3042 hasParent(classTemplateSpecializationDecl()));
3043 auto *FromFun =
3044 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3045 auto *ToFun =
3046 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3047 ASSERT_TRUE(FromFun->hasBody());
3048 ASSERT_FALSE(ToFun->hasBody());
3049 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3050 ASSERT_TRUE(ImportedSpec);
3051 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3052 ToTU, classTemplateSpecializationDecl(hasName("X")));
3053 EXPECT_EQ(ImportedSpec, ToSpec);
3054 EXPECT_TRUE(ToFun->hasBody());
3055}
3056
3057TEST_P(ASTImporterTestBase,
3058 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3059 std::string ClassTemplate =
3060 R"(
3061 template <typename T>
3062 struct X {};
3063 )";
3064 Decl *ToTU = getToTuDecl(ClassTemplate +
3065 R"(
3066 template <>
3067 struct X<char> {
3068 int a;
3069 };
3070 void foo() {
3071 X<char> x;
3072 }
3073 )",
3074 Lang_CXX11);
3075 Decl *FromTU = getTuDecl(ClassTemplate +
3076 R"(
3077 template <>
3078 struct X<char> {
3079 int b;
3080 };
3081 void foo() {
3082 X<char> x;
3083 }
3084 )",
3085 Lang_CXX11);
3086 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3087 FromTU, classTemplateSpecializationDecl(hasName("X")));
3088 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3089
3090 // We expect one (ODR) warning during the import.
3091 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3092
3093 // The second specialization is different from the first, thus it violates
3094 // ODR, consequently we expect to keep the first specialization only, which is
3095 // already in the "To" context.
3096 EXPECT_TRUE(ImportedSpec);
3097 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3098 ToTU, classTemplateSpecializationDecl(hasName("X")));
3099 EXPECT_EQ(ImportedSpec, ToSpec);
3100 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3101 ToTU, classTemplateSpecializationDecl()));
3102}
3103
3104TEST_P(ASTImporterTestBase, MergeCtorOfClassTemplateSpecialization) {
3105 std::string ClassTemplate =
3106 R"(
3107 template <typename T>
3108 struct X {
3109 X(char) {}
3110 X(int) {}
3111 };
3112 )";
3113 Decl *ToTU = getToTuDecl(ClassTemplate +
3114 R"(
3115 void foo() {
3116 X<char> x('c');
3117 }
3118 )", Lang_CXX11);
3119 Decl *FromTU = getTuDecl(ClassTemplate +
3120 R"(
3121 void bar() {
3122 X<char> x(1);
3123 }
3124 )", Lang_CXX11);
3125 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3126 FromTU, classTemplateSpecializationDecl(hasName("X")));
3127 // Match the void(int) ctor.
3128 auto CtorPattern =
3129 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3130 hasParent(classTemplateSpecializationDecl()));
3131 auto *FromCtor =
3132 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3133 auto *ToCtor =
3134 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3135 ASSERT_TRUE(FromCtor->hasBody());
3136 ASSERT_FALSE(ToCtor->hasBody());
3137 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3138 ASSERT_TRUE(ImportedSpec);
3139 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3140 ToTU, classTemplateSpecializationDecl(hasName("X")));
3141 EXPECT_EQ(ImportedSpec, ToSpec);
3142 EXPECT_TRUE(ToCtor->hasBody());
3143}
3144
3145TEST_P(ASTImporterTestBase,
3146 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3147 auto Code =
3148 R"(
3149 // primary template
3150 template<class T1, class T2, int I>
3151 class A {};
3152
3153 // partial specialization
3154 template<class T, int I>
3155 class A<T, T*, I> {};
3156 )";
3157 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3158 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3159 auto *FromSpec =
3160 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3161 FromTU, classTemplatePartialSpecializationDecl());
3162 auto *ToSpec =
3163 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3164 ToTU, classTemplatePartialSpecializationDecl());
3165
3166 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3167 EXPECT_EQ(ImportedSpec, ToSpec);
3168 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3169 ToTU, classTemplatePartialSpecializationDecl()));
3170}
3171
3172TEST_P(ASTImporterTestBase, ClassTemplateSpecializationsShouldNotBeDuplicated) {
3173 auto Code =
3174 R"(
3175 // primary template
3176 template<class T1, class T2, int I>
3177 class A {};
3178
3179 // full specialization
3180 template<>
3181 class A<int, int, 1> {};
3182 )";
3183 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3184 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3185 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3186 FromTU, classTemplateSpecializationDecl());
3187 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3188 ToTU, classTemplateSpecializationDecl());
3189
3190 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3191 EXPECT_EQ(ImportedSpec, ToSpec);
3192 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3193 ToTU, classTemplateSpecializationDecl()));
3194}
3195
3196TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3197 std::string PrimaryTemplate =
3198 R"(
3199 template<class T1, class T2, int I>
3200 class A {};
3201 )";
3202 auto PartialSpec =
3203 R"(
3204 template<class T, int I>
3205 class A<T, T*, I> {};
3206 )";
3207 auto FullSpec =
3208 R"(
3209 template<>
3210 class A<int, int, 1> {};
3211 )";
3212 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3213 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3214 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3215 FromTU, classTemplateSpecializationDecl());
3216
3217 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3218 EXPECT_TRUE(ImportedSpec);
3219 // Check the number of partial specializations.
3220 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3221 ToTU, classTemplatePartialSpecializationDecl()));
3222 // Check the number of full specializations.
3223 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3224 ToTU, classTemplateSpecializationDecl(
3225 unless(classTemplatePartialSpecializationDecl()))));
3226}
3227
Gabor Martona20ce602018-09-03 13:10:53 +00003228TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
3229 Decl *TU = getTuDecl(
3230 R"(
3231 const int &init();
3232 void foo() { const int &a{init()}; }
3233 )", Lang_CXX11, "input0.cc");
3234 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3235 ASSERT_TRUE(FromD->getAnyInitializer());
3236 auto *InitExpr = FromD->getAnyInitializer();
3237 ASSERT_TRUE(InitExpr);
3238 ASSERT_TRUE(InitExpr->isGLValue());
3239
3240 auto *ToD = Import(FromD, Lang_CXX11);
3241 EXPECT_TRUE(ToD);
3242 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3243 EXPECT_TRUE(ToInitExpr);
3244 EXPECT_TRUE(ToInitExpr->isGLValue());
3245}
3246
Gabor Marton61d862a2018-05-18 09:08:47 +00003247struct DeclContextTest : ASTImporterTestBase {};
3248
3249TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3250 Decl *TU = getTuDecl(
3251 R"(
3252 namespace NS {
3253
3254 template <typename T>
3255 struct S {};
3256 template struct S<int>;
3257
3258 inline namespace INS {
3259 template <typename T>
3260 struct S {};
3261 template struct S<int>;
3262 }
3263
3264 }
3265 )", Lang_CXX11, "input0.cc");
3266 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
3267 TU, namespaceDecl());
3268 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3269 TU, classTemplateSpecializationDecl());
3270 ASSERT_TRUE(NS->containsDecl(Spec));
3271
3272 NS->removeDecl(Spec);
3273 EXPECT_FALSE(NS->containsDecl(Spec));
3274}
3275
Gabor Marton5254e642018-06-27 13:32:50 +00003276struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
3277
3278TEST_P(ImportFunctionTemplateSpecializations,
3279 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
3280
3281 Decl *FromTU = getTuDecl(
3282 R"(
3283 template<class T>
3284 int f() { return 0; }
3285 void foo() { f<int>(); }
3286 )",
3287 Lang_CXX, "input0.cc");
3288
3289 // Check that the function template instantiation is NOT the child of the TU.
3290 auto Pattern = translationUnitDecl(
3291 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
3292 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3293
3294 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
3295 FromTU, functionDecl(hasName("foo")));
3296 ASSERT_TRUE(Import(Foo, Lang_CXX));
3297
3298 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3299 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3300}
3301
3302TEST_P(ImportFunctionTemplateSpecializations,
3303 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
3304
3305 Decl *FromTU = getTuDecl(
3306 R"(
3307 template<class T>
3308 int f() { return 0; }
3309 template int f<int>();
3310 )",
3311 Lang_CXX, "input0.cc");
3312
3313 // Check that the function template instantiation is NOT the child of the TU.
3314 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
3315 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
3316 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3317
3318 ASSERT_TRUE(
3319 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
3320
3321 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3322 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3323}
3324
3325TEST_P(ImportFunctionTemplateSpecializations,
3326 TUshouldContainFunctionTemplateSpecialization) {
3327
3328 Decl *FromTU = getTuDecl(
3329 R"(
3330 template<class T>
3331 int f() { return 0; }
3332 template <> int f<int>() { return 4; }
3333 )",
3334 Lang_CXX, "input0.cc");
3335
3336 // Check that the function template specialization is the child of the TU.
3337 auto Specialization =
3338 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3339 auto Pattern = translationUnitDecl(has(Specialization));
3340 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3341
3342 ASSERT_TRUE(
3343 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
3344
3345 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3346 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3347}
3348
3349TEST_P(ImportFunctionTemplateSpecializations,
3350 FunctionTemplateSpecializationRedeclChain) {
3351
3352 Decl *FromTU = getTuDecl(
3353 R"(
3354 template<class T>
3355 int f() { return 0; }
3356 template <> int f<int>() { return 4; }
3357 )",
3358 Lang_CXX, "input0.cc");
3359
3360 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
3361 hasParent(translationUnitDecl()));
3362 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
3363 {
3364 auto *TU = FromTU;
3365 auto *SpecD = FromSpecD;
3366 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3367 TU, functionTemplateDecl());
3368 auto *FirstSpecD = *(TemplateD->spec_begin());
3369 ASSERT_EQ(SpecD, FirstSpecD);
3370 ASSERT_TRUE(SpecD->getPreviousDecl());
3371 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3372 ->doesThisDeclarationHaveABody());
3373 }
3374
3375 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
3376
3377 {
3378 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
3379 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
3380 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3381 TU, functionTemplateDecl());
3382 auto *FirstSpecD = *(TemplateD->spec_begin());
3383 EXPECT_EQ(SpecD, FirstSpecD);
3384 ASSERT_TRUE(SpecD->getPreviousDecl());
3385 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3386 ->doesThisDeclarationHaveABody());
3387 }
3388}
3389
3390TEST_P(ImportFunctionTemplateSpecializations,
3391 MatchNumberOfFunctionTemplateSpecializations) {
3392
3393 Decl *FromTU = getTuDecl(
3394 R"(
3395 template <typename T> constexpr int f() { return 0; }
3396 template <> constexpr int f<int>() { return 4; }
3397 void foo() {
3398 static_assert(f<char>() == 0, "");
3399 static_assert(f<int>() == 4, "");
3400 }
3401 )",
3402 Lang_CXX11, "input0.cc");
3403 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
3404 FromTU, functionDecl(hasName("foo")));
3405
3406 Import(FromD, Lang_CXX11);
3407 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3408 EXPECT_EQ(
3409 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
3410 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
3411}
3412
3413TEST_P(ImportFunctionTemplateSpecializations,
3414 ImportPrototypes) {
3415 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3416 auto Code =
3417 R"(
3418 // Proto of the primary template.
3419 template <class T>
3420 void f();
3421 // Proto of the specialization.
3422 template <>
3423 void f<int>();
3424 )";
3425
3426 Decl *ImportedD;
3427 {
3428 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3429 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3430
3431 ImportedD = Import(FromD, Lang_CXX);
3432 }
3433 {
3434 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
3435 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3436 Import(FromD, Lang_CXX);
3437 }
3438
3439 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3440
3441 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3442 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3443 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3444 EXPECT_TRUE(ImportedD == To0);
3445 EXPECT_TRUE(ImportedD != To1);
3446 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
3447 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3448 // Check that they are part of the same redecl chain.
3449 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
3450}
3451
3452TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
3453 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3454 auto Code =
3455 R"(
3456 // Proto of the primary template.
3457 template <class T>
3458 void f();
3459 // Specialization and definition.
3460 template <>
3461 void f<int>() {}
3462 )";
3463
3464 Decl *ImportedD;
3465 {
3466 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3467 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3468 ImportedD = Import(FromD, Lang_CXX);
3469 }
3470 {
3471 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
3472 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3473 Import(FromD, Lang_CXX);
3474 }
3475
3476 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3477
3478 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
3479 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3480 EXPECT_TRUE(ImportedD == To0);
3481 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
3482
3483 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3484 ToTU, functionTemplateDecl());
3485 auto *FirstSpecD = *(TemplateD->spec_begin());
3486 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
3487}
3488
3489TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
3490 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3491 auto Code =
3492 R"(
3493 // Proto of the primary template.
3494 template <class T>
3495 void f();
3496 // Specialization proto.
3497 template <>
3498 void f<int>();
3499 // Specialization proto.
3500 template <>
3501 void f<int>();
3502 )";
3503
3504 Decl *ImportedD;
3505 {
3506 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3507 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3508 ImportedD = Import(FromD, Lang_CXX);
3509 }
3510
3511 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3512
3513 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3514 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3515 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3516 EXPECT_TRUE(ImportedD == To0);
3517 EXPECT_TRUE(ImportedD != To1);
3518 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
3519 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3520 EXPECT_EQ(To1->getPreviousDecl(), To0);
3521}
3522
3523TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
3524 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3525 auto Code =
3526 R"(
3527 // Proto of the primary template.
3528 template <class T>
3529 void f();
3530 // Specialization proto.
3531 template <>
3532 void f<int>();
3533 // Specialization definition.
3534 template <>
3535 void f<int>() {}
3536 )";
3537
3538 Decl *ImportedD;
3539 {
3540 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3541 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3542 ImportedD = Import(FromD, Lang_CXX);
3543 }
3544
3545 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3546
3547 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3548 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3549 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3550 EXPECT_TRUE(ImportedD == To0);
3551 EXPECT_TRUE(ImportedD != To1);
3552 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
3553 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
3554 EXPECT_EQ(To1->getPreviousDecl(), To0);
3555}
3556
3557TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
3558 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3559 auto Code =
3560 R"(
3561 // Proto of the primary template.
3562 template <class T>
3563 void f();
3564 // Specialization definition.
3565 template <>
3566 void f<int>() {}
3567 // Specialization proto.
3568 template <>
3569 void f<int>();
3570 )";
3571
3572 Decl *ImportedD;
3573 {
3574 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3575 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3576 ImportedD = Import(FromD, Lang_CXX);
3577 }
3578
3579 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3580
3581 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3582 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3583 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3584 EXPECT_TRUE(ImportedD == To0);
3585 EXPECT_TRUE(ImportedD != To1);
3586 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
3587 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3588 EXPECT_EQ(To1->getPreviousDecl(), To0);
3589}
3590
Gabor Marton19f4f392018-06-25 13:04:37 +00003591INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
3592 ::testing::Values(ArgVector()), );
3593
Gabor Marton5254e642018-06-27 13:32:50 +00003594INSTANTIATE_TEST_CASE_P(
3595 ParameterizedTests, CanonicalRedeclChain,
3596 ::testing::Values(ArgVector()),);
3597
Gabor Marton19f4f392018-06-25 13:04:37 +00003598auto DefaultTestValuesForRunOptions = ::testing::Values(
3599 ArgVector(),
3600 ArgVector{"-fdelayed-template-parsing"},
3601 ArgVector{"-fms-compatibility"},
3602 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
3603
3604INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
3605 DefaultTestValuesForRunOptions, );
3606
3607INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
3608 DefaultTestValuesForRunOptions, );
3609
3610INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
3611 DefaultTestValuesForRunOptions, );
3612
3613INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
3614 DefaultTestValuesForRunOptions, );
3615
3616INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
3617 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00003618
Gabor Marton5254e642018-06-27 13:32:50 +00003619INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
3620 DefaultTestValuesForRunOptions, );
3621
3622INSTANTIATE_TEST_CASE_P(ParameterizedTests,
3623 ImportFunctionTemplateSpecializations,
3624 DefaultTestValuesForRunOptions, );
3625
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00003626} // end namespace ast_matchers
3627} // end namespace clang