blob: 3407f7da6d1e31003d6c71c216f155eca12605a9 [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
Gabor Marton7df342a2018-12-17 12:42:12 +000014#include "clang/AST/ASTImporter.h"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +000015#include "MatchVerifier.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000016#include "clang/AST/ASTContext.h"
Gabor Marton7df342a2018-12-17 12:42:12 +000017#include "clang/AST/DeclContextInternals.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000018#include "clang/ASTMatchers/ASTMatchFinder.h"
19#include "clang/ASTMatchers/ASTMatchers.h"
20#include "clang/Tooling/Tooling.h"
Peter Szecsidedda6f2018-03-30 22:03:29 +000021
22#include "DeclMatcher.h"
Gabor Marton1f667532018-05-24 08:41:07 +000023#include "Language.h"
Gabor Marton5254e642018-06-27 13:32:50 +000024#include "gmock/gmock.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000025#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000026
27namespace clang {
28namespace ast_matchers {
29
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000030using internal::Matcher;
31using internal::BindableMatcher;
32using llvm::StringMap;
33
Peter Szecsidedda6f2018-03-30 22:03:29 +000034// Creates a virtual file and assigns that to the context of given AST. If the
35// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000036static void
37createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
38 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000039 assert(ToAST);
40 ASTContext &ToCtx = ToAST->getASTContext();
Jonas Devliegherefc514902018-10-10 13:27:25 +000041 auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
Peter Szecsidedda6f2018-03-30 22:03:29 +000042 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
Jonas Devliegherefc514902018-10-10 13:27:25 +000043 auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
44 OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000045 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000046}
47
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000048static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
49 StringRef Code) {
50 return createVirtualFileIfNeeded(ToAST, FileName,
51 llvm::MemoryBuffer::getMemBuffer(Code));
52}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000053
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000054const StringRef DeclToImportID = "declToImport";
55const StringRef DeclToVerifyID = "declToVerify";
56
Gabor Marton19f4f392018-06-25 13:04:37 +000057// Common base for the different families of ASTImporter tests that are
58// parameterized on the compiler options which may result a different AST. E.g.
59// -fms-compatibility or -fdelayed-template-parsing.
60struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000061
Gabor Marton19f4f392018-06-25 13:04:37 +000062 // Returns the argument vector used for a specific language option, this set
63 // can be tweaked by the test parameters.
64 ArgVector getArgVectorForLanguage(Language Lang) const {
65 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
66 ArgVector ExtraArgs = GetParam();
67 for (const auto &Arg : ExtraArgs) {
68 Args.push_back(Arg);
69 }
70 return Args;
71 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000072
Gabor Marton19f4f392018-06-25 13:04:37 +000073};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000074
Gabor Marton19f4f392018-06-25 13:04:37 +000075// Base class for those tests which use the family of `testImport` functions.
76class TestImportBase : public ParameterizedTestsFixture {
Adam Baloghe4192a82018-06-15 06:45:39 +000077
Gabor Marton19f4f392018-06-25 13:04:37 +000078 template <typename NodeType>
79 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
80 NodeType Node) {
81 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000082
Gabor Marton19f4f392018-06-25 13:04:37 +000083 // Add 'From' file to virtual file system so importer can 'find' it
84 // while importing SourceLocations. It is safe to add same file multiple
85 // times - it just isn't replaced.
86 StringRef FromFileName = From->getMainFileName();
87 createVirtualFileIfNeeded(To, FromFileName,
88 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000089
Gabor Marton19f4f392018-06-25 13:04:37 +000090 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000091
Gabor Marton19f4f392018-06-25 13:04:37 +000092 // This should dump source locations and assert if some source locations
93 // were not imported.
94 SmallString<1024> ImportChecker;
95 llvm::raw_svector_ostream ToNothing(ImportChecker);
96 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000097
Gabor Marton19f4f392018-06-25 13:04:37 +000098 // This traverses the AST to catch certain bugs like poorly or not
99 // implemented subtrees.
100 Imported->dump(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000101
Gabor Marton19f4f392018-06-25 13:04:37 +0000102 return Imported;
103 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000104
Gabor Marton19f4f392018-06-25 13:04:37 +0000105 template <typename NodeType>
106 testing::AssertionResult
107 testImport(const std::string &FromCode, const ArgVector &FromArgs,
108 const std::string &ToCode, const ArgVector &ToArgs,
109 MatchVerifier<NodeType> &Verifier,
110 const BindableMatcher<NodeType> &SearchMatcher,
111 const BindableMatcher<NodeType> &VerificationMatcher) {
112 const char *const InputFileName = "input.cc";
113 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000114
Gabor Marton19f4f392018-06-25 13:04:37 +0000115 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
116 FromCode, FromArgs, InputFileName),
117 ToAST = tooling::buildASTFromCodeWithArgs(
118 ToCode, ToArgs, OutputFileName);
119
120 ASTContext &FromCtx = FromAST->getASTContext(),
121 &ToCtx = ToAST->getASTContext();
122
123 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
124 FromAST->getFileManager(), false);
125
126 auto FoundNodes = match(SearchMatcher, FromCtx);
127 if (FoundNodes.size() != 1)
128 return testing::AssertionFailure()
129 << "Multiple potential nodes were found!";
130
131 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
132 if (!ToImport)
133 return testing::AssertionFailure() << "Node type mismatch!";
134
135 // Sanity check: the node being imported should match in the same way as
136 // the result node.
137 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
138 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
139
140 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
141 if (!Imported)
142 return testing::AssertionFailure() << "Import failed, nullptr returned!";
143
Bill Wendling8003edc2018-11-09 00:41:36 +0000144
Gabor Marton19f4f392018-06-25 13:04:37 +0000145 return Verifier.match(Imported, WrapperMatcher);
146 }
147
148 template <typename NodeType>
149 testing::AssertionResult
150 testImport(const std::string &FromCode, const ArgVector &FromArgs,
151 const std::string &ToCode, const ArgVector &ToArgs,
152 MatchVerifier<NodeType> &Verifier,
153 const BindableMatcher<NodeType> &VerificationMatcher) {
154 return testImport(
155 FromCode, FromArgs, ToCode, ToArgs, Verifier,
156 translationUnitDecl(
157 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
158 VerificationMatcher);
159 }
160
161public:
162
163 /// Test how AST node named "declToImport" located in the translation unit
164 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
165 /// The verification is done by running AMatcher over the imported node.
166 template <typename NodeType, typename MatcherType>
167 void testImport(const std::string &FromCode, Language FromLang,
168 const std::string &ToCode, Language ToLang,
169 MatchVerifier<NodeType> &Verifier,
170 const MatcherType &AMatcher) {
171 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
172 ToArgs = getArgVectorForLanguage(ToLang);
173 EXPECT_TRUE(
174 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
175 }
176
177 struct ImportAction {
178 StringRef FromFilename;
179 StringRef ToFilename;
180 // FIXME: Generalize this to support other node kinds.
181 BindableMatcher<Decl> ImportPredicate;
182
183 ImportAction(StringRef FromFilename, StringRef ToFilename,
184 DeclarationMatcher ImportPredicate)
185 : FromFilename(FromFilename), ToFilename(ToFilename),
186 ImportPredicate(ImportPredicate) {}
187
188 ImportAction(StringRef FromFilename, StringRef ToFilename,
189 const std::string &DeclName)
190 : FromFilename(FromFilename), ToFilename(ToFilename),
191 ImportPredicate(namedDecl(hasName(DeclName))) {}
192 };
193
194 using SingleASTUnit = std::unique_ptr<ASTUnit>;
195 using AllASTUnits = StringMap<SingleASTUnit>;
196
197 struct CodeEntry {
198 std::string CodeSample;
199 Language Lang;
200 };
201
202 using CodeFiles = StringMap<CodeEntry>;
203
204 /// Builds an ASTUnit for one potential compile options set.
205 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
206 ArgVector Args = getArgVectorForLanguage(CE.Lang);
207 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
208 EXPECT_TRUE(AST.get());
209 return AST;
210 }
211
212 /// Test an arbitrary sequence of imports for a set of given in-memory files.
213 /// The verification is done by running VerificationMatcher against a
214 /// specified AST node inside of one of given files.
215 /// \param CodeSamples Map whose key is the file name and the value is the
216 /// file content.
217 /// \param ImportActions Sequence of imports. Each import in sequence
218 /// specifies "from file" and "to file" and a matcher that is used for
219 /// searching a declaration for import in "from file".
220 /// \param FileForFinalCheck Name of virtual file for which the final check is
221 /// applied.
222 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
223 /// FileForFinalCheck for which the verification will be done.
224 /// \param VerificationMatcher Matcher that will be used for verification
225 /// after all imports in sequence are done.
226 void testImportSequence(const CodeFiles &CodeSamples,
227 const std::vector<ImportAction> &ImportActions,
228 StringRef FileForFinalCheck,
229 BindableMatcher<Decl> FinalSelectPredicate,
230 BindableMatcher<Decl> VerificationMatcher) {
231 AllASTUnits AllASTs;
232 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
233 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
234
235 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
236 if (!AllASTs.count(Filename)) {
237 auto Found = CodeSamples.find(Filename);
238 assert(Found != CodeSamples.end() && "Wrong file for import!");
239 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
240 }
241 };
242
243 for (const ImportAction &Action : ImportActions) {
244 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
245 GenASTsIfNeeded(FromFile);
246 GenASTsIfNeeded(ToFile);
247
248 ASTUnit *From = AllASTs[FromFile].get();
249 ASTUnit *To = AllASTs[ToFile].get();
250
251 // Create a new importer if needed.
252 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
253 if (!ImporterRef)
254 ImporterRef.reset(new ASTImporter(
255 To->getASTContext(), To->getFileManager(), From->getASTContext(),
256 From->getFileManager(), false));
257
258 // Find the declaration and import it.
259 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
260 From->getASTContext());
261 EXPECT_TRUE(FoundDecl.size() == 1);
262 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
263 auto Imported = importNode(From, To, *ImporterRef, ToImport);
264 EXPECT_TRUE(Imported);
265 }
266
267 // Find the declaration and import it.
268 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
269 AllASTs[FileForFinalCheck]->getASTContext());
270 EXPECT_TRUE(FoundDecl.size() == 1);
271 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
272 MatchVerifier<Decl> Verifier;
273 EXPECT_TRUE(
274 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
275 }
276};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000277
Gabor Martonf086fa82018-07-17 12:06:36 +0000278template <typename T> RecordDecl *getRecordDecl(T *D) {
279 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
280 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000281}
Gabor Martonf086fa82018-07-17 12:06:36 +0000282
Peter Szecsidedda6f2018-03-30 22:03:29 +0000283// This class provides generic methods to write tests which can check internal
Balazs Keri21f938c2018-07-02 14:14:07 +0000284// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000285// this fixture makes it possible to import from several "From" contexts.
Gabor Marton19f4f392018-06-25 13:04:37 +0000286class ASTImporterTestBase : public ParameterizedTestsFixture {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000287
288 const char *const InputFileName = "input.cc";
289 const char *const OutputFileName = "output.cc";
290
291 // Buffer for the To context, must live in the test scope.
292 std::string ToCode;
293
Gabor Marton26f72a92018-07-12 09:42:05 +0000294 // Represents a "From" translation unit and holds an importer object which we
295 // use to import from this translation unit.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000296 struct TU {
297 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000298 std::string Code;
299 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000300 std::unique_ptr<ASTUnit> Unit;
301 TranslationUnitDecl *TUDecl = nullptr;
Gabor Marton26f72a92018-07-12 09:42:05 +0000302 std::unique_ptr<ASTImporter> Importer;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000303 TU(StringRef Code, StringRef FileName, ArgVector Args)
304 : Code(Code), FileName(FileName),
305 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
306 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000307 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
308 Unit->enableSourceFileDiagnostics();
309 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000310
Gabor Marton6e1510c2018-07-12 11:50:21 +0000311 void lazyInitImporter(ASTUnit *ToAST) {
Gabor Marton26f72a92018-07-12 09:42:05 +0000312 assert(ToAST);
313 if (!Importer) {
314 Importer.reset(new ASTImporter(
315 ToAST->getASTContext(), ToAST->getFileManager(),
316 Unit->getASTContext(), Unit->getFileManager(), false));
317 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000318 assert(&ToAST->getASTContext() == &Importer->getToContext());
319 createVirtualFileIfNeeded(ToAST, FileName, Code);
320 }
321
322 Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
323 lazyInitImporter(ToAST);
Gabor Marton26f72a92018-07-12 09:42:05 +0000324 return Importer->Import(FromDecl);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000325 }
326
327 QualType import(ASTUnit *ToAST, QualType FromType) {
328 lazyInitImporter(ToAST);
329 return Importer->Import(FromType);
Gabor Marton26f72a92018-07-12 09:42:05 +0000330 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000331 };
332
333 // We may have several From contexts and related translation units. In each
334 // AST, the buffers for the source are handled via references and are set
335 // during the creation of the AST. These references must point to a valid
336 // buffer until the AST is alive. Thus, we must use a list in order to avoid
337 // moving of the stored objects because that would mean breaking the
338 // references in the AST. By using a vector a move could happen when the
339 // vector is expanding, with the list we won't have these issues.
340 std::list<TU> FromTUs;
341
Gabor Marton6e1510c2018-07-12 11:50:21 +0000342 void lazyInitToAST(Language ToLang) {
343 if (ToAST)
344 return;
345 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
346 // Build the AST from an empty file.
347 ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
348 ToAST->enableSourceFileDiagnostics();
349 }
350
351 TU *findFromTU(Decl *From) {
352 // Create a virtual file in the To Ctx which corresponds to the file from
353 // which we want to import the `From` Decl. Without this source locations
354 // will be invalid in the ToCtx.
355 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
356 return E.TUDecl == From->getTranslationUnitDecl();
357 });
358 assert(It != FromTUs.end());
359 return &*It;
360 }
361
Peter Szecsidedda6f2018-03-30 22:03:29 +0000362public:
363 // We may have several From context but only one To context.
364 std::unique_ptr<ASTUnit> ToAST;
365
Peter Szecsidedda6f2018-03-30 22:03:29 +0000366 // Creates an AST both for the From and To source code and imports the Decl
367 // of the identifier into the To context.
368 // Must not be called more than once within the same test.
369 std::tuple<Decl *, Decl *>
370 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
371 Language ToLang, StringRef Identifier = DeclToImportID) {
372 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
373 ToArgs = getArgVectorForLanguage(ToLang);
374
375 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
376 TU &FromTU = FromTUs.back();
377
378 ToCode = ToSrcCode;
379 assert(!ToAST);
380 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000381 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000382
Gabor Marton26f72a92018-07-12 09:42:05 +0000383 ASTContext &FromCtx = FromTU.Unit->getASTContext();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000384
385 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
386
Peter Szecsidedda6f2018-03-30 22:03:29 +0000387 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
388 assert(ImportedII && "Declaration with the given identifier "
389 "should be specified in test!");
390 DeclarationName ImportDeclName(ImportedII);
391 SmallVector<NamedDecl *, 4> FoundDecls;
392 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
393 FoundDecls);
394
395 assert(FoundDecls.size() == 1);
396
Gabor Marton26f72a92018-07-12 09:42:05 +0000397 Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
398
Peter Szecsidedda6f2018-03-30 22:03:29 +0000399 assert(Imported);
400 return std::make_tuple(*FoundDecls.begin(), Imported);
401 }
402
Gabor Marton9581c332018-05-23 13:53:36 +0000403 // Creates a TU decl for the given source code which can be used as a From
404 // context. May be called several times in a given test (with different file
405 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000406 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
407 StringRef FileName = "input.cc") {
408 assert(
409 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
410 return E.FileName == FileName;
411 }) == FromTUs.end());
412
413 ArgVector Args = getArgVectorForLanguage(Lang);
414 FromTUs.emplace_back(SrcCode, FileName, Args);
415 TU &Tu = FromTUs.back();
416
417 return Tu.TUDecl;
418 }
419
Gabor Marton9581c332018-05-23 13:53:36 +0000420 // Creates the To context with the given source code and returns the TU decl.
421 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
422 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
423 ToCode = ToSrcCode;
424 assert(!ToAST);
425 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000426 ToAST->enableSourceFileDiagnostics();
Gabor Marton9581c332018-05-23 13:53:36 +0000427
428 return ToAST->getASTContext().getTranslationUnitDecl();
429 }
430
Peter Szecsidedda6f2018-03-30 22:03:29 +0000431 // Import the given Decl into the ToCtx.
432 // May be called several times in a given test.
433 // The different instances of the param From may have different ASTContext.
434 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000435 lazyInitToAST(ToLang);
436 TU *FromTU = findFromTU(From);
437 return FromTU->import(ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000438 }
439
Gabor Marton6e1510c2018-07-12 11:50:21 +0000440 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
441 lazyInitToAST(ToLang);
442 TU *FromTU = findFromTU(TUDecl);
443 return FromTU->import(ToAST.get(), FromType);
444 }
445
Peter Szecsidedda6f2018-03-30 22:03:29 +0000446 ~ASTImporterTestBase() {
447 if (!::testing::Test::HasFailure()) return;
448
449 for (auto &Tu : FromTUs) {
450 assert(Tu.Unit);
451 llvm::errs() << "FromAST:\n";
452 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
453 llvm::errs() << "\n";
454 }
455 if (ToAST) {
456 llvm::errs() << "ToAST:\n";
457 ToAST->getASTContext().getTranslationUnitDecl()->dump();
458 }
459 }
460};
461
Gabor Marton19f4f392018-06-25 13:04:37 +0000462struct ImportExpr : TestImportBase {};
463struct ImportType : TestImportBase {};
464struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000465
Gabor Marton5254e642018-06-27 13:32:50 +0000466struct CanonicalRedeclChain : ASTImporterTestBase {};
467
468TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
469 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
470 auto Pattern = functionDecl(hasName("f"));
471 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
472
473 auto Redecls = getCanonicalForwardRedeclChain(D0);
474 ASSERT_EQ(Redecls.size(), 1u);
475 EXPECT_EQ(D0, Redecls[0]);
476}
477
478TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
479 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
480 auto Pattern = functionDecl(hasName("f"));
481 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
482 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
483 FunctionDecl *D1 = D2->getPreviousDecl();
484
485 auto Redecls = getCanonicalForwardRedeclChain(D0);
486 ASSERT_EQ(Redecls.size(), 3u);
487 EXPECT_EQ(D0, Redecls[0]);
488 EXPECT_EQ(D1, Redecls[1]);
489 EXPECT_EQ(D2, Redecls[2]);
490}
491
492TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
493 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
494 auto Pattern = functionDecl(hasName("f"));
495 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
496 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
497 FunctionDecl *D1 = D2->getPreviousDecl();
498
499 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
500 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
501 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
502
503 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
504 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
505}
506
Gabor Marton19f4f392018-06-25 13:04:37 +0000507TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000508 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000509 testImport(
510 "void declToImport() { (void)\"foo\"; }",
511 Lang_CXX, "", Lang_CXX, Verifier,
512 functionDecl(hasDescendant(
513 stringLiteral(hasType(asString("const char [4]"))))));
514 testImport(
515 "void declToImport() { (void)L\"foo\"; }",
516 Lang_CXX, "", Lang_CXX, Verifier,
517 functionDecl(hasDescendant(
518 stringLiteral(hasType(asString("const wchar_t [4]"))))));
519 testImport(
520 "void declToImport() { (void) \"foo\" \"bar\"; }",
521 Lang_CXX, "", Lang_CXX, Verifier,
522 functionDecl(hasDescendant(
523 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000524}
525
Gabor Marton19f4f392018-06-25 13:04:37 +0000526TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000527 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000528 testImport(
529 "void declToImport() { (void)__null; }",
530 Lang_CXX, "", Lang_CXX, Verifier,
531 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000532}
533
Gabor Marton19f4f392018-06-25 13:04:37 +0000534TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000535 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000536 testImport(
537 "void declToImport() { (void)nullptr; }",
538 Lang_CXX11, "", Lang_CXX11, Verifier,
539 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000540}
541
542
Gabor Marton19f4f392018-06-25 13:04:37 +0000543TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000544 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000545 testImport(
546 "void declToImport() { (void)1.0; }",
547 Lang_C, "", Lang_C, Verifier,
548 functionDecl(hasDescendant(
549 floatLiteral(equals(1.0), hasType(asString("double"))))));
550 testImport(
551 "void declToImport() { (void)1.0e-5f; }",
552 Lang_C, "", Lang_C, Verifier,
553 functionDecl(hasDescendant(
554 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000555}
556
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000557TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
558 MatchVerifier<Decl> Verifier;
559 testImport(
560 "void declToImport() { (void)1.0i; }",
561 Lang_CXX14, "", Lang_CXX14, Verifier,
562 functionDecl(hasDescendant(imaginaryLiteral())));
563}
564
Gabor Marton19f4f392018-06-25 13:04:37 +0000565TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000566 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000567 testImport(
568 "void declToImport() {"
569 " struct s { int x; long y; unsigned z; }; "
570 " (void)(struct s){ 42, 0L, 1U }; }",
571 Lang_CXX, "", Lang_CXX, Verifier,
572 functionDecl(hasDescendant(
573 compoundLiteralExpr(
574 hasType(asString("struct s")),
575 has(initListExpr(
576 hasType(asString("struct s")),
577 has(integerLiteral(
578 equals(42), hasType(asString("int")))),
579 has(integerLiteral(
580 equals(0), hasType(asString("long")))),
581 has(integerLiteral(
582 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000583}
584
Gabor Marton19f4f392018-06-25 13:04:37 +0000585TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000586 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000587 testImport(
588 "class declToImport { void f() { (void)this; } };",
589 Lang_CXX, "", Lang_CXX, Verifier,
590 cxxRecordDecl(
591 hasMethod(
592 hasDescendant(
593 cxxThisExpr(
594 hasType(
595 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000596}
597
Gabor Marton19f4f392018-06-25 13:04:37 +0000598TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000599 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000600 testImport(
601 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
602 Lang_C, "", Lang_C, Verifier,
603 functionDecl(hasDescendant(
604 atomicExpr(
605 has(ignoringParenImpCasts(
606 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
607 hasType(asString("int *"))))),
608 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000609}
610
Gabor Marton19f4f392018-06-25 13:04:37 +0000611TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000612 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000613 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000614 "void declToImport() { loop: goto loop; (void)&&loop; }",
615 Lang_C, "", Lang_C, Verifier,
616 functionDecl(
617 hasDescendant(
618 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
619 hasDescendant(
620 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000621}
622
623AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
624 internal::Matcher<NamedDecl>, InnerMatcher) {
625 const NamedDecl *Template = Node.getTemplatedDecl();
626 return Template && InnerMatcher.matches(*Template, Finder, Builder);
627}
628
Gabor Marton19f4f392018-06-25 13:04:37 +0000629TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000630 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000631 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000632 "template<typename T> class dummy { void f() { dummy X(*this); } };"
633 "typedef dummy<int> declToImport;"
634 "template class dummy<int>;",
635 Lang_CXX, "", Lang_CXX, Verifier,
636 typedefDecl(hasType(templateSpecializationType(
637 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
638 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
639 hasName("f"),
640 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
641 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
642 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000643 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000644}
645
Gabor Marton19f4f392018-06-25 13:04:37 +0000646TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000647 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000648 testImport(
649 "void declToImport() { int b; switch (b) { case 1: break; } }",
650 Lang_C, "", Lang_C, Verifier,
651 functionDecl(hasDescendant(
652 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000653}
654
Gabor Marton19f4f392018-06-25 13:04:37 +0000655TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000656 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000657 testImport(
658 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
659 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000660 functionDecl(hasDescendant(
661 varDecl(
662 hasName("C"),
663 hasType(asString("int")),
664 hasInitializer(
665 stmtExpr(
666 hasAnySubstatement(declStmt(hasSingleDecl(
667 varDecl(
668 hasName("X"),
669 hasType(asString("int")),
670 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000671 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000672 hasDescendant(
673 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000674}
675
Gabor Marton19f4f392018-06-25 13:04:37 +0000676TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000677 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000678 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000679 "void declToImport() { (void)(true ? 1 : -5); }",
680 Lang_CXX, "", Lang_CXX, Verifier,
681 functionDecl(hasDescendant(
682 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000683 hasCondition(cxxBoolLiteral(equals(true))),
684 hasTrueExpression(integerLiteral(equals(1))),
685 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000686 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
687 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000688}
689
Gabor Marton19f4f392018-06-25 13:04:37 +0000690TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000691 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000692 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000693 "void declToImport() { (void)(1 ?: -5); }",
694 Lang_CXX, "", Lang_CXX, Verifier,
695 functionDecl(hasDescendant(
696 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000697 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000698 implicitCastExpr(
699 hasSourceExpression(opaqueValueExpr(
700 hasSourceExpression(integerLiteral(equals(1))))),
701 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000702 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000703 opaqueValueExpr(
704 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000705 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000706 unaryOperator(
707 hasOperatorName("-"),
708 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000709}
710
Gabor Marton19f4f392018-06-25 13:04:37 +0000711TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000712 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000713 testImport(
714 "void declToImport() {"
715 " struct point { double x; double y; };"
716 " struct point ptarray[10] = "
717 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
718 Lang_C, "", Lang_C, Verifier,
719 functionDecl(hasDescendant(
720 initListExpr(
721 has(designatedInitExpr(
722 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000723 hasDescendant(floatLiteral(equals(1.0))),
724 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000725 has(designatedInitExpr(
726 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000727 hasDescendant(floatLiteral(equals(2.0))),
728 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000729 has(designatedInitExpr(
730 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000731 hasDescendant(floatLiteral(equals(1.0))),
732 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000733}
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 Marton7df342a2018-12-17 12:42:12 +00001812TEST_P(ASTImporterTestBase, AnonymousRecords) {
1813 auto *Code =
1814 R"(
1815 struct X {
1816 struct { int a; };
1817 struct { int b; };
1818 };
1819 )";
1820 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1821
1822 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1823
1824 auto *X0 =
1825 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1826 auto *X1 =
1827 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1828 Import(X0, Lang_C);
1829 Import(X1, Lang_C);
1830
1831 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1832 // We expect no (ODR) warning during the import.
1833 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1834 EXPECT_EQ(1u,
1835 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1836}
1837
1838TEST_P(ASTImporterTestBase, AnonymousRecordsReversed) {
1839 Decl *FromTU0 = getTuDecl(
1840 R"(
1841 struct X {
1842 struct { int a; };
1843 struct { int b; };
1844 };
1845 )",
1846 Lang_C, "input0.c");
1847
1848 Decl *FromTU1 = getTuDecl(
1849 R"(
1850 struct X { // reversed order
1851 struct { int b; };
1852 struct { int a; };
1853 };
1854 )",
1855 Lang_C, "input1.c");
1856
1857 auto *X0 =
1858 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1859 auto *X1 =
1860 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1861 Import(X0, Lang_C);
1862 Import(X1, Lang_C);
1863
1864 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1865 // We expect one (ODR) warning during the import.
1866 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1867 EXPECT_EQ(2u,
1868 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1869}
1870
Gabor Marton26f72a92018-07-12 09:42:05 +00001871TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
1872 auto Pattern = varDecl(hasName("x"));
1873 VarDecl *Imported1;
1874 {
1875 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1876 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1877 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1878 }
1879 VarDecl *Imported2;
1880 {
1881 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1882 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1883 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1884 }
1885 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1886 EXPECT_FALSE(Imported2->isUsed(false));
1887 {
1888 Decl *FromTU =
1889 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001890 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1891 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001892 Import(FromD, Lang_CXX);
1893 }
1894 EXPECT_TRUE(Imported2->isUsed(false));
1895}
1896
Gabor Martonac3a5d62018-09-17 12:04:52 +00001897TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag2) {
1898 auto Pattern = varDecl(hasName("x"));
1899 VarDecl *ExistingD;
1900 {
1901 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1902 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1903 }
1904 EXPECT_FALSE(ExistingD->isUsed(false));
1905 {
1906 Decl *FromTU = getTuDecl(
1907 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1908 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1909 FromTU, functionDecl(hasName("f")));
1910 Import(FromD, Lang_CXX);
1911 }
1912 EXPECT_TRUE(ExistingD->isUsed(false));
1913}
1914
1915TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag3) {
1916 auto Pattern = varDecl(hasName("a"));
1917 VarDecl *ExistingD;
1918 {
1919 Decl *ToTU = getToTuDecl(
1920 R"(
1921 struct A {
1922 static const int a = 1;
1923 };
1924 )", Lang_CXX);
1925 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1926 }
1927 EXPECT_FALSE(ExistingD->isUsed(false));
1928 {
1929 Decl *FromTU = getTuDecl(
1930 R"(
1931 struct A {
1932 static const int a = 1;
1933 };
1934 const int *f() { return &A::a; } // requires storage,
1935 // thus used flag will be set
1936 )", Lang_CXX, "input1.cc");
1937 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1938 FromTU, functionDecl(hasName("f")));
1939 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1940 ASSERT_TRUE(FromD->isUsed(false));
1941 Import(FromFunD, Lang_CXX);
1942 }
1943 EXPECT_TRUE(ExistingD->isUsed(false));
1944}
1945
Gabor Marton26f72a92018-07-12 09:42:05 +00001946TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
1947 auto Pattern = varDecl(hasName("x"));
1948
1949 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1950 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1951
1952 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1953
1954 ASSERT_FALSE(Imported1->isUsed(false));
1955
1956 FromD->setIsUsed();
1957 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1958
1959 EXPECT_EQ(Imported1, Imported2);
1960 EXPECT_TRUE(Imported2->isUsed(false));
1961}
1962
Peter Szecsidedda6f2018-03-30 22:03:29 +00001963struct ImportFunctions : ASTImporterTestBase {};
1964
1965TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001966 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1967 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1968 auto Pattern = functionDecl(hasName("f"));
1969 FunctionDecl *FromD = // Definition
1970 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1971
1972 Decl *ImportedD = Import(FromD, Lang_CXX);
1973 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1974
Gabor Marton5254e642018-06-27 13:32:50 +00001975 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001976 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1977}
1978
1979TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1980 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1981 auto Pattern = functionDecl(hasName("f"));
1982 FunctionDecl *FromD =
1983 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1984
1985 Decl *ImportedD = Import(FromD, Lang_CXX);
1986 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1987
1988 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1989 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1990}
1991
Gabor Marton5254e642018-06-27 13:32:50 +00001992TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001993 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1994 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001995 auto *From =
1996 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001997
Gabor Marton5254e642018-06-27 13:32:50 +00001998 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001999 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2000
Gabor Marton5254e642018-06-27 13:32:50 +00002001 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2002 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2003 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2004 EXPECT_TRUE(ImportedD == To0);
2005 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2006 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2007 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002008}
2009
2010TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2011 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2012 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002013 auto *From =
2014 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002015
Gabor Marton5254e642018-06-27 13:32:50 +00002016 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002017 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2018
Gabor Marton5254e642018-06-27 13:32:50 +00002019 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2020 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2021 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2022 EXPECT_TRUE(ImportedD == To1);
2023 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2024 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2025 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002026}
2027
2028TEST_P(ImportFunctions, ImportPrototypes) {
2029 auto Pattern = functionDecl(hasName("f"));
2030
2031 Decl *ImportedD;
2032 {
2033 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002034 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002035
2036 ImportedD = Import(FromD, Lang_CXX);
2037 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00002038 {
2039 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002040 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2041 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002042 }
2043
Gabor Marton5254e642018-06-27 13:32:50 +00002044 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2045
2046 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2047 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2048 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2049 EXPECT_TRUE(ImportedD == To0);
2050 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2051 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2052 EXPECT_EQ(To1->getPreviousDecl(), To0);
2053}
2054
2055TEST_P(ImportFunctions, ImportDefinitions) {
2056 auto Pattern = functionDecl(hasName("f"));
2057
2058 Decl *ImportedD;
2059 {
2060 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
2061 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2062 ImportedD = Import(FromD, Lang_CXX);
2063 }
2064 {
2065 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
2066 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2067 Import(FromD, Lang_CXX);
2068 }
2069
2070 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2071
Peter Szecsidedda6f2018-03-30 22:03:29 +00002072 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00002073 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2074 EXPECT_TRUE(ImportedD == To0);
2075 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002076}
2077
2078TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
2079 auto Pattern = functionDecl(hasName("f"));
2080
2081 Decl *ImportedD;
2082 {
2083 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002084 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002085 ImportedD = Import(FromD, Lang_CXX);
2086 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00002087 {
2088 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002089 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2090 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002091 }
2092
2093 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002094
2095 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2096 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2097 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2098 EXPECT_TRUE(ImportedD == To0);
2099 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2100 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2101 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002102}
2103
2104TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
2105 auto Pattern = functionDecl(hasName("f"));
2106
2107 {
2108 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
2109 FunctionDecl *FromD =
2110 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2111
2112 Import(FromD, Lang_CXX);
2113 }
2114 {
2115 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
2116 FunctionDecl *FromD =
2117 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2118 Import(FromD, Lang_CXX);
2119 }
2120
2121 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2122 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2123 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002124 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002125 FunctionDecl *DefinitionD =
2126 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2127 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
2128 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
2129}
2130
Gabor Marton5254e642018-06-27 13:32:50 +00002131TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002132 auto Pattern = functionDecl(hasName("f"));
2133
2134 {
2135 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002136 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002137 Import(FromD, Lang_CXX);
2138 }
2139 {
2140 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002141 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002142 Import(FromD, Lang_CXX);
2143 }
2144
2145 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002146
2147 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002148 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002149 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
2150
Peter Szecsidedda6f2018-03-30 22:03:29 +00002151 FunctionDecl *DefinitionD =
2152 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2153 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00002154
2155 EXPECT_TRUE(DefinitionD->getPreviousDecl());
2156 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
2157 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002158}
2159
2160TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2161 auto Code =
2162 R"(
2163 struct B { virtual void f(); };
2164 void B::f() {}
2165 struct D : B { void f(); };
2166 )";
2167 auto Pattern =
2168 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2169 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2170 CXXMethodDecl *Proto =
2171 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2172
2173 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2174 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2175 EXPECT_EQ(To->size_overridden_methods(), 1u);
2176}
2177
2178TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2179 auto Code =
2180 R"(
2181 struct B { virtual void f(); };
2182 void B::f() {}
2183 )";
2184 auto Pattern =
2185 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2186 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2187 CXXMethodDecl *Proto =
2188 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2189 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2190
2191 ASSERT_TRUE(Proto->isVirtual());
2192 ASSERT_TRUE(Def->isVirtual());
2193 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2194 EXPECT_TRUE(To->isVirtual());
2195}
2196
Gabor Marton5254e642018-06-27 13:32:50 +00002197TEST_P(ImportFunctions,
2198 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2199 Decl *ToTU = getToTuDecl(
2200 R"(
2201 void f() {}
2202 void f();
2203 )",
2204 Lang_CXX);
2205 ASSERT_EQ(1u,
2206 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2207 return FD->doesThisDeclarationHaveABody();
2208 }).match(ToTU, functionDecl()));
2209
2210 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2211 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2212
2213 Import(FromD, Lang_CXX);
2214
2215 EXPECT_EQ(1u,
2216 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2217 return FD->doesThisDeclarationHaveABody();
2218 }).match(ToTU, functionDecl()));
2219}
2220
2221struct ImportFriendFunctions : ImportFunctions {};
2222
2223TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2224 auto Pattern = functionDecl(hasName("f"));
2225
2226 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2227 "void f();",
2228 Lang_CXX,
2229 "input0.cc");
2230 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2231
2232 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2233 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2234 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2235 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2236 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2237 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2238 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2239}
2240
2241TEST_P(ImportFriendFunctions,
2242 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2243 auto Pattern = functionDecl(hasName("f"));
2244
2245 Decl *FromTU = getTuDecl("void f();"
2246 "struct X { friend void f(); };",
2247 Lang_CXX, "input0.cc");
2248 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2249
2250 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2251 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2252 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2253 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2254 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2255 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2256 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2257}
2258
2259TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2260 auto Pattern = functionDecl(hasName("f"));
2261
2262 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2263 "void f();",
2264 Lang_CXX,
2265 "input0.cc");
2266 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2267
2268 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2269 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2270 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2271 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2272 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2273 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2274 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2275}
2276
2277TEST_P(ImportFriendFunctions,
2278 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2279 auto Pattern = functionDecl(hasName("f"));
2280
2281 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2282 "void f(){}",
2283 Lang_CXX, "input0.cc");
2284 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2285
2286 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2287 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2288 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2289 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2290 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2291 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2292 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2293}
2294
Gabor Marton26f72a92018-07-12 09:42:05 +00002295// Disabled temporarily, because the new structural equivalence check
2296// (https://reviews.llvm.org/D48628) breaks it.
2297// PreviousDecl is not set because there is no structural match.
2298// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002299TEST_P(ImportFriendFunctions,
2300 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2301 auto Pattern = functionDecl(hasName("f"));
2302
2303 Decl *FromTU = getTuDecl(
2304 R"(
2305 class X;
2306 void f(X *x){}
2307 class X{
2308 friend void f(X *x);
2309 };
2310 )",
2311 Lang_CXX, "input0.cc");
2312 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2313
2314 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2315 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2316 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2317 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2318 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2319 .match(ToTU, friendDecl())
2320 ->getFriendDecl());
2321 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2322 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2323 // The parameters must refer the same type
2324 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2325 (*ImportedD->param_begin())->getOriginalType());
2326}
2327
Gabor Marton26f72a92018-07-12 09:42:05 +00002328// Disabled temporarily, because the new structural equivalence check
2329// (https://reviews.llvm.org/D48628) breaks it.
2330// PreviousDecl is not set because there is no structural match.
2331// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002332TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002333 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002334 auto Pattern = functionDecl(hasName("f"));
2335
2336 Decl *FromTU = getTuDecl(
2337 R"(
2338 class X;
2339 void f(X *x){}
2340 class X{
2341 friend void f(X *x);
2342 };
2343 )",
2344 Lang_CXX, "input0.cc");
2345 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2346
2347 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2348 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2349 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2350 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2351 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2352 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2353
2354 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2355 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2356 // The parameters must refer the same type
2357 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2358 (*ImportedD->param_begin())->getOriginalType());
2359}
2360
2361TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2362 auto Pattern = functionDecl(hasName("f"));
2363
2364 FunctionDecl *ImportedD;
2365 {
2366 Decl *FromTU =
2367 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2368 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2369 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2370 }
2371 FunctionDecl *ImportedD1;
2372 {
2373 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2374 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2375 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2376 }
2377
2378 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2379 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2380 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2381 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2382 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2383}
2384
Balazs Keri89632b82018-08-21 14:32:21 +00002385TEST_P(ImportFriendFunctions, Lookup) {
2386 auto FunctionPattern = functionDecl(hasName("f"));
2387 auto ClassPattern = cxxRecordDecl(hasName("X"));
2388
2389 TranslationUnitDecl *FromTU =
2390 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2391 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2392 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2393 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2394 {
2395 auto FromName = FromD->getDeclName();
2396 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2397 auto LookupRes = Class->noload_lookup(FromName);
2398 ASSERT_EQ(LookupRes.size(), 0u);
2399 LookupRes = FromTU->noload_lookup(FromName);
2400 ASSERT_EQ(LookupRes.size(), 1u);
2401 }
2402
2403 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2404 auto ToName = ToD->getDeclName();
2405
2406 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2407 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2408 auto LookupRes = Class->noload_lookup(ToName);
2409 EXPECT_EQ(LookupRes.size(), 0u);
2410 LookupRes = ToTU->noload_lookup(ToName);
2411 EXPECT_EQ(LookupRes.size(), 1u);
2412
2413 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2414 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2415 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2416 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2417}
2418
2419TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2420 auto FunctionPattern = functionDecl(hasName("f"));
2421 auto ClassPattern = cxxRecordDecl(hasName("X"));
2422
2423 TranslationUnitDecl *FromTU = getTuDecl(
2424 "struct X { friend void f(); };"
2425 // This proto decl makes f available to normal
2426 // lookup, otherwise it is hidden.
2427 // Normal C++ lookup (implemented in
2428 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2429 // returns the found `NamedDecl` only if the set IDNS is matched
2430 "void f();",
2431 Lang_CXX, "input0.cc");
2432 auto *FromFriend =
2433 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2434 auto *FromNormal =
2435 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2436 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2437 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2438 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2439 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2440
2441 auto FromName = FromFriend->getDeclName();
2442 auto *FromClass =
2443 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2444 auto LookupRes = FromClass->noload_lookup(FromName);
2445 ASSERT_EQ(LookupRes.size(), 0u);
2446 LookupRes = FromTU->noload_lookup(FromName);
2447 ASSERT_EQ(LookupRes.size(), 1u);
2448
2449 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2450 auto ToName = ToFriend->getDeclName();
2451
2452 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2453 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2454 LookupRes = ToClass->noload_lookup(ToName);
2455 EXPECT_EQ(LookupRes.size(), 0u);
2456 LookupRes = ToTU->noload_lookup(ToName);
2457 // Test is disabled because this result is 2.
2458 EXPECT_EQ(LookupRes.size(), 1u);
2459
2460 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2461 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2462 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2463 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2464 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2465 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2466 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2467}
2468
2469TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2470 auto FunctionPattern = functionDecl(hasName("f"));
2471 auto ClassPattern = cxxRecordDecl(hasName("X"));
2472
2473 TranslationUnitDecl *FromTU = getTuDecl(
2474 "void f();"
2475 "struct X { friend void f(); };",
2476 Lang_CXX, "input0.cc");
2477 auto *FromNormal =
2478 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2479 auto *FromFriend =
2480 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2481 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2482 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2483 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2484 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2485
2486 auto FromName = FromNormal->getDeclName();
2487 auto *FromClass =
2488 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2489 auto LookupRes = FromClass->noload_lookup(FromName);
2490 ASSERT_EQ(LookupRes.size(), 0u);
2491 LookupRes = FromTU->noload_lookup(FromName);
2492 ASSERT_EQ(LookupRes.size(), 1u);
2493
2494 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2495 auto ToName = ToNormal->getDeclName();
2496 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2497
2498 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2499 LookupRes = ToClass->noload_lookup(ToName);
2500 EXPECT_EQ(LookupRes.size(), 0u);
2501 LookupRes = ToTU->noload_lookup(ToName);
2502 EXPECT_EQ(LookupRes.size(), 1u);
2503
2504 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2505 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2506 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2507 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2508 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2509 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2510 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2511}
2512
2513TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2514 auto Pattern = functionDecl(hasName("f"));
2515
2516 TranslationUnitDecl *FromNormalTU =
2517 getTuDecl("void f();", Lang_CXX, "input0.cc");
2518 auto *FromNormalF =
2519 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2520 TranslationUnitDecl *FromFriendTU =
2521 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2522 auto *FromFriendF =
2523 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2524 auto FromNormalName = FromNormalF->getDeclName();
2525 auto FromFriendName = FromFriendF->getDeclName();
2526
2527 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2528 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2529 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2530 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2531 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2532 ASSERT_EQ(LookupRes.size(), 1u);
2533 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2534 ASSERT_EQ(LookupRes.size(), 1u);
2535
2536 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2537 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2538 auto ToName = ToNormalF->getDeclName();
2539 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2540 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2541 LookupRes = ToTU->noload_lookup(ToName);
2542 EXPECT_EQ(LookupRes.size(), 1u);
2543 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002544
Balazs Keri89632b82018-08-21 14:32:21 +00002545 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2546 LookupRes = ToTU->noload_lookup(ToName);
2547 EXPECT_EQ(LookupRes.size(), 1u);
2548 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2549
2550 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2551 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2552
2553 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2554 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2555}
2556
2557TEST_P(ImportFriendFunctions, ImportFriendList) {
2558 TranslationUnitDecl *FromTU = getTuDecl(
2559 "struct X { friend void f(); };"
2560 "void f();",
2561 Lang_CXX, "input0.cc");
2562 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2563 FromTU, functionDecl(hasName("f")));
2564
2565 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2566 FromTU, cxxRecordDecl(hasName("X")));
2567 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2568 auto FromFriends = FromClass->friends();
2569 unsigned int FrN = 0;
2570 for (auto Fr : FromFriends) {
2571 ASSERT_EQ(Fr, FromFriend);
2572 ++FrN;
2573 }
2574 ASSERT_EQ(FrN, 1u);
2575
2576 Import(FromFriendF, Lang_CXX);
2577 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2578 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2579 ToTU, cxxRecordDecl(hasName("X")));
2580 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2581 auto ToFriends = ToClass->friends();
2582 FrN = 0;
2583 for (auto Fr : ToFriends) {
2584 EXPECT_EQ(Fr, ToFriend);
2585 ++FrN;
2586 }
2587 EXPECT_EQ(FrN, 1u);
2588}
2589
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002590AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2591 InnerMatcher) {
2592 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2593 return InnerMatcher.matches(*Typedef, Finder, Builder);
2594 return false;
2595}
2596
Gabor Marton19f4f392018-06-25 13:04:37 +00002597TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002598 CodeFiles Samples{{"main.c",
2599 {"void foo();"
2600 "void moo();"
2601 "int main() { foo(); moo(); }",
2602 Lang_C}},
2603
2604 {"foo.c",
2605 {"typedef enum { THING_VALUE } thing_t;"
2606 "void conflict(thing_t type);"
2607 "void foo() { (void)THING_VALUE; }"
2608 "void conflict(thing_t type) {}",
2609 Lang_C}},
2610
2611 {"moo.c",
2612 {"typedef enum { THING_VALUE } thing_t;"
2613 "void conflict(thing_t type);"
2614 "void moo() { conflict(THING_VALUE); }",
2615 Lang_C}}};
2616
2617 auto VerificationMatcher =
2618 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2619 hasTypedefForAnonDecl(hasName("thing_t")));
2620
2621 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2622 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2623
2624 testImportSequence(
2625 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2626 // Just check that there is only one enum decl in the result AST.
2627 "main.c", enumDecl(), VerificationMatcher);
2628
2629 // For different import order, result should be the same.
2630 testImportSequence(
2631 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2632 // Check that there is only one enum decl in the result AST.
2633 "main.c", enumDecl(), VerificationMatcher);
2634}
2635
Peter Szecsice7f3182018-05-07 12:08:27 +00002636const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2637 dependentScopeDeclRefExpr;
2638
Gabor Marton19f4f392018-06-25 13:04:37 +00002639TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002640 MatchVerifier<Decl> Verifier;
2641 testImport("template <typename T> struct S { static T foo; };"
2642 "template <typename T> void declToImport() {"
2643 " (void) S<T>::foo;"
2644 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002645 "void instantiate() { declToImport<int>(); }"
2646 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002647 Lang_CXX11, "", Lang_CXX11, Verifier,
2648 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2649 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2650
2651 testImport("template <typename T> struct S {"
2652 "template<typename S> static void foo(){};"
2653 "};"
2654 "template <typename T> void declToImport() {"
2655 " S<T>::template foo<T>();"
2656 "}"
2657 "void instantiate() { declToImport<int>(); }",
2658 Lang_CXX11, "", Lang_CXX11, Verifier,
2659 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2660 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2661}
2662
2663const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2664 dependentNameType;
2665
Gabor Marton19f4f392018-06-25 13:04:37 +00002666TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002667 MatchVerifier<Decl> Verifier;
2668 testImport("template <typename T> struct declToImport {"
2669 " typedef typename T::type dependent_name;"
2670 "};",
2671 Lang_CXX11, "", Lang_CXX11, Verifier,
2672 classTemplateDecl(has(
2673 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2674}
2675
Gabor Marton19f4f392018-06-25 13:04:37 +00002676TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002677 MatchVerifier<Decl> Verifier;
2678 testImport("struct S { template <typename T> void mem(); };"
2679 "template <typename U> void declToImport() {"
2680 " S s;"
2681 " s.mem<U>();"
2682 "}"
2683 "void instantiate() { declToImport<int>(); }",
2684 Lang_CXX11, "", Lang_CXX11, Verifier,
2685 functionTemplateDecl(has(functionDecl(has(
2686 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2687}
2688
Balazs Keri1d20cc22018-07-16 12:16:39 +00002689class ImportImplicitMethods : public ASTImporterTestBase {
2690public:
2691 static constexpr auto DefaultCode = R"(
2692 struct A { int x; };
2693 void f() {
2694 A a;
2695 A a1(a);
2696 A a2(A{});
2697 a = a1;
2698 a = A{};
2699 a.~A();
2700 })";
2701
2702 template <typename MatcherType>
2703 void testImportOf(
2704 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2705 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2706 }
2707
2708 template <typename MatcherType>
2709 void testNoImportOf(
2710 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2711 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2712 }
2713
2714private:
2715 template <typename MatcherType>
2716 void test(const MatcherType &MethodMatcher,
2717 const char *Code, unsigned int ExpectedCount) {
2718 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2719
2720 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2721 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2722 ToTU, ClassMatcher);
2723
Balazs Keri2f752ba2018-07-16 14:05:18 +00002724 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002725
2726 {
2727 CXXMethodDecl *Method =
2728 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2729 ToClass->removeDecl(Method);
2730 }
2731
Balazs Keri2f752ba2018-07-16 14:05:18 +00002732 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002733
2734 Decl *ImportedClass = nullptr;
2735 {
2736 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2737 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2738 FromTU, ClassMatcher);
2739 ImportedClass = Import(FromClass, Lang_CXX11);
2740 }
2741
2742 EXPECT_EQ(ToClass, ImportedClass);
2743 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2744 ExpectedCount);
2745 }
2746};
2747
2748TEST_P(ImportImplicitMethods, DefaultConstructor) {
2749 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2750}
2751
2752TEST_P(ImportImplicitMethods, CopyConstructor) {
2753 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2754}
2755
2756TEST_P(ImportImplicitMethods, MoveConstructor) {
2757 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2758}
2759
2760TEST_P(ImportImplicitMethods, Destructor) {
2761 testImportOf(cxxDestructorDecl());
2762}
2763
2764TEST_P(ImportImplicitMethods, CopyAssignment) {
2765 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2766}
2767
2768TEST_P(ImportImplicitMethods, MoveAssignment) {
2769 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2770}
2771
2772TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2773 auto Code = R"(
2774 struct A { A() { int x; } };
2775 )";
2776 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2777}
2778
2779TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2780 auto Code = R"(
2781 struct A { A() = default; };
2782 )";
2783 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2784}
2785
2786TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2787 auto Code = R"(
2788 struct A { A() = delete; };
2789 )";
2790 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2791}
2792
2793TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2794 auto Code = R"(
2795 struct A { void f() { } };
2796 )";
2797 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2798}
2799
Balazs Keric7797c42018-07-11 09:37:24 +00002800TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
2801 Decl *ToR1;
2802 {
2803 Decl *FromTU = getTuDecl(
2804 "struct A { };", Lang_CXX, "input0.cc");
2805 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2806 FromTU, cxxRecordDecl(hasName("A")));
2807
2808 ToR1 = Import(FromR, Lang_CXX);
2809 }
2810
2811 Decl *ToR2;
2812 {
2813 Decl *FromTU = getTuDecl(
2814 "struct A { };", Lang_CXX, "input1.cc");
2815 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2816 FromTU, cxxRecordDecl(hasName("A")));
2817
2818 ToR2 = Import(FromR, Lang_CXX);
2819 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00002820
Balazs Keric7797c42018-07-11 09:37:24 +00002821 EXPECT_EQ(ToR1, ToR2);
2822}
2823
2824TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
2825 Decl *ToR1;
2826 {
2827 Decl *FromTU = getTuDecl(
2828 "struct A { int x; };", Lang_CXX, "input0.cc");
2829 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2830 FromTU, cxxRecordDecl(hasName("A")));
2831 ToR1 = Import(FromR, Lang_CXX);
2832 }
2833 Decl *ToR2;
2834 {
2835 Decl *FromTU = getTuDecl(
2836 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2837 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2838 FromTU, cxxRecordDecl(hasName("A")));
2839 ToR2 = Import(FromR, Lang_CXX);
2840 }
2841 EXPECT_NE(ToR1, ToR2);
2842}
2843
2844TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
2845 Decl *ToF1;
2846 {
2847 Decl *FromTU = getTuDecl(
2848 "struct A { int x; };", Lang_CXX, "input0.cc");
2849 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2850 FromTU, fieldDecl(hasName("x")));
2851 ToF1 = Import(FromF, Lang_CXX);
2852 }
2853 Decl *ToF2;
2854 {
2855 Decl *FromTU = getTuDecl(
2856 "struct A { int x; };", Lang_CXX, "input1.cc");
2857 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2858 FromTU, fieldDecl(hasName("x")));
2859 ToF2 = Import(FromF, Lang_CXX);
2860 }
2861 EXPECT_EQ(ToF1, ToF2);
2862}
2863
2864TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
2865 Decl *ToF1;
2866 {
2867 Decl *FromTU = getTuDecl(
2868 "struct A { int x; };", Lang_CXX, "input0.cc");
2869 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2870 FromTU, fieldDecl(hasName("x")));
2871 ToF1 = Import(FromF, Lang_CXX);
2872 }
2873 Decl *ToF2;
2874 {
2875 Decl *FromTU = getTuDecl(
2876 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2877 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2878 FromTU, fieldDecl(hasName("x")));
2879 ToF2 = Import(FromF, Lang_CXX);
2880 }
2881 EXPECT_NE(ToF1, ToF2);
2882}
2883
2884TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
2885 Decl *ToM1;
2886 {
2887 Decl *FromTU = getTuDecl(
2888 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2889 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2890 FromTU, functionDecl(hasName("x"), isDefinition()));
2891 ToM1 = Import(FromM, Lang_CXX);
2892 }
2893 Decl *ToM2;
2894 {
2895 Decl *FromTU = getTuDecl(
2896 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2897 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2898 FromTU, functionDecl(hasName("x"), isDefinition()));
2899 ToM2 = Import(FromM, Lang_CXX);
2900 }
2901 EXPECT_EQ(ToM1, ToM2);
2902}
2903
2904TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
2905 Decl *ToM1;
2906 {
2907 Decl *FromTU = getTuDecl(
2908 "struct A { void x(); }; void A::x() { }",
2909 Lang_CXX, "input0.cc");
2910 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2911 FromTU, functionDecl(hasName("x"), isDefinition()));
2912 ToM1 = Import(FromM, Lang_CXX);
2913 }
2914 Decl *ToM2;
2915 {
2916 Decl *FromTU = getTuDecl(
2917 "struct A { void x() const; }; void A::x() const { }",
2918 Lang_CXX, "input1.cc");
2919 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2920 FromTU, functionDecl(hasName("x"), isDefinition()));
2921 ToM2 = Import(FromM, Lang_CXX);
2922 }
2923 EXPECT_NE(ToM1, ToM2);
2924}
2925
Gabor Martonf086fa82018-07-17 12:06:36 +00002926TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
2927 Decl *FromTU = getTuDecl(
2928 R"(
2929 struct A {
2930 struct {
2931 struct A *next;
2932 } entry0;
2933 struct {
2934 struct A *next;
2935 } entry1;
2936 };
2937 )",
2938 Lang_C, "input0.cc");
2939 auto *From =
2940 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
2941
2942 Import(From, Lang_C);
2943
2944 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2945 auto *Entry0 =
2946 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
2947 auto *Entry1 =
2948 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
2949 auto *R0 = getRecordDecl(Entry0);
2950 auto *R1 = getRecordDecl(Entry1);
2951 EXPECT_NE(R0, R1);
2952 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2953 R0, recordDecl(has(fieldDecl(hasName("next"))))));
2954 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2955 R1, recordDecl(has(fieldDecl(hasName("next"))))));
2956}
2957
Balazs Keri2544b4b2018-08-08 09:40:57 +00002958TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
2959 Decl *FromTU = getTuDecl(
2960 R"(
2961 void f(int X, int Y, bool Z) {
2962 (void)[X, Y, Z] { (void)Z; };
2963 }
2964 )",
2965 Lang_CXX11, "input0.cc");
2966 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
2967 FromTU, functionDecl(hasName("f")));
2968 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
2969 EXPECT_TRUE(ToF);
2970
2971 CXXRecordDecl *FromLambda =
2972 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
2973 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
2974
2975 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
2976 EXPECT_TRUE(ToLambda);
2977
2978 // Check if the fields of the lambda class are imported in correct order.
2979 unsigned FromIndex = 0u;
2980 for (auto *FromField : FromLambda->fields()) {
2981 ASSERT_FALSE(FromField->getDeclName());
2982 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
2983 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00002984 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
2985 EXPECT_TRUE(ToIndex);
2986 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00002987 ++FromIndex;
2988 }
2989
2990 EXPECT_EQ(FromIndex, 3u);
2991}
2992
Gabor Marton42e15de2018-08-22 11:52:14 +00002993TEST_P(ASTImporterTestBase, MergeFieldDeclsOfClassTemplateSpecialization) {
2994 std::string ClassTemplate =
2995 R"(
2996 template <typename T>
2997 struct X {
2998 int a{0}; // FieldDecl with InitListExpr
2999 X(char) : a(3) {} // (1)
3000 X(int) {} // (2)
3001 };
3002 )";
3003 Decl *ToTU = getToTuDecl(ClassTemplate +
3004 R"(
3005 void foo() {
3006 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3007 X<char> xc('c');
3008 }
3009 )", Lang_CXX11);
3010 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3011 ToTU, classTemplateSpecializationDecl(hasName("X")));
3012 // FieldDecl without InitlistExpr:
3013 auto *ToField = *ToSpec->field_begin();
3014 ASSERT_TRUE(ToField);
3015 ASSERT_FALSE(ToField->getInClassInitializer());
3016 Decl *FromTU = getTuDecl(ClassTemplate +
3017 R"(
3018 void bar() {
3019 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3020 X<char> xc(1);
3021 }
3022 )", Lang_CXX11);
3023 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3024 FromTU, classTemplateSpecializationDecl(hasName("X")));
3025 // FieldDecl with InitlistExpr:
3026 auto *FromField = *FromSpec->field_begin();
3027 ASSERT_TRUE(FromField);
3028 ASSERT_TRUE(FromField->getInClassInitializer());
3029
3030 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3031 ASSERT_TRUE(ImportedSpec);
3032 EXPECT_EQ(ImportedSpec, ToSpec);
3033 // After the import, the FieldDecl has to be merged, thus it should have the
3034 // InitListExpr.
3035 EXPECT_TRUE(ToField->getInClassInitializer());
3036}
3037
3038TEST_P(ASTImporterTestBase, MergeFunctionOfClassTemplateSpecialization) {
3039 std::string ClassTemplate =
3040 R"(
3041 template <typename T>
3042 struct X {
3043 void f() {}
3044 void g() {}
3045 };
3046 )";
3047 Decl *ToTU = getToTuDecl(ClassTemplate +
3048 R"(
3049 void foo() {
3050 X<char> x;
3051 x.f();
3052 }
3053 )", Lang_CXX11);
3054 Decl *FromTU = getTuDecl(ClassTemplate +
3055 R"(
3056 void bar() {
3057 X<char> x;
3058 x.g();
3059 }
3060 )", Lang_CXX11);
3061 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3062 FromTU, classTemplateSpecializationDecl(hasName("X")));
3063 auto FunPattern = functionDecl(hasName("g"),
3064 hasParent(classTemplateSpecializationDecl()));
3065 auto *FromFun =
3066 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3067 auto *ToFun =
3068 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3069 ASSERT_TRUE(FromFun->hasBody());
3070 ASSERT_FALSE(ToFun->hasBody());
3071 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3072 ASSERT_TRUE(ImportedSpec);
3073 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3074 ToTU, classTemplateSpecializationDecl(hasName("X")));
3075 EXPECT_EQ(ImportedSpec, ToSpec);
3076 EXPECT_TRUE(ToFun->hasBody());
3077}
3078
3079TEST_P(ASTImporterTestBase,
3080 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3081 std::string ClassTemplate =
3082 R"(
3083 template <typename T>
3084 struct X {};
3085 )";
3086 Decl *ToTU = getToTuDecl(ClassTemplate +
3087 R"(
3088 template <>
3089 struct X<char> {
3090 int a;
3091 };
3092 void foo() {
3093 X<char> x;
3094 }
3095 )",
3096 Lang_CXX11);
3097 Decl *FromTU = getTuDecl(ClassTemplate +
3098 R"(
3099 template <>
3100 struct X<char> {
3101 int b;
3102 };
3103 void foo() {
3104 X<char> x;
3105 }
3106 )",
3107 Lang_CXX11);
3108 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3109 FromTU, classTemplateSpecializationDecl(hasName("X")));
3110 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3111
3112 // We expect one (ODR) warning during the import.
3113 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3114
3115 // The second specialization is different from the first, thus it violates
3116 // ODR, consequently we expect to keep the first specialization only, which is
3117 // already in the "To" context.
3118 EXPECT_TRUE(ImportedSpec);
3119 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3120 ToTU, classTemplateSpecializationDecl(hasName("X")));
3121 EXPECT_EQ(ImportedSpec, ToSpec);
3122 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3123 ToTU, classTemplateSpecializationDecl()));
3124}
3125
3126TEST_P(ASTImporterTestBase, MergeCtorOfClassTemplateSpecialization) {
3127 std::string ClassTemplate =
3128 R"(
3129 template <typename T>
3130 struct X {
3131 X(char) {}
3132 X(int) {}
3133 };
3134 )";
3135 Decl *ToTU = getToTuDecl(ClassTemplate +
3136 R"(
3137 void foo() {
3138 X<char> x('c');
3139 }
3140 )", Lang_CXX11);
3141 Decl *FromTU = getTuDecl(ClassTemplate +
3142 R"(
3143 void bar() {
3144 X<char> x(1);
3145 }
3146 )", Lang_CXX11);
3147 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3148 FromTU, classTemplateSpecializationDecl(hasName("X")));
3149 // Match the void(int) ctor.
3150 auto CtorPattern =
3151 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3152 hasParent(classTemplateSpecializationDecl()));
3153 auto *FromCtor =
3154 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3155 auto *ToCtor =
3156 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3157 ASSERT_TRUE(FromCtor->hasBody());
3158 ASSERT_FALSE(ToCtor->hasBody());
3159 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3160 ASSERT_TRUE(ImportedSpec);
3161 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3162 ToTU, classTemplateSpecializationDecl(hasName("X")));
3163 EXPECT_EQ(ImportedSpec, ToSpec);
3164 EXPECT_TRUE(ToCtor->hasBody());
3165}
3166
3167TEST_P(ASTImporterTestBase,
3168 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3169 auto Code =
3170 R"(
3171 // primary template
3172 template<class T1, class T2, int I>
3173 class A {};
3174
3175 // partial specialization
3176 template<class T, int I>
3177 class A<T, T*, I> {};
3178 )";
3179 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3180 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3181 auto *FromSpec =
3182 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3183 FromTU, classTemplatePartialSpecializationDecl());
3184 auto *ToSpec =
3185 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3186 ToTU, classTemplatePartialSpecializationDecl());
3187
3188 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3189 EXPECT_EQ(ImportedSpec, ToSpec);
3190 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3191 ToTU, classTemplatePartialSpecializationDecl()));
3192}
3193
3194TEST_P(ASTImporterTestBase, ClassTemplateSpecializationsShouldNotBeDuplicated) {
3195 auto Code =
3196 R"(
3197 // primary template
3198 template<class T1, class T2, int I>
3199 class A {};
3200
3201 // full specialization
3202 template<>
3203 class A<int, int, 1> {};
3204 )";
3205 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3206 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3207 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3208 FromTU, classTemplateSpecializationDecl());
3209 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3210 ToTU, classTemplateSpecializationDecl());
3211
3212 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3213 EXPECT_EQ(ImportedSpec, ToSpec);
3214 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3215 ToTU, classTemplateSpecializationDecl()));
3216}
3217
3218TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3219 std::string PrimaryTemplate =
3220 R"(
3221 template<class T1, class T2, int I>
3222 class A {};
3223 )";
3224 auto PartialSpec =
3225 R"(
3226 template<class T, int I>
3227 class A<T, T*, I> {};
3228 )";
3229 auto FullSpec =
3230 R"(
3231 template<>
3232 class A<int, int, 1> {};
3233 )";
3234 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3235 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3236 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3237 FromTU, classTemplateSpecializationDecl());
3238
3239 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3240 EXPECT_TRUE(ImportedSpec);
3241 // Check the number of partial specializations.
3242 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3243 ToTU, classTemplatePartialSpecializationDecl()));
3244 // Check the number of full specializations.
3245 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3246 ToTU, classTemplateSpecializationDecl(
3247 unless(classTemplatePartialSpecializationDecl()))));
3248}
3249
Gabor Martona20ce602018-09-03 13:10:53 +00003250TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
3251 Decl *TU = getTuDecl(
3252 R"(
3253 const int &init();
3254 void foo() { const int &a{init()}; }
3255 )", Lang_CXX11, "input0.cc");
3256 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3257 ASSERT_TRUE(FromD->getAnyInitializer());
3258 auto *InitExpr = FromD->getAnyInitializer();
3259 ASSERT_TRUE(InitExpr);
3260 ASSERT_TRUE(InitExpr->isGLValue());
3261
3262 auto *ToD = Import(FromD, Lang_CXX11);
3263 EXPECT_TRUE(ToD);
3264 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3265 EXPECT_TRUE(ToInitExpr);
3266 EXPECT_TRUE(ToInitExpr->isGLValue());
3267}
3268
Gabor Martonac3a5d62018-09-17 12:04:52 +00003269struct ImportVariables : ASTImporterTestBase {};
3270
3271TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3272 Decl *FromTU = getTuDecl(
3273 R"(
3274 struct A {
3275 static const int a = 1 + 2;
3276 };
3277 const int A::a;
3278 )", Lang_CXX, "input1.cc");
3279
3280 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3281 FromTU, varDecl(hasName("a"))); // Decl with init
3282 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3283 FromTU, varDecl(hasName("a"))); // Decl with definition
3284 ASSERT_NE(FromDWithInit, FromDWithDef);
3285 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3286
3287 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3288 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3289 ASSERT_TRUE(ToD0);
3290 ASSERT_TRUE(ToD1);
3291 EXPECT_NE(ToD0, ToD1);
3292 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3293}
3294
3295TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3296 auto StructA =
3297 R"(
3298 struct A {
3299 static const int a = 1 + 2;
3300 };
3301 )";
3302 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3303 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3304 "input1.cc");
3305
3306 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3307 FromTU, varDecl(hasName("a"))); // Decl with init
3308 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3309 FromTU, varDecl(hasName("a"))); // Decl with definition
3310 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3311 ASSERT_TRUE(FromDWithInit->getInit());
3312 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3313 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3314 ASSERT_FALSE(FromDWithDef->getInit());
3315
3316 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3317 ToTU, varDecl(hasName("a"))); // Decl with init
3318 ASSERT_TRUE(ToD->getInit());
3319 ASSERT_FALSE(ToD->getDefinition());
3320
3321 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3322 EXPECT_TRUE(ImportedD->getAnyInitializer());
3323 EXPECT_TRUE(ImportedD->getDefinition());
3324}
3325
3326TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3327 auto StructA =
3328 R"(
3329 struct A {
3330 static const int a;
3331 };
3332 )";
3333 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3334 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3335 Lang_CXX, "input1.cc");
3336
3337 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3338 FromTU, varDecl(hasName("a")));
3339 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3340 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3341 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3342 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3343 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3344 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3345 ASSERT_TRUE(FromDWithDef->getInit());
3346
3347 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3348 ToTU, varDecl(hasName("a")));
3349 ASSERT_FALSE(ToD->getInit());
3350 ASSERT_FALSE(ToD->getDefinition());
3351
3352 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3353 EXPECT_TRUE(ImportedD->getAnyInitializer());
3354 EXPECT_TRUE(ImportedD->getDefinition());
3355}
3356
Gabor Marton7df342a2018-12-17 12:42:12 +00003357struct ImportClasses : ASTImporterTestBase {};
3358
3359TEST_P(ImportClasses,
3360 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
3361 Decl *FromTU = getTuDecl("class X;", Lang_CXX);
3362 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3363 auto FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3364
3365 Decl *ImportedD = Import(FromD, Lang_CXX);
3366 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3367
3368 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
3369 auto ToD = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3370 EXPECT_TRUE(ImportedD == ToD);
3371 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
3372}
3373
3374TEST_P(ImportClasses, ImportPrototypeAfterImportedPrototype) {
3375 Decl *FromTU = getTuDecl("class X; class X;", Lang_CXX);
3376 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3377 auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3378 auto From1 = LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3379
3380 Decl *Imported0 = Import(From0, Lang_CXX);
3381 Decl *Imported1 = Import(From1, Lang_CXX);
3382 Decl *ToTU = Imported0->getTranslationUnitDecl();
3383
3384 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3385 auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3386 auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3387 EXPECT_TRUE(Imported0 == To0);
3388 EXPECT_TRUE(Imported1 == To1);
3389 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3390 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3391 EXPECT_EQ(To1->getPreviousDecl(), To0);
3392}
3393
3394TEST_P(ImportClasses, DefinitionShouldBeImportedAsADefinition) {
3395 Decl *FromTU = getTuDecl("class X {};", Lang_CXX);
3396 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3397 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3398
3399 Decl *ImportedD = Import(FromD, Lang_CXX);
3400 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3401
3402 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
3403 EXPECT_TRUE(cast<CXXRecordDecl>(ImportedD)->isThisDeclarationADefinition());
3404}
3405
3406TEST_P(ImportClasses, ImportPrototypeFromDifferentTUAfterImportedPrototype) {
3407 Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
3408 Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
3409 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3410 auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3411 auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3412
3413 Decl *Imported0 = Import(From0, Lang_CXX);
3414 Decl *Imported1 = Import(From1, Lang_CXX);
3415 Decl *ToTU = Imported0->getTranslationUnitDecl();
3416
3417 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3418 auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3419 auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3420 EXPECT_TRUE(Imported0 == To0);
3421 EXPECT_TRUE(Imported1 == To1);
3422 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3423 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3424 EXPECT_EQ(To1->getPreviousDecl(), To0);
3425}
3426
3427TEST_P(ImportClasses, ImportDefinitions) {
3428 Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
3429 Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
3430 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3431 auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3432 auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3433
3434 Decl *Imported0 = Import(From0, Lang_CXX);
3435 Decl *Imported1 = Import(From1, Lang_CXX);
3436 Decl *ToTU = Imported0->getTranslationUnitDecl();
3437
3438 EXPECT_EQ(Imported0, Imported1);
3439 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
3440 auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3441 EXPECT_TRUE(Imported0 == To0);
3442 EXPECT_TRUE(To0->isThisDeclarationADefinition());
3443}
3444
3445TEST_P(ImportClasses, ImportDefinitionThenPrototype) {
3446 Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
3447 Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
3448 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3449 auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3450 auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3451
3452 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3453 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3454 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3455
3456 EXPECT_NE(ImportedDef, ImportedProto);
3457 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3458 auto ToDef = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3459 auto ToProto = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3460 EXPECT_TRUE(ImportedDef == ToDef);
3461 EXPECT_TRUE(ImportedProto == ToProto);
3462 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3463 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3464 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
3465}
3466
3467TEST_P(ImportClasses, ImportPrototypeThenDefinition) {
3468 Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
3469 Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
3470 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3471 auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3472 auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3473
3474 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3475 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3476 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3477
3478 EXPECT_NE(ImportedDef, ImportedProto);
3479 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3480 auto ToProto = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3481 auto ToDef = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3482 EXPECT_TRUE(ImportedDef == ToDef);
3483 EXPECT_TRUE(ImportedProto == ToProto);
3484 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3485 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3486 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3487}
3488
3489struct ImportClassTemplates : ASTImporterTestBase {};
3490
3491TEST_P(ImportClassTemplates,
3492 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
3493 Decl *FromTU = getTuDecl("template <class T> class X;", Lang_CXX);
3494 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3495 auto FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3496
3497 Decl *ImportedD = Import(FromD, Lang_CXX);
3498 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3499
3500 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
3501 auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3502 EXPECT_TRUE(ImportedD == ToD);
3503 ASSERT_TRUE(ToD->getTemplatedDecl());
3504 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
3505}
3506
3507TEST_P(ImportClassTemplates, ImportPrototypeAfterImportedPrototype) {
3508 Decl *FromTU = getTuDecl(
3509 "template <class T> class X; template <class T> class X;", Lang_CXX);
3510 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3511 auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3512 auto From1 = LastDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3513
3514 Decl *Imported0 = Import(From0, Lang_CXX);
3515 Decl *Imported1 = Import(From1, Lang_CXX);
3516 Decl *ToTU = Imported0->getTranslationUnitDecl();
3517
3518 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3519 auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3520 auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3521 EXPECT_TRUE(Imported0 == To0);
3522 EXPECT_TRUE(Imported1 == To1);
3523 ASSERT_TRUE(To0->getTemplatedDecl());
3524 ASSERT_TRUE(To1->getTemplatedDecl());
3525 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3526 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3527 EXPECT_EQ(To1->getPreviousDecl(), To0);
3528 EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
3529 To0->getTemplatedDecl());
3530}
3531
3532TEST_P(ImportClassTemplates, DefinitionShouldBeImportedAsADefinition) {
3533 Decl *FromTU = getTuDecl("template <class T> class X {};", Lang_CXX);
3534 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3535 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3536
3537 Decl *ImportedD = Import(FromD, Lang_CXX);
3538 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3539
3540 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
3541 auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3542 ASSERT_TRUE(ToD->getTemplatedDecl());
3543 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
3544}
3545
3546TEST_P(ImportClassTemplates,
3547 ImportPrototypeFromDifferentTUAfterImportedPrototype) {
3548 Decl *FromTU0 =
3549 getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
3550 Decl *FromTU1 =
3551 getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
3552 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3553 auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3554 auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3555
3556 Decl *Imported0 = Import(From0, Lang_CXX);
3557 Decl *Imported1 = Import(From1, Lang_CXX);
3558 Decl *ToTU = Imported0->getTranslationUnitDecl();
3559
3560 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3561 auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3562 auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3563 EXPECT_TRUE(Imported0 == To0);
3564 EXPECT_TRUE(Imported1 == To1);
3565 ASSERT_TRUE(To0->getTemplatedDecl());
3566 ASSERT_TRUE(To1->getTemplatedDecl());
3567 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3568 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3569 EXPECT_EQ(To1->getPreviousDecl(), To0);
3570 EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
3571 To0->getTemplatedDecl());
3572}
3573
3574TEST_P(ImportClassTemplates, ImportDefinitions) {
3575 Decl *FromTU0 =
3576 getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
3577 Decl *FromTU1 =
3578 getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
3579 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3580 auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3581 auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3582
3583 Decl *Imported0 = Import(From0, Lang_CXX);
3584 Decl *Imported1 = Import(From1, Lang_CXX);
3585 Decl *ToTU = Imported0->getTranslationUnitDecl();
3586
3587 EXPECT_EQ(Imported0, Imported1);
3588 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
3589 auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3590 EXPECT_TRUE(Imported0 == To0);
3591 ASSERT_TRUE(To0->getTemplatedDecl());
3592 EXPECT_TRUE(To0->isThisDeclarationADefinition());
3593}
3594
3595TEST_P(ImportClassTemplates, ImportDefinitionThenPrototype) {
3596 Decl *FromTU0 =
3597 getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
3598 Decl *FromTU1 =
3599 getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
3600 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3601 auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3602 auto FromProto =
3603 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3604
3605 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3606 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3607 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3608
3609 EXPECT_NE(ImportedDef, ImportedProto);
3610 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3611 auto ToDef = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3612 auto ToProto = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3613 EXPECT_TRUE(ImportedDef == ToDef);
3614 EXPECT_TRUE(ImportedProto == ToProto);
3615 ASSERT_TRUE(ToDef->getTemplatedDecl());
3616 ASSERT_TRUE(ToProto->getTemplatedDecl());
3617 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3618 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3619 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
3620 EXPECT_EQ(ToProto->getTemplatedDecl()->getPreviousDecl(),
3621 ToDef->getTemplatedDecl());
3622}
3623
3624TEST_P(ImportClassTemplates, ImportPrototypeThenDefinition) {
3625 Decl *FromTU0 =
3626 getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
3627 Decl *FromTU1 =
3628 getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
3629 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3630 auto FromProto =
3631 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3632 auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3633
3634 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3635 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3636 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3637
3638 EXPECT_NE(ImportedDef, ImportedProto);
3639 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3640 auto ToProto = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3641 auto ToDef = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3642 EXPECT_TRUE(ImportedDef == ToDef);
3643 EXPECT_TRUE(ImportedProto == ToProto);
3644 ASSERT_TRUE(ToProto->getTemplatedDecl());
3645 ASSERT_TRUE(ToDef->getTemplatedDecl());
3646 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3647 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3648 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3649 EXPECT_EQ(ToDef->getTemplatedDecl()->getPreviousDecl(),
3650 ToProto->getTemplatedDecl());
3651}
3652
3653struct ImportFriendClasses : ASTImporterTestBase {};
3654
3655TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3656 Decl *FromTU = getTuDecl(
3657 R"(
3658 class A {
3659 template <int I> class F {};
3660 class X {
3661 template <int I> friend class F;
3662 };
3663 };
3664 )",
3665 Lang_CXX, "input0.cc");
3666
3667 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3668 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3669 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3670 FromTU, cxxRecordDecl(hasName("F")));
3671
3672 ASSERT_TRUE(FromClass);
3673 ASSERT_TRUE(FromFriendClass);
3674 ASSERT_NE(FromClass, FromFriendClass);
3675 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3676 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3677 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3678 FromClass->getDescribedClassTemplate());
3679
3680 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3681 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3682
3683 EXPECT_TRUE(ToClass);
3684 EXPECT_TRUE(ToFriendClass);
3685 EXPECT_NE(ToClass, ToFriendClass);
3686 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3687 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3688 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3689 ToClass->getDescribedClassTemplate());
3690}
3691
3692TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3693 Decl *FromTu = getTuDecl(
3694 R"(
3695 class declToImport {
3696 friend class declToImport;
3697 };
3698 )",
3699 Lang_CXX, "input.cc");
3700
3701 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3702 FromTu, cxxRecordDecl(hasName("declToImport")));
3703 auto *ToD = Import(FromD, Lang_CXX);
3704 auto Pattern = cxxRecordDecl(has(friendDecl()));
3705 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3706 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3707}
3708
3709TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3710 Decl *FromTu = getTuDecl(
3711 R"(
3712 template<class A> class declToImport {
3713 template<class A1> friend class declToImport;
3714 };
3715 )",
3716 Lang_CXX, "input.cc");
3717
3718 auto *FromD =
3719 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3720 auto *ToD = Import(FromD, Lang_CXX);
3721
3722 auto Pattern = classTemplateDecl(
3723 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3724 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3725 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3726
3727 auto *Class =
3728 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3729 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3730 EXPECT_NE(Friend->getFriendDecl(), Class);
3731 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3732}
3733
3734TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3735 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3736
3737 ClassTemplateSpecializationDecl *Imported1;
3738 {
3739 Decl *FromTU = getTuDecl("template<class T> class X;"
3740 "struct Y { friend class X<int>; };",
3741 Lang_CXX, "input0.cc");
3742 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3743 FromTU, Pattern);
3744
3745 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3746 }
3747 ClassTemplateSpecializationDecl *Imported2;
3748 {
3749 Decl *FromTU = getTuDecl("template<class T> class X;"
3750 "template<> class X<int>{};"
3751 "struct Z { friend class X<int>; };",
3752 Lang_CXX, "input1.cc");
3753 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3754 FromTU, Pattern);
3755
3756 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3757 }
3758
3759 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3760 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3761 2u);
3762 ASSERT_TRUE(Imported2->getPreviousDecl());
3763 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3764}
3765
3766TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3767 Decl *FromTU0 = getTuDecl(
3768 R"(
3769 class X {
3770 class Y;
3771 };
3772 class X::Y {
3773 template <typename T>
3774 friend class F; // The decl context of F is the global namespace.
3775 };
3776 )",
3777 Lang_CXX, "input0.cc");
3778 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3779 FromTU0, classTemplateDecl(hasName("F")));
3780 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3781 Decl *FromTU1 = getTuDecl(
3782 R"(
3783 template <typename T>
3784 class F {};
3785 )",
3786 Lang_CXX, "input1.cc");
3787 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3788 FromTU1, classTemplateDecl(hasName("F")));
3789 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3790 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3791 Imported1->getTemplatedDecl()->getTypeForDecl());
3792}
3793
3794TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3795 Decl *From, *To;
3796 std::tie(From, To) =
3797 getImportedDecl("class declToImport {};", Lang_CXX,
3798 "class Y { friend class declToImport; };", Lang_CXX);
3799 auto *Imported = cast<CXXRecordDecl>(To);
3800
3801 EXPECT_TRUE(Imported->getPreviousDecl());
3802}
3803
3804TEST_P(ImportFriendClasses,
3805 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3806 Decl *ToTU = getToTuDecl(
3807 R"(
3808 class X {
3809 class Y;
3810 };
3811 class X::Y {
3812 template <typename T>
3813 friend class F; // The decl context of F is the global namespace.
3814 };
3815 )",
3816 Lang_CXX);
3817 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3818 ToTU, classTemplateDecl(hasName("F")));
3819 Decl *FromTU = getTuDecl(
3820 R"(
3821 template <typename T>
3822 class F {};
3823 )",
3824 Lang_CXX, "input0.cc");
3825 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3826 FromTU, classTemplateDecl(hasName("F")));
3827 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3828 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3829 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3830 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3831 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3832}
3833
3834TEST_P(ImportFriendClasses,
3835 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3836 Decl *FromTU0 = getTuDecl(
3837 R"(
3838 class X {
3839 class Y;
3840 };
3841 class X::Y {
3842 template <typename T>
3843 friend class F; // The decl context of F is the global namespace.
3844 };
3845 )",
3846 Lang_CXX, "input0.cc");
3847 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3848 FromTU0, classTemplateDecl(hasName("F")));
3849 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3850 Decl *FromTU1 = getTuDecl(
3851 R"(
3852 template <typename T>
3853 class F {};
3854 )",
3855 Lang_CXX, "input1.cc");
3856 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3857 FromTU1, classTemplateDecl(hasName("F")));
3858 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3859 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3860 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3861 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3862 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3863}
3864
3865TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3866 Decl *FromTU0 = getTuDecl(
3867 R"(
3868 class X {
3869 class Y;
3870 };
3871 class X::Y {
3872 friend class F; // The decl context of F is the global namespace.
3873 };
3874 )",
3875 Lang_CXX, "input0.cc");
3876 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3877 QualType FT = Friend->getFriendType()->getType();
3878 FT = FromTU0->getASTContext().getCanonicalType(FT);
3879 auto *Fwd = cast<TagType>(FT)->getDecl();
3880 auto *ImportedFwd = Import(Fwd, Lang_CXX);
3881 Decl *FromTU1 = getTuDecl(
3882 R"(
3883 class F {};
3884 )",
3885 Lang_CXX, "input1.cc");
3886 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
3887 FromTU1, cxxRecordDecl(hasName("F")));
3888 auto *ImportedDef = Import(Definition, Lang_CXX);
3889 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3890 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3891}
3892
Gabor Marton61d862a2018-05-18 09:08:47 +00003893struct DeclContextTest : ASTImporterTestBase {};
3894
3895TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3896 Decl *TU = getTuDecl(
3897 R"(
3898 namespace NS {
3899
3900 template <typename T>
3901 struct S {};
3902 template struct S<int>;
3903
3904 inline namespace INS {
3905 template <typename T>
3906 struct S {};
3907 template struct S<int>;
3908 }
3909
3910 }
3911 )", Lang_CXX11, "input0.cc");
3912 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
3913 TU, namespaceDecl());
3914 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3915 TU, classTemplateSpecializationDecl());
3916 ASSERT_TRUE(NS->containsDecl(Spec));
3917
3918 NS->removeDecl(Spec);
3919 EXPECT_FALSE(NS->containsDecl(Spec));
3920}
3921
Gabor Marton7df342a2018-12-17 12:42:12 +00003922TEST_P(DeclContextTest,
3923 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
3924 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
3925 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3926 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3927
3928 // Investigate the list.
3929 auto *DC = A0->getDeclContext();
3930 ASSERT_TRUE(DC->containsDecl(A0));
3931 ASSERT_TRUE(DC->containsDecl(A1));
3932
3933 // Investigate the lookup table.
3934 auto *Map = DC->getLookupPtr();
3935 ASSERT_TRUE(Map);
3936 auto I = Map->find(A0->getDeclName());
3937 ASSERT_NE(I, Map->end());
3938 StoredDeclsList &L = I->second;
3939 // The lookup table contains the most recent decl of A.
3940 ASSERT_NE(L.getAsDecl(), A0);
3941 ASSERT_EQ(L.getAsDecl(), A1);
3942
3943 ASSERT_TRUE(L.getAsDecl());
3944 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
3945 // The point here is to have a Vec with only one element, which is not the
3946 // one we are going to delete from the DC later.
3947 L.setHasExternalDecls();
3948 ASSERT_TRUE(L.getAsVector());
3949 ASSERT_EQ(1u, L.getAsVector()->size());
3950
3951 // This asserts in the old implementation.
3952 DC->removeDecl(A0);
3953 EXPECT_FALSE(DC->containsDecl(A0));
3954}
3955
Gabor Marton5254e642018-06-27 13:32:50 +00003956struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
3957
3958TEST_P(ImportFunctionTemplateSpecializations,
3959 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
3960
3961 Decl *FromTU = getTuDecl(
3962 R"(
3963 template<class T>
3964 int f() { return 0; }
3965 void foo() { f<int>(); }
3966 )",
3967 Lang_CXX, "input0.cc");
3968
3969 // Check that the function template instantiation is NOT the child of the TU.
3970 auto Pattern = translationUnitDecl(
3971 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
3972 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3973
3974 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
3975 FromTU, functionDecl(hasName("foo")));
3976 ASSERT_TRUE(Import(Foo, Lang_CXX));
3977
3978 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3979 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3980}
3981
3982TEST_P(ImportFunctionTemplateSpecializations,
3983 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
3984
3985 Decl *FromTU = getTuDecl(
3986 R"(
3987 template<class T>
3988 int f() { return 0; }
3989 template int f<int>();
3990 )",
3991 Lang_CXX, "input0.cc");
3992
3993 // Check that the function template instantiation is NOT the child of the TU.
3994 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
3995 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
3996 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3997
3998 ASSERT_TRUE(
3999 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4000
4001 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4002 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4003}
4004
4005TEST_P(ImportFunctionTemplateSpecializations,
4006 TUshouldContainFunctionTemplateSpecialization) {
4007
4008 Decl *FromTU = getTuDecl(
4009 R"(
4010 template<class T>
4011 int f() { return 0; }
4012 template <> int f<int>() { return 4; }
4013 )",
4014 Lang_CXX, "input0.cc");
4015
4016 // Check that the function template specialization is the child of the TU.
4017 auto Specialization =
4018 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4019 auto Pattern = translationUnitDecl(has(Specialization));
4020 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4021
4022 ASSERT_TRUE(
4023 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4024
4025 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4026 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4027}
4028
4029TEST_P(ImportFunctionTemplateSpecializations,
4030 FunctionTemplateSpecializationRedeclChain) {
4031
4032 Decl *FromTU = getTuDecl(
4033 R"(
4034 template<class T>
4035 int f() { return 0; }
4036 template <> int f<int>() { return 4; }
4037 )",
4038 Lang_CXX, "input0.cc");
4039
4040 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4041 hasParent(translationUnitDecl()));
4042 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4043 {
4044 auto *TU = FromTU;
4045 auto *SpecD = FromSpecD;
4046 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4047 TU, functionTemplateDecl());
4048 auto *FirstSpecD = *(TemplateD->spec_begin());
4049 ASSERT_EQ(SpecD, FirstSpecD);
4050 ASSERT_TRUE(SpecD->getPreviousDecl());
4051 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4052 ->doesThisDeclarationHaveABody());
4053 }
4054
4055 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4056
4057 {
4058 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4059 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4060 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4061 TU, functionTemplateDecl());
4062 auto *FirstSpecD = *(TemplateD->spec_begin());
4063 EXPECT_EQ(SpecD, FirstSpecD);
4064 ASSERT_TRUE(SpecD->getPreviousDecl());
4065 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4066 ->doesThisDeclarationHaveABody());
4067 }
4068}
4069
4070TEST_P(ImportFunctionTemplateSpecializations,
4071 MatchNumberOfFunctionTemplateSpecializations) {
4072
4073 Decl *FromTU = getTuDecl(
4074 R"(
4075 template <typename T> constexpr int f() { return 0; }
4076 template <> constexpr int f<int>() { return 4; }
4077 void foo() {
4078 static_assert(f<char>() == 0, "");
4079 static_assert(f<int>() == 4, "");
4080 }
4081 )",
4082 Lang_CXX11, "input0.cc");
4083 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4084 FromTU, functionDecl(hasName("foo")));
4085
4086 Import(FromD, Lang_CXX11);
4087 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4088 EXPECT_EQ(
4089 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4090 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4091}
4092
4093TEST_P(ImportFunctionTemplateSpecializations,
4094 ImportPrototypes) {
4095 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4096 auto Code =
4097 R"(
4098 // Proto of the primary template.
4099 template <class T>
4100 void f();
4101 // Proto of the specialization.
4102 template <>
4103 void f<int>();
4104 )";
4105
4106 Decl *ImportedD;
4107 {
4108 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4109 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4110
4111 ImportedD = Import(FromD, Lang_CXX);
4112 }
4113 {
4114 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
4115 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4116 Import(FromD, Lang_CXX);
4117 }
4118
4119 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4120
4121 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4122 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4123 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4124 EXPECT_TRUE(ImportedD == To0);
4125 EXPECT_TRUE(ImportedD != To1);
4126 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
4127 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
4128 // Check that they are part of the same redecl chain.
4129 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
4130}
4131
4132TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
4133 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4134 auto Code =
4135 R"(
4136 // Proto of the primary template.
4137 template <class T>
4138 void f();
4139 // Specialization and definition.
4140 template <>
4141 void f<int>() {}
4142 )";
4143
4144 Decl *ImportedD;
4145 {
4146 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4147 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4148 ImportedD = Import(FromD, Lang_CXX);
4149 }
4150 {
4151 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
4152 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4153 Import(FromD, Lang_CXX);
4154 }
4155
4156 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4157
4158 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
4159 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4160 EXPECT_TRUE(ImportedD == To0);
4161 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
4162
4163 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4164 ToTU, functionTemplateDecl());
4165 auto *FirstSpecD = *(TemplateD->spec_begin());
4166 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
4167}
4168
4169TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
4170 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4171 auto Code =
4172 R"(
4173 // Proto of the primary template.
4174 template <class T>
4175 void f();
4176 // Specialization proto.
4177 template <>
4178 void f<int>();
4179 // Specialization proto.
4180 template <>
4181 void f<int>();
4182 )";
4183
4184 Decl *ImportedD;
4185 {
4186 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4187 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4188 ImportedD = Import(FromD, Lang_CXX);
4189 }
4190
4191 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4192
4193 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4194 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4195 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4196 EXPECT_TRUE(ImportedD == To0);
4197 EXPECT_TRUE(ImportedD != To1);
4198 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
4199 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
4200 EXPECT_EQ(To1->getPreviousDecl(), To0);
4201}
4202
4203TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
4204 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4205 auto Code =
4206 R"(
4207 // Proto of the primary template.
4208 template <class T>
4209 void f();
4210 // Specialization proto.
4211 template <>
4212 void f<int>();
4213 // Specialization definition.
4214 template <>
4215 void f<int>() {}
4216 )";
4217
4218 Decl *ImportedD;
4219 {
4220 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4221 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4222 ImportedD = Import(FromD, Lang_CXX);
4223 }
4224
4225 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4226
4227 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4228 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4229 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4230 EXPECT_TRUE(ImportedD == To0);
4231 EXPECT_TRUE(ImportedD != To1);
4232 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
4233 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
4234 EXPECT_EQ(To1->getPreviousDecl(), To0);
4235}
4236
4237TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
4238 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4239 auto Code =
4240 R"(
4241 // Proto of the primary template.
4242 template <class T>
4243 void f();
4244 // Specialization definition.
4245 template <>
4246 void f<int>() {}
4247 // Specialization proto.
4248 template <>
4249 void f<int>();
4250 )";
4251
4252 Decl *ImportedD;
4253 {
4254 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4255 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4256 ImportedD = Import(FromD, Lang_CXX);
4257 }
4258
4259 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4260
4261 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4262 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4263 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4264 EXPECT_TRUE(ImportedD == To0);
4265 EXPECT_TRUE(ImportedD != To1);
4266 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
4267 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
4268 EXPECT_EQ(To1->getPreviousDecl(), To0);
4269}
4270
Gabor Marton17d39672018-11-26 15:54:08 +00004271TEST_P(ASTImporterTestBase,
4272 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4273 {
4274 Decl *FromTU = getTuDecl(
4275 R"(
4276 template <typename T>
4277 struct B;
4278 )",
4279 Lang_CXX, "input0.cc");
4280 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4281 FromTU, classTemplateDecl(hasName("B")));
4282
4283 Import(FromD, Lang_CXX);
4284 }
4285
4286 {
4287 Decl *FromTU = getTuDecl(
4288 R"(
4289 template <typename T>
4290 struct B {
4291 void f();
4292 B* b;
4293 };
4294 )",
4295 Lang_CXX, "input1.cc");
4296 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4297 FromTU, functionDecl(hasName("f")));
4298 Import(FromD, Lang_CXX);
4299 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4300 FromTU, classTemplateDecl(hasName("B")));
4301 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4302 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4303
4304 // We expect no (ODR) warning during the import.
4305 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4306 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4307 }
4308}
4309
Gabor Martonb93baf62018-11-27 09:51:36 +00004310TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
4311 // We already have an incomplete underlying type in the "To" context.
4312 auto Code =
4313 R"(
4314 template <typename T>
4315 struct S {
4316 void foo();
4317 };
4318 using U = S<int>;
4319 )";
4320 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4321 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4322 typedefNameDecl(hasName("U")));
4323 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4324
4325 // The "From" context has the same typedef, but the underlying type is
4326 // complete this time.
4327 Decl *FromTU = getTuDecl(std::string(Code) +
4328 R"(
4329 void foo(U* u) {
4330 u->foo();
4331 }
4332 )", Lang_CXX11);
4333 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4334 typedefNameDecl(hasName("U")));
4335 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4336
4337 // The imported type should be complete.
4338 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4339 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4340}
4341
Gabor Marton19f4f392018-06-25 13:04:37 +00004342INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
4343 ::testing::Values(ArgVector()), );
4344
Gabor Marton5254e642018-06-27 13:32:50 +00004345INSTANTIATE_TEST_CASE_P(
4346 ParameterizedTests, CanonicalRedeclChain,
4347 ::testing::Values(ArgVector()),);
4348
Gabor Marton19f4f392018-06-25 13:04:37 +00004349auto DefaultTestValuesForRunOptions = ::testing::Values(
4350 ArgVector(),
4351 ArgVector{"-fdelayed-template-parsing"},
4352 ArgVector{"-fms-compatibility"},
4353 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
4354
4355INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
4356 DefaultTestValuesForRunOptions, );
4357
4358INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
4359 DefaultTestValuesForRunOptions, );
4360
4361INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
4362 DefaultTestValuesForRunOptions, );
4363
4364INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
4365 DefaultTestValuesForRunOptions, );
4366
4367INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
4368 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00004369
Gabor Marton5254e642018-06-27 13:32:50 +00004370INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
4371 DefaultTestValuesForRunOptions, );
4372
Gabor Marton7df342a2018-12-17 12:42:12 +00004373INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
4374 DefaultTestValuesForRunOptions, );
4375
4376INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplates,
4377 DefaultTestValuesForRunOptions, );
4378
4379INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
4380 DefaultTestValuesForRunOptions, );
4381
Gabor Marton5254e642018-06-27 13:32:50 +00004382INSTANTIATE_TEST_CASE_P(ParameterizedTests,
4383 ImportFunctionTemplateSpecializations,
4384 DefaultTestValuesForRunOptions, );
4385
Gabor Martonac3a5d62018-09-17 12:04:52 +00004386INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
4387 DefaultTestValuesForRunOptions, );
4388
4389INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
4390 DefaultTestValuesForRunOptions, );
4391
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00004392} // end namespace ast_matchers
4393} // end namespace clang