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