blob: 366ff7f0e08a5f93a7e36b1a029246d0a9a11c87 [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");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001831 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1832 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001833 Import(FromD, Lang_CXX);
1834 }
1835 EXPECT_TRUE(Imported2->isUsed(false));
1836}
1837
Gabor Martonac3a5d62018-09-17 12:04:52 +00001838TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag2) {
1839 auto Pattern = varDecl(hasName("x"));
1840 VarDecl *ExistingD;
1841 {
1842 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1843 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1844 }
1845 EXPECT_FALSE(ExistingD->isUsed(false));
1846 {
1847 Decl *FromTU = getTuDecl(
1848 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1849 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1850 FromTU, functionDecl(hasName("f")));
1851 Import(FromD, Lang_CXX);
1852 }
1853 EXPECT_TRUE(ExistingD->isUsed(false));
1854}
1855
1856TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag3) {
1857 auto Pattern = varDecl(hasName("a"));
1858 VarDecl *ExistingD;
1859 {
1860 Decl *ToTU = getToTuDecl(
1861 R"(
1862 struct A {
1863 static const int a = 1;
1864 };
1865 )", Lang_CXX);
1866 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1867 }
1868 EXPECT_FALSE(ExistingD->isUsed(false));
1869 {
1870 Decl *FromTU = getTuDecl(
1871 R"(
1872 struct A {
1873 static const int a = 1;
1874 };
1875 const int *f() { return &A::a; } // requires storage,
1876 // thus used flag will be set
1877 )", Lang_CXX, "input1.cc");
1878 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1879 FromTU, functionDecl(hasName("f")));
1880 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1881 ASSERT_TRUE(FromD->isUsed(false));
1882 Import(FromFunD, Lang_CXX);
1883 }
1884 EXPECT_TRUE(ExistingD->isUsed(false));
1885}
1886
Gabor Marton26f72a92018-07-12 09:42:05 +00001887TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
1888 auto Pattern = varDecl(hasName("x"));
1889
1890 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1891 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1892
1893 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1894
1895 ASSERT_FALSE(Imported1->isUsed(false));
1896
1897 FromD->setIsUsed();
1898 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1899
1900 EXPECT_EQ(Imported1, Imported2);
1901 EXPECT_TRUE(Imported2->isUsed(false));
1902}
1903
Peter Szecsidedda6f2018-03-30 22:03:29 +00001904struct ImportFunctions : ASTImporterTestBase {};
1905
1906TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001907 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1908 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1909 auto Pattern = functionDecl(hasName("f"));
1910 FunctionDecl *FromD = // Definition
1911 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1912
1913 Decl *ImportedD = Import(FromD, Lang_CXX);
1914 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1915
Gabor Marton5254e642018-06-27 13:32:50 +00001916 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001917 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1918}
1919
1920TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1921 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1922 auto Pattern = functionDecl(hasName("f"));
1923 FunctionDecl *FromD =
1924 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1925
1926 Decl *ImportedD = Import(FromD, Lang_CXX);
1927 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1928
1929 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1930 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1931}
1932
Gabor Marton5254e642018-06-27 13:32:50 +00001933TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001934 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1935 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001936 auto *From =
1937 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001938
Gabor Marton5254e642018-06-27 13:32:50 +00001939 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001940 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1941
Gabor Marton5254e642018-06-27 13:32:50 +00001942 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1943 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1944 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1945 EXPECT_TRUE(ImportedD == To0);
1946 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1947 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1948 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001949}
1950
1951TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1952 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1953 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001954 auto *From =
1955 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001956
Gabor Marton5254e642018-06-27 13:32:50 +00001957 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001958 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1959
Gabor Marton5254e642018-06-27 13:32:50 +00001960 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1961 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1962 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1963 EXPECT_TRUE(ImportedD == To1);
1964 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1965 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1966 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001967}
1968
1969TEST_P(ImportFunctions, ImportPrototypes) {
1970 auto Pattern = functionDecl(hasName("f"));
1971
1972 Decl *ImportedD;
1973 {
1974 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001975 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001976
1977 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
Gabor Marton5254e642018-06-27 13:32:50 +00001985 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1986
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_FALSE(To0->doesThisDeclarationHaveABody());
1992 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1993 EXPECT_EQ(To1->getPreviousDecl(), To0);
1994}
1995
1996TEST_P(ImportFunctions, ImportDefinitions) {
1997 auto Pattern = functionDecl(hasName("f"));
1998
1999 Decl *ImportedD;
2000 {
2001 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
2002 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2003 ImportedD = Import(FromD, Lang_CXX);
2004 }
2005 {
2006 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
2007 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2008 Import(FromD, Lang_CXX);
2009 }
2010
2011 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2012
Peter Szecsidedda6f2018-03-30 22:03:29 +00002013 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00002014 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2015 EXPECT_TRUE(ImportedD == To0);
2016 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002017}
2018
2019TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
2020 auto Pattern = functionDecl(hasName("f"));
2021
2022 Decl *ImportedD;
2023 {
2024 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002025 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002026 ImportedD = Import(FromD, Lang_CXX);
2027 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00002028 {
2029 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002030 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2031 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002032 }
2033
2034 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002035
2036 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2037 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2038 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2039 EXPECT_TRUE(ImportedD == To0);
2040 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2041 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2042 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002043}
2044
2045TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
2046 auto Pattern = functionDecl(hasName("f"));
2047
2048 {
2049 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
2050 FunctionDecl *FromD =
2051 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2052
2053 Import(FromD, Lang_CXX);
2054 }
2055 {
2056 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
2057 FunctionDecl *FromD =
2058 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2059 Import(FromD, Lang_CXX);
2060 }
2061
2062 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2063 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2064 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002065 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002066 FunctionDecl *DefinitionD =
2067 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2068 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
2069 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
2070}
2071
Gabor Marton5254e642018-06-27 13:32:50 +00002072TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002073 auto Pattern = functionDecl(hasName("f"));
2074
2075 {
2076 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002077 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002078 Import(FromD, Lang_CXX);
2079 }
2080 {
2081 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002082 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002083 Import(FromD, Lang_CXX);
2084 }
2085
2086 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002087
2088 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002089 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002090 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
2091
Peter Szecsidedda6f2018-03-30 22:03:29 +00002092 FunctionDecl *DefinitionD =
2093 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2094 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00002095
2096 EXPECT_TRUE(DefinitionD->getPreviousDecl());
2097 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
2098 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002099}
2100
2101TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2102 auto Code =
2103 R"(
2104 struct B { virtual void f(); };
2105 void B::f() {}
2106 struct D : B { void f(); };
2107 )";
2108 auto Pattern =
2109 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2110 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2111 CXXMethodDecl *Proto =
2112 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2113
2114 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2115 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2116 EXPECT_EQ(To->size_overridden_methods(), 1u);
2117}
2118
2119TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2120 auto Code =
2121 R"(
2122 struct B { virtual void f(); };
2123 void B::f() {}
2124 )";
2125 auto Pattern =
2126 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2127 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2128 CXXMethodDecl *Proto =
2129 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2130 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2131
2132 ASSERT_TRUE(Proto->isVirtual());
2133 ASSERT_TRUE(Def->isVirtual());
2134 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2135 EXPECT_TRUE(To->isVirtual());
2136}
2137
Gabor Marton5254e642018-06-27 13:32:50 +00002138TEST_P(ImportFunctions,
2139 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2140 Decl *ToTU = getToTuDecl(
2141 R"(
2142 void f() {}
2143 void f();
2144 )",
2145 Lang_CXX);
2146 ASSERT_EQ(1u,
2147 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2148 return FD->doesThisDeclarationHaveABody();
2149 }).match(ToTU, functionDecl()));
2150
2151 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2152 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2153
2154 Import(FromD, Lang_CXX);
2155
2156 EXPECT_EQ(1u,
2157 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2158 return FD->doesThisDeclarationHaveABody();
2159 }).match(ToTU, functionDecl()));
2160}
2161
2162struct ImportFriendFunctions : ImportFunctions {};
2163
2164TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2165 auto Pattern = functionDecl(hasName("f"));
2166
2167 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2168 "void f();",
2169 Lang_CXX,
2170 "input0.cc");
2171 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2172
2173 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2174 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2175 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2176 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2177 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2178 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2179 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2180}
2181
2182TEST_P(ImportFriendFunctions,
2183 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2184 auto Pattern = functionDecl(hasName("f"));
2185
2186 Decl *FromTU = getTuDecl("void f();"
2187 "struct X { friend void f(); };",
2188 Lang_CXX, "input0.cc");
2189 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2190
2191 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2192 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2193 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2194 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2195 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2196 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2197 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2198}
2199
2200TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2201 auto Pattern = functionDecl(hasName("f"));
2202
2203 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2204 "void f();",
2205 Lang_CXX,
2206 "input0.cc");
2207 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2208
2209 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2210 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2211 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2212 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2213 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2214 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2215 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2216}
2217
2218TEST_P(ImportFriendFunctions,
2219 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2220 auto Pattern = functionDecl(hasName("f"));
2221
2222 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2223 "void f(){}",
2224 Lang_CXX, "input0.cc");
2225 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2226
2227 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2228 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2229 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2230 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2231 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2232 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2233 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2234}
2235
Gabor Marton26f72a92018-07-12 09:42:05 +00002236// Disabled temporarily, because the new structural equivalence check
2237// (https://reviews.llvm.org/D48628) breaks it.
2238// PreviousDecl is not set because there is no structural match.
2239// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002240TEST_P(ImportFriendFunctions,
2241 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2242 auto Pattern = functionDecl(hasName("f"));
2243
2244 Decl *FromTU = getTuDecl(
2245 R"(
2246 class X;
2247 void f(X *x){}
2248 class X{
2249 friend void f(X *x);
2250 };
2251 )",
2252 Lang_CXX, "input0.cc");
2253 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2254
2255 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2256 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2257 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2258 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2259 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2260 .match(ToTU, friendDecl())
2261 ->getFriendDecl());
2262 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2263 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2264 // The parameters must refer the same type
2265 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2266 (*ImportedD->param_begin())->getOriginalType());
2267}
2268
Gabor Marton26f72a92018-07-12 09:42:05 +00002269// Disabled temporarily, because the new structural equivalence check
2270// (https://reviews.llvm.org/D48628) breaks it.
2271// PreviousDecl is not set because there is no structural match.
2272// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002273TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002274 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002275 auto Pattern = functionDecl(hasName("f"));
2276
2277 Decl *FromTU = getTuDecl(
2278 R"(
2279 class X;
2280 void f(X *x){}
2281 class X{
2282 friend void f(X *x);
2283 };
2284 )",
2285 Lang_CXX, "input0.cc");
2286 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2287
2288 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2289 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2290 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2291 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2292 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2293 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2294
2295 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2296 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2297 // The parameters must refer the same type
2298 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2299 (*ImportedD->param_begin())->getOriginalType());
2300}
2301
2302TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2303 auto Pattern = functionDecl(hasName("f"));
2304
2305 FunctionDecl *ImportedD;
2306 {
2307 Decl *FromTU =
2308 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2309 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2310 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2311 }
2312 FunctionDecl *ImportedD1;
2313 {
2314 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2315 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2316 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2317 }
2318
2319 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2320 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2321 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2322 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2323 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2324}
2325
Balazs Keri89632b82018-08-21 14:32:21 +00002326TEST_P(ImportFriendFunctions, Lookup) {
2327 auto FunctionPattern = functionDecl(hasName("f"));
2328 auto ClassPattern = cxxRecordDecl(hasName("X"));
2329
2330 TranslationUnitDecl *FromTU =
2331 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2332 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2333 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2334 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2335 {
2336 auto FromName = FromD->getDeclName();
2337 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2338 auto LookupRes = Class->noload_lookup(FromName);
2339 ASSERT_EQ(LookupRes.size(), 0u);
2340 LookupRes = FromTU->noload_lookup(FromName);
2341 ASSERT_EQ(LookupRes.size(), 1u);
2342 }
2343
2344 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2345 auto ToName = ToD->getDeclName();
2346
2347 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2348 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2349 auto LookupRes = Class->noload_lookup(ToName);
2350 EXPECT_EQ(LookupRes.size(), 0u);
2351 LookupRes = ToTU->noload_lookup(ToName);
2352 EXPECT_EQ(LookupRes.size(), 1u);
2353
2354 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2355 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2356 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2357 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2358}
2359
2360TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2361 auto FunctionPattern = functionDecl(hasName("f"));
2362 auto ClassPattern = cxxRecordDecl(hasName("X"));
2363
2364 TranslationUnitDecl *FromTU = getTuDecl(
2365 "struct X { friend void f(); };"
2366 // This proto decl makes f available to normal
2367 // lookup, otherwise it is hidden.
2368 // Normal C++ lookup (implemented in
2369 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2370 // returns the found `NamedDecl` only if the set IDNS is matched
2371 "void f();",
2372 Lang_CXX, "input0.cc");
2373 auto *FromFriend =
2374 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2375 auto *FromNormal =
2376 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2377 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2378 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2379 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2380 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2381
2382 auto FromName = FromFriend->getDeclName();
2383 auto *FromClass =
2384 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2385 auto LookupRes = FromClass->noload_lookup(FromName);
2386 ASSERT_EQ(LookupRes.size(), 0u);
2387 LookupRes = FromTU->noload_lookup(FromName);
2388 ASSERT_EQ(LookupRes.size(), 1u);
2389
2390 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2391 auto ToName = ToFriend->getDeclName();
2392
2393 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2394 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2395 LookupRes = ToClass->noload_lookup(ToName);
2396 EXPECT_EQ(LookupRes.size(), 0u);
2397 LookupRes = ToTU->noload_lookup(ToName);
2398 // Test is disabled because this result is 2.
2399 EXPECT_EQ(LookupRes.size(), 1u);
2400
2401 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2402 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2403 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2404 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2405 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2406 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2407 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2408}
2409
2410TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2411 auto FunctionPattern = functionDecl(hasName("f"));
2412 auto ClassPattern = cxxRecordDecl(hasName("X"));
2413
2414 TranslationUnitDecl *FromTU = getTuDecl(
2415 "void f();"
2416 "struct X { friend void f(); };",
2417 Lang_CXX, "input0.cc");
2418 auto *FromNormal =
2419 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2420 auto *FromFriend =
2421 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2422 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2423 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2424 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2425 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2426
2427 auto FromName = FromNormal->getDeclName();
2428 auto *FromClass =
2429 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2430 auto LookupRes = FromClass->noload_lookup(FromName);
2431 ASSERT_EQ(LookupRes.size(), 0u);
2432 LookupRes = FromTU->noload_lookup(FromName);
2433 ASSERT_EQ(LookupRes.size(), 1u);
2434
2435 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2436 auto ToName = ToNormal->getDeclName();
2437 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2438
2439 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2440 LookupRes = ToClass->noload_lookup(ToName);
2441 EXPECT_EQ(LookupRes.size(), 0u);
2442 LookupRes = ToTU->noload_lookup(ToName);
2443 EXPECT_EQ(LookupRes.size(), 1u);
2444
2445 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2446 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2447 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2448 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2449 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2450 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2451 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2452}
2453
2454TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2455 auto Pattern = functionDecl(hasName("f"));
2456
2457 TranslationUnitDecl *FromNormalTU =
2458 getTuDecl("void f();", Lang_CXX, "input0.cc");
2459 auto *FromNormalF =
2460 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2461 TranslationUnitDecl *FromFriendTU =
2462 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2463 auto *FromFriendF =
2464 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2465 auto FromNormalName = FromNormalF->getDeclName();
2466 auto FromFriendName = FromFriendF->getDeclName();
2467
2468 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2469 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2470 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2471 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2472 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2473 ASSERT_EQ(LookupRes.size(), 1u);
2474 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2475 ASSERT_EQ(LookupRes.size(), 1u);
2476
2477 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2478 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2479 auto ToName = ToNormalF->getDeclName();
2480 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2481 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2482 LookupRes = ToTU->noload_lookup(ToName);
2483 EXPECT_EQ(LookupRes.size(), 1u);
2484 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2485
2486 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2487 LookupRes = ToTU->noload_lookup(ToName);
2488 EXPECT_EQ(LookupRes.size(), 1u);
2489 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2490
2491 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2492 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2493
2494 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2495 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2496}
2497
2498TEST_P(ImportFriendFunctions, ImportFriendList) {
2499 TranslationUnitDecl *FromTU = getTuDecl(
2500 "struct X { friend void f(); };"
2501 "void f();",
2502 Lang_CXX, "input0.cc");
2503 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2504 FromTU, functionDecl(hasName("f")));
2505
2506 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2507 FromTU, cxxRecordDecl(hasName("X")));
2508 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2509 auto FromFriends = FromClass->friends();
2510 unsigned int FrN = 0;
2511 for (auto Fr : FromFriends) {
2512 ASSERT_EQ(Fr, FromFriend);
2513 ++FrN;
2514 }
2515 ASSERT_EQ(FrN, 1u);
2516
2517 Import(FromFriendF, Lang_CXX);
2518 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2519 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2520 ToTU, cxxRecordDecl(hasName("X")));
2521 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2522 auto ToFriends = ToClass->friends();
2523 FrN = 0;
2524 for (auto Fr : ToFriends) {
2525 EXPECT_EQ(Fr, ToFriend);
2526 ++FrN;
2527 }
2528 EXPECT_EQ(FrN, 1u);
2529}
2530
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002531AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2532 InnerMatcher) {
2533 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2534 return InnerMatcher.matches(*Typedef, Finder, Builder);
2535 return false;
2536}
2537
Gabor Marton19f4f392018-06-25 13:04:37 +00002538TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002539 CodeFiles Samples{{"main.c",
2540 {"void foo();"
2541 "void moo();"
2542 "int main() { foo(); moo(); }",
2543 Lang_C}},
2544
2545 {"foo.c",
2546 {"typedef enum { THING_VALUE } thing_t;"
2547 "void conflict(thing_t type);"
2548 "void foo() { (void)THING_VALUE; }"
2549 "void conflict(thing_t type) {}",
2550 Lang_C}},
2551
2552 {"moo.c",
2553 {"typedef enum { THING_VALUE } thing_t;"
2554 "void conflict(thing_t type);"
2555 "void moo() { conflict(THING_VALUE); }",
2556 Lang_C}}};
2557
2558 auto VerificationMatcher =
2559 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2560 hasTypedefForAnonDecl(hasName("thing_t")));
2561
2562 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2563 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2564
2565 testImportSequence(
2566 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2567 // Just check that there is only one enum decl in the result AST.
2568 "main.c", enumDecl(), VerificationMatcher);
2569
2570 // For different import order, result should be the same.
2571 testImportSequence(
2572 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2573 // Check that there is only one enum decl in the result AST.
2574 "main.c", enumDecl(), VerificationMatcher);
2575}
2576
Peter Szecsice7f3182018-05-07 12:08:27 +00002577const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2578 dependentScopeDeclRefExpr;
2579
Gabor Marton19f4f392018-06-25 13:04:37 +00002580TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002581 MatchVerifier<Decl> Verifier;
2582 testImport("template <typename T> struct S { static T foo; };"
2583 "template <typename T> void declToImport() {"
2584 " (void) S<T>::foo;"
2585 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002586 "void instantiate() { declToImport<int>(); }"
2587 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002588 Lang_CXX11, "", Lang_CXX11, Verifier,
2589 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2590 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2591
2592 testImport("template <typename T> struct S {"
2593 "template<typename S> static void foo(){};"
2594 "};"
2595 "template <typename T> void declToImport() {"
2596 " S<T>::template foo<T>();"
2597 "}"
2598 "void instantiate() { declToImport<int>(); }",
2599 Lang_CXX11, "", Lang_CXX11, Verifier,
2600 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2601 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2602}
2603
2604const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2605 dependentNameType;
2606
Gabor Marton19f4f392018-06-25 13:04:37 +00002607TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002608 MatchVerifier<Decl> Verifier;
2609 testImport("template <typename T> struct declToImport {"
2610 " typedef typename T::type dependent_name;"
2611 "};",
2612 Lang_CXX11, "", Lang_CXX11, Verifier,
2613 classTemplateDecl(has(
2614 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2615}
2616
Gabor Marton19f4f392018-06-25 13:04:37 +00002617TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002618 MatchVerifier<Decl> Verifier;
2619 testImport("struct S { template <typename T> void mem(); };"
2620 "template <typename U> void declToImport() {"
2621 " S s;"
2622 " s.mem<U>();"
2623 "}"
2624 "void instantiate() { declToImport<int>(); }",
2625 Lang_CXX11, "", Lang_CXX11, Verifier,
2626 functionTemplateDecl(has(functionDecl(has(
2627 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2628}
2629
Balazs Keri1d20cc22018-07-16 12:16:39 +00002630class ImportImplicitMethods : public ASTImporterTestBase {
2631public:
2632 static constexpr auto DefaultCode = R"(
2633 struct A { int x; };
2634 void f() {
2635 A a;
2636 A a1(a);
2637 A a2(A{});
2638 a = a1;
2639 a = A{};
2640 a.~A();
2641 })";
2642
2643 template <typename MatcherType>
2644 void testImportOf(
2645 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2646 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2647 }
2648
2649 template <typename MatcherType>
2650 void testNoImportOf(
2651 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2652 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2653 }
2654
2655private:
2656 template <typename MatcherType>
2657 void test(const MatcherType &MethodMatcher,
2658 const char *Code, unsigned int ExpectedCount) {
2659 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2660
2661 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2662 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2663 ToTU, ClassMatcher);
2664
Balazs Keri2f752ba2018-07-16 14:05:18 +00002665 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002666
2667 {
2668 CXXMethodDecl *Method =
2669 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2670 ToClass->removeDecl(Method);
2671 }
2672
Balazs Keri2f752ba2018-07-16 14:05:18 +00002673 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002674
2675 Decl *ImportedClass = nullptr;
2676 {
2677 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2678 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2679 FromTU, ClassMatcher);
2680 ImportedClass = Import(FromClass, Lang_CXX11);
2681 }
2682
2683 EXPECT_EQ(ToClass, ImportedClass);
2684 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2685 ExpectedCount);
2686 }
2687};
2688
2689TEST_P(ImportImplicitMethods, DefaultConstructor) {
2690 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2691}
2692
2693TEST_P(ImportImplicitMethods, CopyConstructor) {
2694 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2695}
2696
2697TEST_P(ImportImplicitMethods, MoveConstructor) {
2698 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2699}
2700
2701TEST_P(ImportImplicitMethods, Destructor) {
2702 testImportOf(cxxDestructorDecl());
2703}
2704
2705TEST_P(ImportImplicitMethods, CopyAssignment) {
2706 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2707}
2708
2709TEST_P(ImportImplicitMethods, MoveAssignment) {
2710 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2711}
2712
2713TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2714 auto Code = R"(
2715 struct A { A() { int x; } };
2716 )";
2717 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2718}
2719
2720TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2721 auto Code = R"(
2722 struct A { A() = default; };
2723 )";
2724 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2725}
2726
2727TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2728 auto Code = R"(
2729 struct A { A() = delete; };
2730 )";
2731 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2732}
2733
2734TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2735 auto Code = R"(
2736 struct A { void f() { } };
2737 )";
2738 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2739}
2740
Balazs Keric7797c42018-07-11 09:37:24 +00002741TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
2742 Decl *ToR1;
2743 {
2744 Decl *FromTU = getTuDecl(
2745 "struct A { };", Lang_CXX, "input0.cc");
2746 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2747 FromTU, cxxRecordDecl(hasName("A")));
2748
2749 ToR1 = Import(FromR, Lang_CXX);
2750 }
2751
2752 Decl *ToR2;
2753 {
2754 Decl *FromTU = getTuDecl(
2755 "struct A { };", Lang_CXX, "input1.cc");
2756 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2757 FromTU, cxxRecordDecl(hasName("A")));
2758
2759 ToR2 = Import(FromR, Lang_CXX);
2760 }
2761
2762 EXPECT_EQ(ToR1, ToR2);
2763}
2764
2765TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
2766 Decl *ToR1;
2767 {
2768 Decl *FromTU = getTuDecl(
2769 "struct A { int x; };", Lang_CXX, "input0.cc");
2770 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2771 FromTU, cxxRecordDecl(hasName("A")));
2772 ToR1 = Import(FromR, Lang_CXX);
2773 }
2774 Decl *ToR2;
2775 {
2776 Decl *FromTU = getTuDecl(
2777 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2778 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2779 FromTU, cxxRecordDecl(hasName("A")));
2780 ToR2 = Import(FromR, Lang_CXX);
2781 }
2782 EXPECT_NE(ToR1, ToR2);
2783}
2784
2785TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
2786 Decl *ToF1;
2787 {
2788 Decl *FromTU = getTuDecl(
2789 "struct A { int x; };", Lang_CXX, "input0.cc");
2790 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2791 FromTU, fieldDecl(hasName("x")));
2792 ToF1 = Import(FromF, Lang_CXX);
2793 }
2794 Decl *ToF2;
2795 {
2796 Decl *FromTU = getTuDecl(
2797 "struct A { int x; };", Lang_CXX, "input1.cc");
2798 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2799 FromTU, fieldDecl(hasName("x")));
2800 ToF2 = Import(FromF, Lang_CXX);
2801 }
2802 EXPECT_EQ(ToF1, ToF2);
2803}
2804
2805TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
2806 Decl *ToF1;
2807 {
2808 Decl *FromTU = getTuDecl(
2809 "struct A { int x; };", Lang_CXX, "input0.cc");
2810 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2811 FromTU, fieldDecl(hasName("x")));
2812 ToF1 = Import(FromF, Lang_CXX);
2813 }
2814 Decl *ToF2;
2815 {
2816 Decl *FromTU = getTuDecl(
2817 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2818 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2819 FromTU, fieldDecl(hasName("x")));
2820 ToF2 = Import(FromF, Lang_CXX);
2821 }
2822 EXPECT_NE(ToF1, ToF2);
2823}
2824
2825TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
2826 Decl *ToM1;
2827 {
2828 Decl *FromTU = getTuDecl(
2829 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2830 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2831 FromTU, functionDecl(hasName("x"), isDefinition()));
2832 ToM1 = Import(FromM, Lang_CXX);
2833 }
2834 Decl *ToM2;
2835 {
2836 Decl *FromTU = getTuDecl(
2837 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2838 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2839 FromTU, functionDecl(hasName("x"), isDefinition()));
2840 ToM2 = Import(FromM, Lang_CXX);
2841 }
2842 EXPECT_EQ(ToM1, ToM2);
2843}
2844
2845TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
2846 Decl *ToM1;
2847 {
2848 Decl *FromTU = getTuDecl(
2849 "struct A { void x(); }; void A::x() { }",
2850 Lang_CXX, "input0.cc");
2851 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2852 FromTU, functionDecl(hasName("x"), isDefinition()));
2853 ToM1 = Import(FromM, Lang_CXX);
2854 }
2855 Decl *ToM2;
2856 {
2857 Decl *FromTU = getTuDecl(
2858 "struct A { void x() const; }; void A::x() const { }",
2859 Lang_CXX, "input1.cc");
2860 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2861 FromTU, functionDecl(hasName("x"), isDefinition()));
2862 ToM2 = Import(FromM, Lang_CXX);
2863 }
2864 EXPECT_NE(ToM1, ToM2);
2865}
2866
Gabor Martonf086fa82018-07-17 12:06:36 +00002867TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
2868 Decl *FromTU = getTuDecl(
2869 R"(
2870 struct A {
2871 struct {
2872 struct A *next;
2873 } entry0;
2874 struct {
2875 struct A *next;
2876 } entry1;
2877 };
2878 )",
2879 Lang_C, "input0.cc");
2880 auto *From =
2881 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
2882
2883 Import(From, Lang_C);
2884
2885 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2886 auto *Entry0 =
2887 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
2888 auto *Entry1 =
2889 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
2890 auto *R0 = getRecordDecl(Entry0);
2891 auto *R1 = getRecordDecl(Entry1);
2892 EXPECT_NE(R0, R1);
2893 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2894 R0, recordDecl(has(fieldDecl(hasName("next"))))));
2895 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2896 R1, recordDecl(has(fieldDecl(hasName("next"))))));
2897}
2898
Balazs Keri2544b4b2018-08-08 09:40:57 +00002899TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
2900 Decl *FromTU = getTuDecl(
2901 R"(
2902 void f(int X, int Y, bool Z) {
2903 (void)[X, Y, Z] { (void)Z; };
2904 }
2905 )",
2906 Lang_CXX11, "input0.cc");
2907 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
2908 FromTU, functionDecl(hasName("f")));
2909 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
2910 EXPECT_TRUE(ToF);
2911
2912 CXXRecordDecl *FromLambda =
2913 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
2914 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
2915
2916 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
2917 EXPECT_TRUE(ToLambda);
2918
2919 // Check if the fields of the lambda class are imported in correct order.
2920 unsigned FromIndex = 0u;
2921 for (auto *FromField : FromLambda->fields()) {
2922 ASSERT_FALSE(FromField->getDeclName());
2923 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
2924 EXPECT_TRUE(ToField);
2925 unsigned ToIndex = ASTImporter::getFieldIndex(ToField);
2926 EXPECT_EQ(ToIndex, FromIndex + 1);
2927 ++FromIndex;
2928 }
2929
2930 EXPECT_EQ(FromIndex, 3u);
2931}
2932
Balazs Keri0c23dc52018-08-13 13:08:37 +00002933TEST_P(
2934 ASTImporterTestBase,
2935 ImportOfFriendRecordDoesNotMergeDefinition) {
2936 Decl *FromTU = getTuDecl(
2937 R"(
2938 class A {
2939 template <int I> class F {};
2940 class X {
2941 template <int I> friend class F;
2942 };
2943 };
2944 )",
2945 Lang_CXX, "input0.cc");
2946
2947 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2948 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
2949 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
2950 FromTU, cxxRecordDecl(hasName("F")));
2951
2952 ASSERT_TRUE(FromClass);
2953 ASSERT_TRUE(FromFriendClass);
2954 ASSERT_NE(FromClass, FromFriendClass);
2955 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
2956 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
2957 ASSERT_EQ(
2958 FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
2959 FromClass->getDescribedClassTemplate());
2960
2961 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
2962 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
2963
2964 EXPECT_TRUE(ToClass);
2965 EXPECT_TRUE(ToFriendClass);
2966 EXPECT_NE(ToClass, ToFriendClass);
2967 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
2968 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
2969 EXPECT_EQ(
2970 ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
2971 ToClass->getDescribedClassTemplate());
2972}
2973
2974TEST_P(
2975 ASTImporterTestBase,
2976 ImportOfRecursiveFriendClass) {
2977 Decl *FromTu = getTuDecl(
2978 R"(
2979 class declToImport {
2980 friend class declToImport;
2981 };
2982 )",
2983 Lang_CXX, "input.cc");
2984
2985 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
2986 FromTu, cxxRecordDecl(hasName("declToImport")));
2987 auto *ToD = Import(FromD, Lang_CXX);
2988 auto Pattern = cxxRecordDecl(hasName("declToImport"), has(friendDecl()));
2989 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
2990 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
2991}
2992
2993TEST_P(
2994 ASTImporterTestBase,
2995 ImportOfRecursiveFriendClassTemplate) {
2996 Decl *FromTu = getTuDecl(
2997 R"(
2998 template <class A> class declToImport {
2999 template <class A1> friend class declToImport;
3000 };
3001 )",
3002 Lang_CXX, "input.cc");
3003
3004 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
3005 FromTu, classTemplateDecl(hasName("declToImport")));
3006 auto *ToD = Import(FromD, Lang_CXX);
Gabor Marton42e15de2018-08-22 11:52:14 +00003007
Balazs Keri0c23dc52018-08-13 13:08:37 +00003008 auto Pattern = classTemplateDecl(
3009 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3010 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3011 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
Gabor Marton42e15de2018-08-22 11:52:14 +00003012
Balazs Keri0c23dc52018-08-13 13:08:37 +00003013 auto *Class =
3014 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3015 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3016 EXPECT_NE(Friend->getFriendDecl(), Class);
3017 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3018}
3019
Gabor Marton42e15de2018-08-22 11:52:14 +00003020TEST_P(ASTImporterTestBase, MergeFieldDeclsOfClassTemplateSpecialization) {
3021 std::string ClassTemplate =
3022 R"(
3023 template <typename T>
3024 struct X {
3025 int a{0}; // FieldDecl with InitListExpr
3026 X(char) : a(3) {} // (1)
3027 X(int) {} // (2)
3028 };
3029 )";
3030 Decl *ToTU = getToTuDecl(ClassTemplate +
3031 R"(
3032 void foo() {
3033 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3034 X<char> xc('c');
3035 }
3036 )", Lang_CXX11);
3037 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3038 ToTU, classTemplateSpecializationDecl(hasName("X")));
3039 // FieldDecl without InitlistExpr:
3040 auto *ToField = *ToSpec->field_begin();
3041 ASSERT_TRUE(ToField);
3042 ASSERT_FALSE(ToField->getInClassInitializer());
3043 Decl *FromTU = getTuDecl(ClassTemplate +
3044 R"(
3045 void bar() {
3046 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3047 X<char> xc(1);
3048 }
3049 )", Lang_CXX11);
3050 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3051 FromTU, classTemplateSpecializationDecl(hasName("X")));
3052 // FieldDecl with InitlistExpr:
3053 auto *FromField = *FromSpec->field_begin();
3054 ASSERT_TRUE(FromField);
3055 ASSERT_TRUE(FromField->getInClassInitializer());
3056
3057 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3058 ASSERT_TRUE(ImportedSpec);
3059 EXPECT_EQ(ImportedSpec, ToSpec);
3060 // After the import, the FieldDecl has to be merged, thus it should have the
3061 // InitListExpr.
3062 EXPECT_TRUE(ToField->getInClassInitializer());
3063}
3064
3065TEST_P(ASTImporterTestBase, MergeFunctionOfClassTemplateSpecialization) {
3066 std::string ClassTemplate =
3067 R"(
3068 template <typename T>
3069 struct X {
3070 void f() {}
3071 void g() {}
3072 };
3073 )";
3074 Decl *ToTU = getToTuDecl(ClassTemplate +
3075 R"(
3076 void foo() {
3077 X<char> x;
3078 x.f();
3079 }
3080 )", Lang_CXX11);
3081 Decl *FromTU = getTuDecl(ClassTemplate +
3082 R"(
3083 void bar() {
3084 X<char> x;
3085 x.g();
3086 }
3087 )", Lang_CXX11);
3088 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3089 FromTU, classTemplateSpecializationDecl(hasName("X")));
3090 auto FunPattern = functionDecl(hasName("g"),
3091 hasParent(classTemplateSpecializationDecl()));
3092 auto *FromFun =
3093 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3094 auto *ToFun =
3095 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3096 ASSERT_TRUE(FromFun->hasBody());
3097 ASSERT_FALSE(ToFun->hasBody());
3098 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3099 ASSERT_TRUE(ImportedSpec);
3100 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3101 ToTU, classTemplateSpecializationDecl(hasName("X")));
3102 EXPECT_EQ(ImportedSpec, ToSpec);
3103 EXPECT_TRUE(ToFun->hasBody());
3104}
3105
3106TEST_P(ASTImporterTestBase,
3107 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3108 std::string ClassTemplate =
3109 R"(
3110 template <typename T>
3111 struct X {};
3112 )";
3113 Decl *ToTU = getToTuDecl(ClassTemplate +
3114 R"(
3115 template <>
3116 struct X<char> {
3117 int a;
3118 };
3119 void foo() {
3120 X<char> x;
3121 }
3122 )",
3123 Lang_CXX11);
3124 Decl *FromTU = getTuDecl(ClassTemplate +
3125 R"(
3126 template <>
3127 struct X<char> {
3128 int b;
3129 };
3130 void foo() {
3131 X<char> x;
3132 }
3133 )",
3134 Lang_CXX11);
3135 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3136 FromTU, classTemplateSpecializationDecl(hasName("X")));
3137 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3138
3139 // We expect one (ODR) warning during the import.
3140 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3141
3142 // The second specialization is different from the first, thus it violates
3143 // ODR, consequently we expect to keep the first specialization only, which is
3144 // already in the "To" context.
3145 EXPECT_TRUE(ImportedSpec);
3146 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3147 ToTU, classTemplateSpecializationDecl(hasName("X")));
3148 EXPECT_EQ(ImportedSpec, ToSpec);
3149 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3150 ToTU, classTemplateSpecializationDecl()));
3151}
3152
3153TEST_P(ASTImporterTestBase, MergeCtorOfClassTemplateSpecialization) {
3154 std::string ClassTemplate =
3155 R"(
3156 template <typename T>
3157 struct X {
3158 X(char) {}
3159 X(int) {}
3160 };
3161 )";
3162 Decl *ToTU = getToTuDecl(ClassTemplate +
3163 R"(
3164 void foo() {
3165 X<char> x('c');
3166 }
3167 )", Lang_CXX11);
3168 Decl *FromTU = getTuDecl(ClassTemplate +
3169 R"(
3170 void bar() {
3171 X<char> x(1);
3172 }
3173 )", Lang_CXX11);
3174 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3175 FromTU, classTemplateSpecializationDecl(hasName("X")));
3176 // Match the void(int) ctor.
3177 auto CtorPattern =
3178 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3179 hasParent(classTemplateSpecializationDecl()));
3180 auto *FromCtor =
3181 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3182 auto *ToCtor =
3183 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3184 ASSERT_TRUE(FromCtor->hasBody());
3185 ASSERT_FALSE(ToCtor->hasBody());
3186 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3187 ASSERT_TRUE(ImportedSpec);
3188 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3189 ToTU, classTemplateSpecializationDecl(hasName("X")));
3190 EXPECT_EQ(ImportedSpec, ToSpec);
3191 EXPECT_TRUE(ToCtor->hasBody());
3192}
3193
3194TEST_P(ASTImporterTestBase,
3195 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3196 auto Code =
3197 R"(
3198 // primary template
3199 template<class T1, class T2, int I>
3200 class A {};
3201
3202 // partial specialization
3203 template<class T, int I>
3204 class A<T, T*, I> {};
3205 )";
3206 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3207 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3208 auto *FromSpec =
3209 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3210 FromTU, classTemplatePartialSpecializationDecl());
3211 auto *ToSpec =
3212 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3213 ToTU, classTemplatePartialSpecializationDecl());
3214
3215 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3216 EXPECT_EQ(ImportedSpec, ToSpec);
3217 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3218 ToTU, classTemplatePartialSpecializationDecl()));
3219}
3220
3221TEST_P(ASTImporterTestBase, ClassTemplateSpecializationsShouldNotBeDuplicated) {
3222 auto Code =
3223 R"(
3224 // primary template
3225 template<class T1, class T2, int I>
3226 class A {};
3227
3228 // full specialization
3229 template<>
3230 class A<int, int, 1> {};
3231 )";
3232 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3233 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3234 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3235 FromTU, classTemplateSpecializationDecl());
3236 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3237 ToTU, classTemplateSpecializationDecl());
3238
3239 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3240 EXPECT_EQ(ImportedSpec, ToSpec);
3241 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3242 ToTU, classTemplateSpecializationDecl()));
3243}
3244
3245TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3246 std::string PrimaryTemplate =
3247 R"(
3248 template<class T1, class T2, int I>
3249 class A {};
3250 )";
3251 auto PartialSpec =
3252 R"(
3253 template<class T, int I>
3254 class A<T, T*, I> {};
3255 )";
3256 auto FullSpec =
3257 R"(
3258 template<>
3259 class A<int, int, 1> {};
3260 )";
3261 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3262 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3263 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3264 FromTU, classTemplateSpecializationDecl());
3265
3266 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3267 EXPECT_TRUE(ImportedSpec);
3268 // Check the number of partial specializations.
3269 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3270 ToTU, classTemplatePartialSpecializationDecl()));
3271 // Check the number of full specializations.
3272 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3273 ToTU, classTemplateSpecializationDecl(
3274 unless(classTemplatePartialSpecializationDecl()))));
3275}
3276
Gabor Martona20ce602018-09-03 13:10:53 +00003277TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
3278 Decl *TU = getTuDecl(
3279 R"(
3280 const int &init();
3281 void foo() { const int &a{init()}; }
3282 )", Lang_CXX11, "input0.cc");
3283 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3284 ASSERT_TRUE(FromD->getAnyInitializer());
3285 auto *InitExpr = FromD->getAnyInitializer();
3286 ASSERT_TRUE(InitExpr);
3287 ASSERT_TRUE(InitExpr->isGLValue());
3288
3289 auto *ToD = Import(FromD, Lang_CXX11);
3290 EXPECT_TRUE(ToD);
3291 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3292 EXPECT_TRUE(ToInitExpr);
3293 EXPECT_TRUE(ToInitExpr->isGLValue());
3294}
3295
Gabor Martonac3a5d62018-09-17 12:04:52 +00003296struct ImportVariables : ASTImporterTestBase {};
3297
3298TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3299 Decl *FromTU = getTuDecl(
3300 R"(
3301 struct A {
3302 static const int a = 1 + 2;
3303 };
3304 const int A::a;
3305 )", Lang_CXX, "input1.cc");
3306
3307 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3308 FromTU, varDecl(hasName("a"))); // Decl with init
3309 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3310 FromTU, varDecl(hasName("a"))); // Decl with definition
3311 ASSERT_NE(FromDWithInit, FromDWithDef);
3312 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3313
3314 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3315 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3316 ASSERT_TRUE(ToD0);
3317 ASSERT_TRUE(ToD1);
3318 EXPECT_NE(ToD0, ToD1);
3319 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3320}
3321
3322TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3323 auto StructA =
3324 R"(
3325 struct A {
3326 static const int a = 1 + 2;
3327 };
3328 )";
3329 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3330 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3331 "input1.cc");
3332
3333 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3334 FromTU, varDecl(hasName("a"))); // Decl with init
3335 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3336 FromTU, varDecl(hasName("a"))); // Decl with definition
3337 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3338 ASSERT_TRUE(FromDWithInit->getInit());
3339 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3340 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3341 ASSERT_FALSE(FromDWithDef->getInit());
3342
3343 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3344 ToTU, varDecl(hasName("a"))); // Decl with init
3345 ASSERT_TRUE(ToD->getInit());
3346 ASSERT_FALSE(ToD->getDefinition());
3347
3348 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3349 EXPECT_TRUE(ImportedD->getAnyInitializer());
3350 EXPECT_TRUE(ImportedD->getDefinition());
3351}
3352
3353TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3354 auto StructA =
3355 R"(
3356 struct A {
3357 static const int a;
3358 };
3359 )";
3360 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3361 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3362 Lang_CXX, "input1.cc");
3363
3364 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3365 FromTU, varDecl(hasName("a")));
3366 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3367 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3368 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3369 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3370 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3371 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3372 ASSERT_TRUE(FromDWithDef->getInit());
3373
3374 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3375 ToTU, varDecl(hasName("a")));
3376 ASSERT_FALSE(ToD->getInit());
3377 ASSERT_FALSE(ToD->getDefinition());
3378
3379 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3380 EXPECT_TRUE(ImportedD->getAnyInitializer());
3381 EXPECT_TRUE(ImportedD->getDefinition());
3382}
3383
Gabor Marton61d862a2018-05-18 09:08:47 +00003384struct DeclContextTest : ASTImporterTestBase {};
3385
3386TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3387 Decl *TU = getTuDecl(
3388 R"(
3389 namespace NS {
3390
3391 template <typename T>
3392 struct S {};
3393 template struct S<int>;
3394
3395 inline namespace INS {
3396 template <typename T>
3397 struct S {};
3398 template struct S<int>;
3399 }
3400
3401 }
3402 )", Lang_CXX11, "input0.cc");
3403 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
3404 TU, namespaceDecl());
3405 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3406 TU, classTemplateSpecializationDecl());
3407 ASSERT_TRUE(NS->containsDecl(Spec));
3408
3409 NS->removeDecl(Spec);
3410 EXPECT_FALSE(NS->containsDecl(Spec));
3411}
3412
Gabor Marton5254e642018-06-27 13:32:50 +00003413struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
3414
3415TEST_P(ImportFunctionTemplateSpecializations,
3416 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
3417
3418 Decl *FromTU = getTuDecl(
3419 R"(
3420 template<class T>
3421 int f() { return 0; }
3422 void foo() { f<int>(); }
3423 )",
3424 Lang_CXX, "input0.cc");
3425
3426 // Check that the function template instantiation is NOT the child of the TU.
3427 auto Pattern = translationUnitDecl(
3428 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
3429 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3430
3431 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
3432 FromTU, functionDecl(hasName("foo")));
3433 ASSERT_TRUE(Import(Foo, Lang_CXX));
3434
3435 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3436 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3437}
3438
3439TEST_P(ImportFunctionTemplateSpecializations,
3440 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
3441
3442 Decl *FromTU = getTuDecl(
3443 R"(
3444 template<class T>
3445 int f() { return 0; }
3446 template int f<int>();
3447 )",
3448 Lang_CXX, "input0.cc");
3449
3450 // Check that the function template instantiation is NOT the child of the TU.
3451 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
3452 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
3453 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3454
3455 ASSERT_TRUE(
3456 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
3457
3458 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3459 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3460}
3461
3462TEST_P(ImportFunctionTemplateSpecializations,
3463 TUshouldContainFunctionTemplateSpecialization) {
3464
3465 Decl *FromTU = getTuDecl(
3466 R"(
3467 template<class T>
3468 int f() { return 0; }
3469 template <> int f<int>() { return 4; }
3470 )",
3471 Lang_CXX, "input0.cc");
3472
3473 // Check that the function template specialization is the child of the TU.
3474 auto Specialization =
3475 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3476 auto Pattern = translationUnitDecl(has(Specialization));
3477 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3478
3479 ASSERT_TRUE(
3480 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
3481
3482 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3483 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3484}
3485
3486TEST_P(ImportFunctionTemplateSpecializations,
3487 FunctionTemplateSpecializationRedeclChain) {
3488
3489 Decl *FromTU = getTuDecl(
3490 R"(
3491 template<class T>
3492 int f() { return 0; }
3493 template <> int f<int>() { return 4; }
3494 )",
3495 Lang_CXX, "input0.cc");
3496
3497 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
3498 hasParent(translationUnitDecl()));
3499 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
3500 {
3501 auto *TU = FromTU;
3502 auto *SpecD = FromSpecD;
3503 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3504 TU, functionTemplateDecl());
3505 auto *FirstSpecD = *(TemplateD->spec_begin());
3506 ASSERT_EQ(SpecD, FirstSpecD);
3507 ASSERT_TRUE(SpecD->getPreviousDecl());
3508 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3509 ->doesThisDeclarationHaveABody());
3510 }
3511
3512 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
3513
3514 {
3515 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
3516 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
3517 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3518 TU, functionTemplateDecl());
3519 auto *FirstSpecD = *(TemplateD->spec_begin());
3520 EXPECT_EQ(SpecD, FirstSpecD);
3521 ASSERT_TRUE(SpecD->getPreviousDecl());
3522 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3523 ->doesThisDeclarationHaveABody());
3524 }
3525}
3526
3527TEST_P(ImportFunctionTemplateSpecializations,
3528 MatchNumberOfFunctionTemplateSpecializations) {
3529
3530 Decl *FromTU = getTuDecl(
3531 R"(
3532 template <typename T> constexpr int f() { return 0; }
3533 template <> constexpr int f<int>() { return 4; }
3534 void foo() {
3535 static_assert(f<char>() == 0, "");
3536 static_assert(f<int>() == 4, "");
3537 }
3538 )",
3539 Lang_CXX11, "input0.cc");
3540 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
3541 FromTU, functionDecl(hasName("foo")));
3542
3543 Import(FromD, Lang_CXX11);
3544 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3545 EXPECT_EQ(
3546 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
3547 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
3548}
3549
3550TEST_P(ImportFunctionTemplateSpecializations,
3551 ImportPrototypes) {
3552 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3553 auto Code =
3554 R"(
3555 // Proto of the primary template.
3556 template <class T>
3557 void f();
3558 // Proto of the specialization.
3559 template <>
3560 void f<int>();
3561 )";
3562
3563 Decl *ImportedD;
3564 {
3565 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3566 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3567
3568 ImportedD = Import(FromD, Lang_CXX);
3569 }
3570 {
3571 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
3572 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3573 Import(FromD, Lang_CXX);
3574 }
3575
3576 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3577
3578 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3579 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3580 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3581 EXPECT_TRUE(ImportedD == To0);
3582 EXPECT_TRUE(ImportedD != To1);
3583 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
3584 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3585 // Check that they are part of the same redecl chain.
3586 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
3587}
3588
3589TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
3590 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3591 auto Code =
3592 R"(
3593 // Proto of the primary template.
3594 template <class T>
3595 void f();
3596 // Specialization and definition.
3597 template <>
3598 void f<int>() {}
3599 )";
3600
3601 Decl *ImportedD;
3602 {
3603 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3604 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3605 ImportedD = Import(FromD, Lang_CXX);
3606 }
3607 {
3608 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
3609 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3610 Import(FromD, Lang_CXX);
3611 }
3612
3613 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3614
3615 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
3616 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3617 EXPECT_TRUE(ImportedD == To0);
3618 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
3619
3620 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3621 ToTU, functionTemplateDecl());
3622 auto *FirstSpecD = *(TemplateD->spec_begin());
3623 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
3624}
3625
3626TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
3627 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3628 auto Code =
3629 R"(
3630 // Proto of the primary template.
3631 template <class T>
3632 void f();
3633 // Specialization proto.
3634 template <>
3635 void f<int>();
3636 // Specialization proto.
3637 template <>
3638 void f<int>();
3639 )";
3640
3641 Decl *ImportedD;
3642 {
3643 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3644 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3645 ImportedD = Import(FromD, Lang_CXX);
3646 }
3647
3648 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3649
3650 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3651 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3652 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3653 EXPECT_TRUE(ImportedD == To0);
3654 EXPECT_TRUE(ImportedD != To1);
3655 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
3656 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3657 EXPECT_EQ(To1->getPreviousDecl(), To0);
3658}
3659
3660TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
3661 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3662 auto Code =
3663 R"(
3664 // Proto of the primary template.
3665 template <class T>
3666 void f();
3667 // Specialization proto.
3668 template <>
3669 void f<int>();
3670 // Specialization definition.
3671 template <>
3672 void f<int>() {}
3673 )";
3674
3675 Decl *ImportedD;
3676 {
3677 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3678 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3679 ImportedD = Import(FromD, Lang_CXX);
3680 }
3681
3682 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3683
3684 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3685 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3686 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3687 EXPECT_TRUE(ImportedD == To0);
3688 EXPECT_TRUE(ImportedD != To1);
3689 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
3690 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
3691 EXPECT_EQ(To1->getPreviousDecl(), To0);
3692}
3693
3694TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
3695 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3696 auto Code =
3697 R"(
3698 // Proto of the primary template.
3699 template <class T>
3700 void f();
3701 // Specialization definition.
3702 template <>
3703 void f<int>() {}
3704 // Specialization proto.
3705 template <>
3706 void f<int>();
3707 )";
3708
3709 Decl *ImportedD;
3710 {
3711 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3712 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3713 ImportedD = Import(FromD, Lang_CXX);
3714 }
3715
3716 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3717
3718 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3719 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3720 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3721 EXPECT_TRUE(ImportedD == To0);
3722 EXPECT_TRUE(ImportedD != To1);
3723 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
3724 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3725 EXPECT_EQ(To1->getPreviousDecl(), To0);
3726}
3727
Gabor Marton19f4f392018-06-25 13:04:37 +00003728INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
3729 ::testing::Values(ArgVector()), );
3730
Gabor Marton5254e642018-06-27 13:32:50 +00003731INSTANTIATE_TEST_CASE_P(
3732 ParameterizedTests, CanonicalRedeclChain,
3733 ::testing::Values(ArgVector()),);
3734
Gabor Marton19f4f392018-06-25 13:04:37 +00003735auto DefaultTestValuesForRunOptions = ::testing::Values(
3736 ArgVector(),
3737 ArgVector{"-fdelayed-template-parsing"},
3738 ArgVector{"-fms-compatibility"},
3739 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
3740
3741INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
3742 DefaultTestValuesForRunOptions, );
3743
3744INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
3745 DefaultTestValuesForRunOptions, );
3746
3747INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
3748 DefaultTestValuesForRunOptions, );
3749
3750INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
3751 DefaultTestValuesForRunOptions, );
3752
3753INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
3754 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00003755
Gabor Marton5254e642018-06-27 13:32:50 +00003756INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
3757 DefaultTestValuesForRunOptions, );
3758
3759INSTANTIATE_TEST_CASE_P(ParameterizedTests,
3760 ImportFunctionTemplateSpecializations,
3761 DefaultTestValuesForRunOptions, );
3762
Gabor Martonac3a5d62018-09-17 12:04:52 +00003763INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
3764 DefaultTestValuesForRunOptions, );
3765
3766INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
3767 DefaultTestValuesForRunOptions, );
3768
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00003769} // end namespace ast_matchers
3770} // end namespace clang