blob: d1683cd0a678400ce3055df0de662b851f07f4ad [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();
Jonas Devliegherefc514902018-10-10 13:27:25 +000040 auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
Peter Szecsidedda6f2018-03-30 22:03:29 +000041 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
Jonas Devliegherefc514902018-10-10 13:27:25 +000042 auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
43 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,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001460 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001461 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);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002485
Balazs Keri89632b82018-08-21 14:32:21 +00002486 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 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00002761
Balazs Keric7797c42018-07-11 09:37:24 +00002762 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);
Balazs Keri3b30d652018-10-19 13:32:20 +00002925 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
2926 EXPECT_TRUE(ToIndex);
2927 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00002928 ++FromIndex;
2929 }
2930
2931 EXPECT_EQ(FromIndex, 3u);
2932}
2933
Balazs Keri0c23dc52018-08-13 13:08:37 +00002934TEST_P(
2935 ASTImporterTestBase,
2936 ImportOfFriendRecordDoesNotMergeDefinition) {
2937 Decl *FromTU = getTuDecl(
2938 R"(
2939 class A {
2940 template <int I> class F {};
2941 class X {
2942 template <int I> friend class F;
2943 };
2944 };
2945 )",
2946 Lang_CXX, "input0.cc");
2947
2948 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2949 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
2950 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
2951 FromTU, cxxRecordDecl(hasName("F")));
2952
2953 ASSERT_TRUE(FromClass);
2954 ASSERT_TRUE(FromFriendClass);
2955 ASSERT_NE(FromClass, FromFriendClass);
2956 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
2957 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
2958 ASSERT_EQ(
2959 FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
2960 FromClass->getDescribedClassTemplate());
2961
2962 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
2963 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
2964
2965 EXPECT_TRUE(ToClass);
2966 EXPECT_TRUE(ToFriendClass);
2967 EXPECT_NE(ToClass, ToFriendClass);
2968 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
2969 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
2970 EXPECT_EQ(
2971 ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
2972 ToClass->getDescribedClassTemplate());
2973}
2974
2975TEST_P(
2976 ASTImporterTestBase,
2977 ImportOfRecursiveFriendClass) {
2978 Decl *FromTu = getTuDecl(
2979 R"(
2980 class declToImport {
2981 friend class declToImport;
2982 };
2983 )",
2984 Lang_CXX, "input.cc");
2985
2986 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
2987 FromTu, cxxRecordDecl(hasName("declToImport")));
2988 auto *ToD = Import(FromD, Lang_CXX);
2989 auto Pattern = cxxRecordDecl(hasName("declToImport"), has(friendDecl()));
2990 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
2991 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
2992}
2993
2994TEST_P(
2995 ASTImporterTestBase,
2996 ImportOfRecursiveFriendClassTemplate) {
2997 Decl *FromTu = getTuDecl(
2998 R"(
2999 template <class A> class declToImport {
3000 template <class A1> friend class declToImport;
3001 };
3002 )",
3003 Lang_CXX, "input.cc");
3004
3005 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
3006 FromTu, classTemplateDecl(hasName("declToImport")));
3007 auto *ToD = Import(FromD, Lang_CXX);
Gabor Marton42e15de2018-08-22 11:52:14 +00003008
Balazs Keri0c23dc52018-08-13 13:08:37 +00003009 auto Pattern = classTemplateDecl(
3010 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3011 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3012 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
Gabor Marton42e15de2018-08-22 11:52:14 +00003013
Balazs Keri0c23dc52018-08-13 13:08:37 +00003014 auto *Class =
3015 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3016 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3017 EXPECT_NE(Friend->getFriendDecl(), Class);
3018 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3019}
3020
Gabor Marton42e15de2018-08-22 11:52:14 +00003021TEST_P(ASTImporterTestBase, MergeFieldDeclsOfClassTemplateSpecialization) {
3022 std::string ClassTemplate =
3023 R"(
3024 template <typename T>
3025 struct X {
3026 int a{0}; // FieldDecl with InitListExpr
3027 X(char) : a(3) {} // (1)
3028 X(int) {} // (2)
3029 };
3030 )";
3031 Decl *ToTU = getToTuDecl(ClassTemplate +
3032 R"(
3033 void foo() {
3034 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3035 X<char> xc('c');
3036 }
3037 )", Lang_CXX11);
3038 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3039 ToTU, classTemplateSpecializationDecl(hasName("X")));
3040 // FieldDecl without InitlistExpr:
3041 auto *ToField = *ToSpec->field_begin();
3042 ASSERT_TRUE(ToField);
3043 ASSERT_FALSE(ToField->getInClassInitializer());
3044 Decl *FromTU = getTuDecl(ClassTemplate +
3045 R"(
3046 void bar() {
3047 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3048 X<char> xc(1);
3049 }
3050 )", Lang_CXX11);
3051 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3052 FromTU, classTemplateSpecializationDecl(hasName("X")));
3053 // FieldDecl with InitlistExpr:
3054 auto *FromField = *FromSpec->field_begin();
3055 ASSERT_TRUE(FromField);
3056 ASSERT_TRUE(FromField->getInClassInitializer());
3057
3058 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3059 ASSERT_TRUE(ImportedSpec);
3060 EXPECT_EQ(ImportedSpec, ToSpec);
3061 // After the import, the FieldDecl has to be merged, thus it should have the
3062 // InitListExpr.
3063 EXPECT_TRUE(ToField->getInClassInitializer());
3064}
3065
3066TEST_P(ASTImporterTestBase, MergeFunctionOfClassTemplateSpecialization) {
3067 std::string ClassTemplate =
3068 R"(
3069 template <typename T>
3070 struct X {
3071 void f() {}
3072 void g() {}
3073 };
3074 )";
3075 Decl *ToTU = getToTuDecl(ClassTemplate +
3076 R"(
3077 void foo() {
3078 X<char> x;
3079 x.f();
3080 }
3081 )", Lang_CXX11);
3082 Decl *FromTU = getTuDecl(ClassTemplate +
3083 R"(
3084 void bar() {
3085 X<char> x;
3086 x.g();
3087 }
3088 )", Lang_CXX11);
3089 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3090 FromTU, classTemplateSpecializationDecl(hasName("X")));
3091 auto FunPattern = functionDecl(hasName("g"),
3092 hasParent(classTemplateSpecializationDecl()));
3093 auto *FromFun =
3094 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3095 auto *ToFun =
3096 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3097 ASSERT_TRUE(FromFun->hasBody());
3098 ASSERT_FALSE(ToFun->hasBody());
3099 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3100 ASSERT_TRUE(ImportedSpec);
3101 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3102 ToTU, classTemplateSpecializationDecl(hasName("X")));
3103 EXPECT_EQ(ImportedSpec, ToSpec);
3104 EXPECT_TRUE(ToFun->hasBody());
3105}
3106
3107TEST_P(ASTImporterTestBase,
3108 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3109 std::string ClassTemplate =
3110 R"(
3111 template <typename T>
3112 struct X {};
3113 )";
3114 Decl *ToTU = getToTuDecl(ClassTemplate +
3115 R"(
3116 template <>
3117 struct X<char> {
3118 int a;
3119 };
3120 void foo() {
3121 X<char> x;
3122 }
3123 )",
3124 Lang_CXX11);
3125 Decl *FromTU = getTuDecl(ClassTemplate +
3126 R"(
3127 template <>
3128 struct X<char> {
3129 int b;
3130 };
3131 void foo() {
3132 X<char> x;
3133 }
3134 )",
3135 Lang_CXX11);
3136 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3137 FromTU, classTemplateSpecializationDecl(hasName("X")));
3138 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3139
3140 // We expect one (ODR) warning during the import.
3141 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3142
3143 // The second specialization is different from the first, thus it violates
3144 // ODR, consequently we expect to keep the first specialization only, which is
3145 // already in the "To" context.
3146 EXPECT_TRUE(ImportedSpec);
3147 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3148 ToTU, classTemplateSpecializationDecl(hasName("X")));
3149 EXPECT_EQ(ImportedSpec, ToSpec);
3150 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3151 ToTU, classTemplateSpecializationDecl()));
3152}
3153
3154TEST_P(ASTImporterTestBase, MergeCtorOfClassTemplateSpecialization) {
3155 std::string ClassTemplate =
3156 R"(
3157 template <typename T>
3158 struct X {
3159 X(char) {}
3160 X(int) {}
3161 };
3162 )";
3163 Decl *ToTU = getToTuDecl(ClassTemplate +
3164 R"(
3165 void foo() {
3166 X<char> x('c');
3167 }
3168 )", Lang_CXX11);
3169 Decl *FromTU = getTuDecl(ClassTemplate +
3170 R"(
3171 void bar() {
3172 X<char> x(1);
3173 }
3174 )", Lang_CXX11);
3175 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3176 FromTU, classTemplateSpecializationDecl(hasName("X")));
3177 // Match the void(int) ctor.
3178 auto CtorPattern =
3179 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3180 hasParent(classTemplateSpecializationDecl()));
3181 auto *FromCtor =
3182 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3183 auto *ToCtor =
3184 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3185 ASSERT_TRUE(FromCtor->hasBody());
3186 ASSERT_FALSE(ToCtor->hasBody());
3187 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3188 ASSERT_TRUE(ImportedSpec);
3189 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3190 ToTU, classTemplateSpecializationDecl(hasName("X")));
3191 EXPECT_EQ(ImportedSpec, ToSpec);
3192 EXPECT_TRUE(ToCtor->hasBody());
3193}
3194
3195TEST_P(ASTImporterTestBase,
3196 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3197 auto Code =
3198 R"(
3199 // primary template
3200 template<class T1, class T2, int I>
3201 class A {};
3202
3203 // partial specialization
3204 template<class T, int I>
3205 class A<T, T*, I> {};
3206 )";
3207 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3208 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3209 auto *FromSpec =
3210 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3211 FromTU, classTemplatePartialSpecializationDecl());
3212 auto *ToSpec =
3213 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3214 ToTU, classTemplatePartialSpecializationDecl());
3215
3216 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3217 EXPECT_EQ(ImportedSpec, ToSpec);
3218 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3219 ToTU, classTemplatePartialSpecializationDecl()));
3220}
3221
3222TEST_P(ASTImporterTestBase, ClassTemplateSpecializationsShouldNotBeDuplicated) {
3223 auto Code =
3224 R"(
3225 // primary template
3226 template<class T1, class T2, int I>
3227 class A {};
3228
3229 // full specialization
3230 template<>
3231 class A<int, int, 1> {};
3232 )";
3233 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3234 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3235 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3236 FromTU, classTemplateSpecializationDecl());
3237 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3238 ToTU, classTemplateSpecializationDecl());
3239
3240 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3241 EXPECT_EQ(ImportedSpec, ToSpec);
3242 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3243 ToTU, classTemplateSpecializationDecl()));
3244}
3245
3246TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3247 std::string PrimaryTemplate =
3248 R"(
3249 template<class T1, class T2, int I>
3250 class A {};
3251 )";
3252 auto PartialSpec =
3253 R"(
3254 template<class T, int I>
3255 class A<T, T*, I> {};
3256 )";
3257 auto FullSpec =
3258 R"(
3259 template<>
3260 class A<int, int, 1> {};
3261 )";
3262 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3263 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3264 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3265 FromTU, classTemplateSpecializationDecl());
3266
3267 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3268 EXPECT_TRUE(ImportedSpec);
3269 // Check the number of partial specializations.
3270 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3271 ToTU, classTemplatePartialSpecializationDecl()));
3272 // Check the number of full specializations.
3273 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3274 ToTU, classTemplateSpecializationDecl(
3275 unless(classTemplatePartialSpecializationDecl()))));
3276}
3277
Gabor Martona20ce602018-09-03 13:10:53 +00003278TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
3279 Decl *TU = getTuDecl(
3280 R"(
3281 const int &init();
3282 void foo() { const int &a{init()}; }
3283 )", Lang_CXX11, "input0.cc");
3284 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3285 ASSERT_TRUE(FromD->getAnyInitializer());
3286 auto *InitExpr = FromD->getAnyInitializer();
3287 ASSERT_TRUE(InitExpr);
3288 ASSERT_TRUE(InitExpr->isGLValue());
3289
3290 auto *ToD = Import(FromD, Lang_CXX11);
3291 EXPECT_TRUE(ToD);
3292 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3293 EXPECT_TRUE(ToInitExpr);
3294 EXPECT_TRUE(ToInitExpr->isGLValue());
3295}
3296
Gabor Martonac3a5d62018-09-17 12:04:52 +00003297struct ImportVariables : ASTImporterTestBase {};
3298
3299TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3300 Decl *FromTU = getTuDecl(
3301 R"(
3302 struct A {
3303 static const int a = 1 + 2;
3304 };
3305 const int A::a;
3306 )", Lang_CXX, "input1.cc");
3307
3308 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3309 FromTU, varDecl(hasName("a"))); // Decl with init
3310 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3311 FromTU, varDecl(hasName("a"))); // Decl with definition
3312 ASSERT_NE(FromDWithInit, FromDWithDef);
3313 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3314
3315 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3316 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3317 ASSERT_TRUE(ToD0);
3318 ASSERT_TRUE(ToD1);
3319 EXPECT_NE(ToD0, ToD1);
3320 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3321}
3322
3323TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3324 auto StructA =
3325 R"(
3326 struct A {
3327 static const int a = 1 + 2;
3328 };
3329 )";
3330 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3331 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3332 "input1.cc");
3333
3334 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3335 FromTU, varDecl(hasName("a"))); // Decl with init
3336 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3337 FromTU, varDecl(hasName("a"))); // Decl with definition
3338 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3339 ASSERT_TRUE(FromDWithInit->getInit());
3340 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3341 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3342 ASSERT_FALSE(FromDWithDef->getInit());
3343
3344 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3345 ToTU, varDecl(hasName("a"))); // Decl with init
3346 ASSERT_TRUE(ToD->getInit());
3347 ASSERT_FALSE(ToD->getDefinition());
3348
3349 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3350 EXPECT_TRUE(ImportedD->getAnyInitializer());
3351 EXPECT_TRUE(ImportedD->getDefinition());
3352}
3353
3354TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3355 auto StructA =
3356 R"(
3357 struct A {
3358 static const int a;
3359 };
3360 )";
3361 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3362 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3363 Lang_CXX, "input1.cc");
3364
3365 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3366 FromTU, varDecl(hasName("a")));
3367 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3368 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3369 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3370 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3371 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3372 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3373 ASSERT_TRUE(FromDWithDef->getInit());
3374
3375 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3376 ToTU, varDecl(hasName("a")));
3377 ASSERT_FALSE(ToD->getInit());
3378 ASSERT_FALSE(ToD->getDefinition());
3379
3380 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3381 EXPECT_TRUE(ImportedD->getAnyInitializer());
3382 EXPECT_TRUE(ImportedD->getDefinition());
3383}
3384
Gabor Marton61d862a2018-05-18 09:08:47 +00003385struct DeclContextTest : ASTImporterTestBase {};
3386
3387TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3388 Decl *TU = getTuDecl(
3389 R"(
3390 namespace NS {
3391
3392 template <typename T>
3393 struct S {};
3394 template struct S<int>;
3395
3396 inline namespace INS {
3397 template <typename T>
3398 struct S {};
3399 template struct S<int>;
3400 }
3401
3402 }
3403 )", Lang_CXX11, "input0.cc");
3404 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
3405 TU, namespaceDecl());
3406 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3407 TU, classTemplateSpecializationDecl());
3408 ASSERT_TRUE(NS->containsDecl(Spec));
3409
3410 NS->removeDecl(Spec);
3411 EXPECT_FALSE(NS->containsDecl(Spec));
3412}
3413
Gabor Marton5254e642018-06-27 13:32:50 +00003414struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
3415
3416TEST_P(ImportFunctionTemplateSpecializations,
3417 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
3418
3419 Decl *FromTU = getTuDecl(
3420 R"(
3421 template<class T>
3422 int f() { return 0; }
3423 void foo() { f<int>(); }
3424 )",
3425 Lang_CXX, "input0.cc");
3426
3427 // Check that the function template instantiation is NOT the child of the TU.
3428 auto Pattern = translationUnitDecl(
3429 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
3430 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3431
3432 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
3433 FromTU, functionDecl(hasName("foo")));
3434 ASSERT_TRUE(Import(Foo, Lang_CXX));
3435
3436 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3437 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3438}
3439
3440TEST_P(ImportFunctionTemplateSpecializations,
3441 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
3442
3443 Decl *FromTU = getTuDecl(
3444 R"(
3445 template<class T>
3446 int f() { return 0; }
3447 template int f<int>();
3448 )",
3449 Lang_CXX, "input0.cc");
3450
3451 // Check that the function template instantiation is NOT the child of the TU.
3452 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
3453 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
3454 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3455
3456 ASSERT_TRUE(
3457 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
3458
3459 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3460 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3461}
3462
3463TEST_P(ImportFunctionTemplateSpecializations,
3464 TUshouldContainFunctionTemplateSpecialization) {
3465
3466 Decl *FromTU = getTuDecl(
3467 R"(
3468 template<class T>
3469 int f() { return 0; }
3470 template <> int f<int>() { return 4; }
3471 )",
3472 Lang_CXX, "input0.cc");
3473
3474 // Check that the function template specialization is the child of the TU.
3475 auto Specialization =
3476 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3477 auto Pattern = translationUnitDecl(has(Specialization));
3478 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3479
3480 ASSERT_TRUE(
3481 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
3482
3483 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3484 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3485}
3486
3487TEST_P(ImportFunctionTemplateSpecializations,
3488 FunctionTemplateSpecializationRedeclChain) {
3489
3490 Decl *FromTU = getTuDecl(
3491 R"(
3492 template<class T>
3493 int f() { return 0; }
3494 template <> int f<int>() { return 4; }
3495 )",
3496 Lang_CXX, "input0.cc");
3497
3498 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
3499 hasParent(translationUnitDecl()));
3500 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
3501 {
3502 auto *TU = FromTU;
3503 auto *SpecD = FromSpecD;
3504 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3505 TU, functionTemplateDecl());
3506 auto *FirstSpecD = *(TemplateD->spec_begin());
3507 ASSERT_EQ(SpecD, FirstSpecD);
3508 ASSERT_TRUE(SpecD->getPreviousDecl());
3509 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3510 ->doesThisDeclarationHaveABody());
3511 }
3512
3513 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
3514
3515 {
3516 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
3517 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
3518 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3519 TU, functionTemplateDecl());
3520 auto *FirstSpecD = *(TemplateD->spec_begin());
3521 EXPECT_EQ(SpecD, FirstSpecD);
3522 ASSERT_TRUE(SpecD->getPreviousDecl());
3523 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3524 ->doesThisDeclarationHaveABody());
3525 }
3526}
3527
3528TEST_P(ImportFunctionTemplateSpecializations,
3529 MatchNumberOfFunctionTemplateSpecializations) {
3530
3531 Decl *FromTU = getTuDecl(
3532 R"(
3533 template <typename T> constexpr int f() { return 0; }
3534 template <> constexpr int f<int>() { return 4; }
3535 void foo() {
3536 static_assert(f<char>() == 0, "");
3537 static_assert(f<int>() == 4, "");
3538 }
3539 )",
3540 Lang_CXX11, "input0.cc");
3541 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
3542 FromTU, functionDecl(hasName("foo")));
3543
3544 Import(FromD, Lang_CXX11);
3545 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3546 EXPECT_EQ(
3547 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
3548 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
3549}
3550
3551TEST_P(ImportFunctionTemplateSpecializations,
3552 ImportPrototypes) {
3553 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3554 auto Code =
3555 R"(
3556 // Proto of the primary template.
3557 template <class T>
3558 void f();
3559 // Proto of the specialization.
3560 template <>
3561 void f<int>();
3562 )";
3563
3564 Decl *ImportedD;
3565 {
3566 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3567 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3568
3569 ImportedD = Import(FromD, Lang_CXX);
3570 }
3571 {
3572 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
3573 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3574 Import(FromD, Lang_CXX);
3575 }
3576
3577 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3578
3579 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3580 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3581 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3582 EXPECT_TRUE(ImportedD == To0);
3583 EXPECT_TRUE(ImportedD != To1);
3584 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
3585 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3586 // Check that they are part of the same redecl chain.
3587 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
3588}
3589
3590TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
3591 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3592 auto Code =
3593 R"(
3594 // Proto of the primary template.
3595 template <class T>
3596 void f();
3597 // Specialization and definition.
3598 template <>
3599 void f<int>() {}
3600 )";
3601
3602 Decl *ImportedD;
3603 {
3604 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3605 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3606 ImportedD = Import(FromD, Lang_CXX);
3607 }
3608 {
3609 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
3610 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3611 Import(FromD, Lang_CXX);
3612 }
3613
3614 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3615
3616 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
3617 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3618 EXPECT_TRUE(ImportedD == To0);
3619 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
3620
3621 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3622 ToTU, functionTemplateDecl());
3623 auto *FirstSpecD = *(TemplateD->spec_begin());
3624 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
3625}
3626
3627TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
3628 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3629 auto Code =
3630 R"(
3631 // Proto of the primary template.
3632 template <class T>
3633 void f();
3634 // Specialization proto.
3635 template <>
3636 void f<int>();
3637 // Specialization proto.
3638 template <>
3639 void f<int>();
3640 )";
3641
3642 Decl *ImportedD;
3643 {
3644 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3645 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3646 ImportedD = Import(FromD, Lang_CXX);
3647 }
3648
3649 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3650
3651 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3652 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3653 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3654 EXPECT_TRUE(ImportedD == To0);
3655 EXPECT_TRUE(ImportedD != To1);
3656 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
3657 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3658 EXPECT_EQ(To1->getPreviousDecl(), To0);
3659}
3660
3661TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
3662 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3663 auto Code =
3664 R"(
3665 // Proto of the primary template.
3666 template <class T>
3667 void f();
3668 // Specialization proto.
3669 template <>
3670 void f<int>();
3671 // Specialization definition.
3672 template <>
3673 void f<int>() {}
3674 )";
3675
3676 Decl *ImportedD;
3677 {
3678 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3679 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3680 ImportedD = Import(FromD, Lang_CXX);
3681 }
3682
3683 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3684
3685 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3686 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3687 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3688 EXPECT_TRUE(ImportedD == To0);
3689 EXPECT_TRUE(ImportedD != To1);
3690 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
3691 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
3692 EXPECT_EQ(To1->getPreviousDecl(), To0);
3693}
3694
3695TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
3696 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3697 auto Code =
3698 R"(
3699 // Proto of the primary template.
3700 template <class T>
3701 void f();
3702 // Specialization definition.
3703 template <>
3704 void f<int>() {}
3705 // Specialization proto.
3706 template <>
3707 void f<int>();
3708 )";
3709
3710 Decl *ImportedD;
3711 {
3712 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
3713 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
3714 ImportedD = Import(FromD, Lang_CXX);
3715 }
3716
3717 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3718
3719 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3720 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3721 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
3722 EXPECT_TRUE(ImportedD == To0);
3723 EXPECT_TRUE(ImportedD != To1);
3724 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
3725 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
3726 EXPECT_EQ(To1->getPreviousDecl(), To0);
3727}
3728
Gabor Marton19f4f392018-06-25 13:04:37 +00003729INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
3730 ::testing::Values(ArgVector()), );
3731
Gabor Marton5254e642018-06-27 13:32:50 +00003732INSTANTIATE_TEST_CASE_P(
3733 ParameterizedTests, CanonicalRedeclChain,
3734 ::testing::Values(ArgVector()),);
3735
Gabor Marton19f4f392018-06-25 13:04:37 +00003736auto DefaultTestValuesForRunOptions = ::testing::Values(
3737 ArgVector(),
3738 ArgVector{"-fdelayed-template-parsing"},
3739 ArgVector{"-fms-compatibility"},
3740 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
3741
3742INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
3743 DefaultTestValuesForRunOptions, );
3744
3745INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
3746 DefaultTestValuesForRunOptions, );
3747
3748INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
3749 DefaultTestValuesForRunOptions, );
3750
3751INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
3752 DefaultTestValuesForRunOptions, );
3753
3754INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
3755 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00003756
Gabor Marton5254e642018-06-27 13:32:50 +00003757INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
3758 DefaultTestValuesForRunOptions, );
3759
3760INSTANTIATE_TEST_CASE_P(ParameterizedTests,
3761 ImportFunctionTemplateSpecializations,
3762 DefaultTestValuesForRunOptions, );
3763
Gabor Martonac3a5d62018-09-17 12:04:52 +00003764INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
3765 DefaultTestValuesForRunOptions, );
3766
3767INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
3768 DefaultTestValuesForRunOptions, );
3769
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00003770} // end namespace ast_matchers
3771} // end namespace clang