blob: 77dbd43a7d2ca78cfb0b3506a76e55b16ce0c4b7 [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"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000023#include "gtest/gtest.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000024#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000025
26namespace clang {
27namespace ast_matchers {
28
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000029using internal::Matcher;
30using internal::BindableMatcher;
31using llvm::StringMap;
32
Peter Szecsidedda6f2018-03-30 22:03:29 +000033// Creates a virtual file and assigns that to the context of given AST. If the
34// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000035static void
36createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
37 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000038 assert(ToAST);
39 ASTContext &ToCtx = ToAST->getASTContext();
40 auto *OFS = static_cast<vfs::OverlayFileSystem *>(
41 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
42 auto *MFS =
43 static_cast<vfs::InMemoryFileSystem *>(OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000044 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000045}
46
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000047static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
48 StringRef Code) {
49 return createVirtualFileIfNeeded(ToAST, FileName,
50 llvm::MemoryBuffer::getMemBuffer(Code));
51}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000052
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000053const StringRef DeclToImportID = "declToImport";
54const StringRef DeclToVerifyID = "declToVerify";
55
Gabor Marton19f4f392018-06-25 13:04:37 +000056// Common base for the different families of ASTImporter tests that are
57// parameterized on the compiler options which may result a different AST. E.g.
58// -fms-compatibility or -fdelayed-template-parsing.
59struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000060
Gabor Marton19f4f392018-06-25 13:04:37 +000061 // Returns the argument vector used for a specific language option, this set
62 // can be tweaked by the test parameters.
63 ArgVector getArgVectorForLanguage(Language Lang) const {
64 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
65 ArgVector ExtraArgs = GetParam();
66 for (const auto &Arg : ExtraArgs) {
67 Args.push_back(Arg);
68 }
69 return Args;
70 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000071
Gabor Marton19f4f392018-06-25 13:04:37 +000072};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000073
Gabor Marton19f4f392018-06-25 13:04:37 +000074// Base class for those tests which use the family of `testImport` functions.
75class TestImportBase : public ParameterizedTestsFixture {
Adam Baloghe4192a82018-06-15 06:45:39 +000076
Gabor Marton19f4f392018-06-25 13:04:37 +000077 template <typename NodeType>
78 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
79 NodeType Node) {
80 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000081
Gabor Marton19f4f392018-06-25 13:04:37 +000082 // Add 'From' file to virtual file system so importer can 'find' it
83 // while importing SourceLocations. It is safe to add same file multiple
84 // times - it just isn't replaced.
85 StringRef FromFileName = From->getMainFileName();
86 createVirtualFileIfNeeded(To, FromFileName,
87 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000088
Gabor Marton19f4f392018-06-25 13:04:37 +000089 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000090
Gabor Marton19f4f392018-06-25 13:04:37 +000091 // This should dump source locations and assert if some source locations
92 // were not imported.
93 SmallString<1024> ImportChecker;
94 llvm::raw_svector_ostream ToNothing(ImportChecker);
95 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000096
Gabor Marton19f4f392018-06-25 13:04:37 +000097 // This traverses the AST to catch certain bugs like poorly or not
98 // implemented subtrees.
99 Imported->dump(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000100
Gabor Marton19f4f392018-06-25 13:04:37 +0000101 return Imported;
102 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000103
Gabor Marton19f4f392018-06-25 13:04:37 +0000104 template <typename NodeType>
105 testing::AssertionResult
106 testImport(const std::string &FromCode, const ArgVector &FromArgs,
107 const std::string &ToCode, const ArgVector &ToArgs,
108 MatchVerifier<NodeType> &Verifier,
109 const BindableMatcher<NodeType> &SearchMatcher,
110 const BindableMatcher<NodeType> &VerificationMatcher) {
111 const char *const InputFileName = "input.cc";
112 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000113
Gabor Marton19f4f392018-06-25 13:04:37 +0000114 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
115 FromCode, FromArgs, InputFileName),
116 ToAST = tooling::buildASTFromCodeWithArgs(
117 ToCode, ToArgs, OutputFileName);
118
119 ASTContext &FromCtx = FromAST->getASTContext(),
120 &ToCtx = ToAST->getASTContext();
121
122 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
123 FromAST->getFileManager(), false);
124
125 auto FoundNodes = match(SearchMatcher, FromCtx);
126 if (FoundNodes.size() != 1)
127 return testing::AssertionFailure()
128 << "Multiple potential nodes were found!";
129
130 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
131 if (!ToImport)
132 return testing::AssertionFailure() << "Node type mismatch!";
133
134 // Sanity check: the node being imported should match in the same way as
135 // the result node.
136 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
137 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
138
139 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
140 if (!Imported)
141 return testing::AssertionFailure() << "Import failed, nullptr returned!";
142
143 return Verifier.match(Imported, WrapperMatcher);
144 }
145
146 template <typename NodeType>
147 testing::AssertionResult
148 testImport(const std::string &FromCode, const ArgVector &FromArgs,
149 const std::string &ToCode, const ArgVector &ToArgs,
150 MatchVerifier<NodeType> &Verifier,
151 const BindableMatcher<NodeType> &VerificationMatcher) {
152 return testImport(
153 FromCode, FromArgs, ToCode, ToArgs, Verifier,
154 translationUnitDecl(
155 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
156 VerificationMatcher);
157 }
158
159public:
160
161 /// Test how AST node named "declToImport" located in the translation unit
162 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
163 /// The verification is done by running AMatcher over the imported node.
164 template <typename NodeType, typename MatcherType>
165 void testImport(const std::string &FromCode, Language FromLang,
166 const std::string &ToCode, Language ToLang,
167 MatchVerifier<NodeType> &Verifier,
168 const MatcherType &AMatcher) {
169 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
170 ToArgs = getArgVectorForLanguage(ToLang);
171 EXPECT_TRUE(
172 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
173 }
174
175 struct ImportAction {
176 StringRef FromFilename;
177 StringRef ToFilename;
178 // FIXME: Generalize this to support other node kinds.
179 BindableMatcher<Decl> ImportPredicate;
180
181 ImportAction(StringRef FromFilename, StringRef ToFilename,
182 DeclarationMatcher ImportPredicate)
183 : FromFilename(FromFilename), ToFilename(ToFilename),
184 ImportPredicate(ImportPredicate) {}
185
186 ImportAction(StringRef FromFilename, StringRef ToFilename,
187 const std::string &DeclName)
188 : FromFilename(FromFilename), ToFilename(ToFilename),
189 ImportPredicate(namedDecl(hasName(DeclName))) {}
190 };
191
192 using SingleASTUnit = std::unique_ptr<ASTUnit>;
193 using AllASTUnits = StringMap<SingleASTUnit>;
194
195 struct CodeEntry {
196 std::string CodeSample;
197 Language Lang;
198 };
199
200 using CodeFiles = StringMap<CodeEntry>;
201
202 /// Builds an ASTUnit for one potential compile options set.
203 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
204 ArgVector Args = getArgVectorForLanguage(CE.Lang);
205 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
206 EXPECT_TRUE(AST.get());
207 return AST;
208 }
209
210 /// Test an arbitrary sequence of imports for a set of given in-memory files.
211 /// The verification is done by running VerificationMatcher against a
212 /// specified AST node inside of one of given files.
213 /// \param CodeSamples Map whose key is the file name and the value is the
214 /// file content.
215 /// \param ImportActions Sequence of imports. Each import in sequence
216 /// specifies "from file" and "to file" and a matcher that is used for
217 /// searching a declaration for import in "from file".
218 /// \param FileForFinalCheck Name of virtual file for which the final check is
219 /// applied.
220 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
221 /// FileForFinalCheck for which the verification will be done.
222 /// \param VerificationMatcher Matcher that will be used for verification
223 /// after all imports in sequence are done.
224 void testImportSequence(const CodeFiles &CodeSamples,
225 const std::vector<ImportAction> &ImportActions,
226 StringRef FileForFinalCheck,
227 BindableMatcher<Decl> FinalSelectPredicate,
228 BindableMatcher<Decl> VerificationMatcher) {
229 AllASTUnits AllASTs;
230 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
231 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
232
233 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
234 if (!AllASTs.count(Filename)) {
235 auto Found = CodeSamples.find(Filename);
236 assert(Found != CodeSamples.end() && "Wrong file for import!");
237 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
238 }
239 };
240
241 for (const ImportAction &Action : ImportActions) {
242 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
243 GenASTsIfNeeded(FromFile);
244 GenASTsIfNeeded(ToFile);
245
246 ASTUnit *From = AllASTs[FromFile].get();
247 ASTUnit *To = AllASTs[ToFile].get();
248
249 // Create a new importer if needed.
250 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
251 if (!ImporterRef)
252 ImporterRef.reset(new ASTImporter(
253 To->getASTContext(), To->getFileManager(), From->getASTContext(),
254 From->getFileManager(), false));
255
256 // Find the declaration and import it.
257 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
258 From->getASTContext());
259 EXPECT_TRUE(FoundDecl.size() == 1);
260 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
261 auto Imported = importNode(From, To, *ImporterRef, ToImport);
262 EXPECT_TRUE(Imported);
263 }
264
265 // Find the declaration and import it.
266 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
267 AllASTs[FileForFinalCheck]->getASTContext());
268 EXPECT_TRUE(FoundDecl.size() == 1);
269 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
270 MatchVerifier<Decl> Verifier;
271 EXPECT_TRUE(
272 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
273 }
274};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000275
Peter Szecsidedda6f2018-03-30 22:03:29 +0000276// This class provides generic methods to write tests which can check internal
277// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
278// this fixture makes it possible to import from several "From" contexts.
Gabor Marton19f4f392018-06-25 13:04:37 +0000279class ASTImporterTestBase : public ParameterizedTestsFixture {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000280
281 const char *const InputFileName = "input.cc";
282 const char *const OutputFileName = "output.cc";
283
284 // Buffer for the To context, must live in the test scope.
285 std::string ToCode;
286
287 struct TU {
288 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000289 std::string Code;
290 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000291 std::unique_ptr<ASTUnit> Unit;
292 TranslationUnitDecl *TUDecl = nullptr;
293 TU(StringRef Code, StringRef FileName, ArgVector Args)
294 : Code(Code), FileName(FileName),
295 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
296 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000297 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
298 Unit->enableSourceFileDiagnostics();
299 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000300 };
301
302 // We may have several From contexts and related translation units. In each
303 // AST, the buffers for the source are handled via references and are set
304 // during the creation of the AST. These references must point to a valid
305 // buffer until the AST is alive. Thus, we must use a list in order to avoid
306 // moving of the stored objects because that would mean breaking the
307 // references in the AST. By using a vector a move could happen when the
308 // vector is expanding, with the list we won't have these issues.
309 std::list<TU> FromTUs;
310
311public:
312 // We may have several From context but only one To context.
313 std::unique_ptr<ASTUnit> ToAST;
314
Peter Szecsidedda6f2018-03-30 22:03:29 +0000315 // Creates an AST both for the From and To source code and imports the Decl
316 // of the identifier into the To context.
317 // Must not be called more than once within the same test.
318 std::tuple<Decl *, Decl *>
319 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
320 Language ToLang, StringRef Identifier = DeclToImportID) {
321 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
322 ToArgs = getArgVectorForLanguage(ToLang);
323
324 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
325 TU &FromTU = FromTUs.back();
326
327 ToCode = ToSrcCode;
328 assert(!ToAST);
329 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000330 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000331
332 ASTContext &FromCtx = FromTU.Unit->getASTContext(),
333 &ToCtx = ToAST->getASTContext();
334
335 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
336
337 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
338 FromTU.Unit->getFileManager(), false);
339
340 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
341 assert(ImportedII && "Declaration with the given identifier "
342 "should be specified in test!");
343 DeclarationName ImportDeclName(ImportedII);
344 SmallVector<NamedDecl *, 4> FoundDecls;
345 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
346 FoundDecls);
347
348 assert(FoundDecls.size() == 1);
349
350 Decl *Imported = Importer.Import(FoundDecls.front());
351 assert(Imported);
352 return std::make_tuple(*FoundDecls.begin(), Imported);
353 }
354
Gabor Marton9581c332018-05-23 13:53:36 +0000355 // Creates a TU decl for the given source code which can be used as a From
356 // context. May be called several times in a given test (with different file
357 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000358 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
359 StringRef FileName = "input.cc") {
360 assert(
361 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
362 return E.FileName == FileName;
363 }) == FromTUs.end());
364
365 ArgVector Args = getArgVectorForLanguage(Lang);
366 FromTUs.emplace_back(SrcCode, FileName, Args);
367 TU &Tu = FromTUs.back();
368
369 return Tu.TUDecl;
370 }
371
Gabor Marton9581c332018-05-23 13:53:36 +0000372 // Creates the To context with the given source code and returns the TU decl.
373 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
374 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
375 ToCode = ToSrcCode;
376 assert(!ToAST);
377 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000378 ToAST->enableSourceFileDiagnostics();
Gabor Marton9581c332018-05-23 13:53:36 +0000379
380 return ToAST->getASTContext().getTranslationUnitDecl();
381 }
382
Peter Szecsidedda6f2018-03-30 22:03:29 +0000383 // Import the given Decl into the ToCtx.
384 // May be called several times in a given test.
385 // The different instances of the param From may have different ASTContext.
386 Decl *Import(Decl *From, Language ToLang) {
387 if (!ToAST) {
388 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
389 // Build the AST from an empty file.
390 ToAST =
391 tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
Adam Baloghe4192a82018-06-15 06:45:39 +0000392 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000393 }
394
395 // Create a virtual file in the To Ctx which corresponds to the file from
396 // which we want to import the `From` Decl. Without this source locations
397 // will be invalid in the ToCtx.
398 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
399 return E.TUDecl == From->getTranslationUnitDecl();
400 });
401 assert(It != FromTUs.end());
402 createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code);
403
404 ASTContext &FromCtx = From->getASTContext(),
405 &ToCtx = ToAST->getASTContext();
406 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
407 FromCtx.getSourceManager().getFileManager(), false);
408 return Importer.Import(From);
409 }
410
411 ~ASTImporterTestBase() {
412 if (!::testing::Test::HasFailure()) return;
413
414 for (auto &Tu : FromTUs) {
415 assert(Tu.Unit);
416 llvm::errs() << "FromAST:\n";
417 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
418 llvm::errs() << "\n";
419 }
420 if (ToAST) {
421 llvm::errs() << "ToAST:\n";
422 ToAST->getASTContext().getTranslationUnitDecl()->dump();
423 }
424 }
425};
426
Gabor Marton19f4f392018-06-25 13:04:37 +0000427struct ImportExpr : TestImportBase {};
428struct ImportType : TestImportBase {};
429struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000430
Gabor Marton19f4f392018-06-25 13:04:37 +0000431TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000432 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000433 testImport("void declToImport() { \"foo\"; }",
434 Lang_CXX, "", Lang_CXX, Verifier,
435 functionDecl(
436 hasBody(
437 compoundStmt(
438 has(
439 stringLiteral(
440 hasType(
441 asString("const char [4]"))))))));
442 testImport("void declToImport() { L\"foo\"; }",
443 Lang_CXX, "", Lang_CXX, Verifier,
444 functionDecl(
445 hasBody(
446 compoundStmt(
447 has(
448 stringLiteral(
449 hasType(
450 asString("const wchar_t [4]"))))))));
451 testImport("void declToImport() { \"foo\" \"bar\"; }",
452 Lang_CXX, "", Lang_CXX, Verifier,
453 functionDecl(
454 hasBody(
455 compoundStmt(
456 has(
457 stringLiteral(
458 hasType(
459 asString("const char [7]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000460}
461
Gabor Marton19f4f392018-06-25 13:04:37 +0000462TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000463 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000464 testImport("void declToImport() { __null; }",
465 Lang_CXX, "", Lang_CXX, Verifier,
466 functionDecl(
467 hasBody(
468 compoundStmt(
469 has(
470 gnuNullExpr(
471 hasType(isInteger())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000472}
473
Gabor Marton19f4f392018-06-25 13:04:37 +0000474TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000475 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000476 testImport("void declToImport() { nullptr; }",
477 Lang_CXX11, "", Lang_CXX11, Verifier,
478 functionDecl(
479 hasBody(
480 compoundStmt(
481 has(
482 cxxNullPtrLiteralExpr())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000483}
484
485
Gabor Marton19f4f392018-06-25 13:04:37 +0000486TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000487 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000488 testImport("void declToImport() { 1.0; }",
489 Lang_C, "", Lang_C, Verifier,
490 functionDecl(
491 hasBody(
492 compoundStmt(
493 has(
494 floatLiteral(
495 equals(1.0),
496 hasType(asString("double"))))))));
497 testImport("void declToImport() { 1.0e-5f; }",
498 Lang_C, "", Lang_C, Verifier,
499 functionDecl(
500 hasBody(
501 compoundStmt(
502 has(
503 floatLiteral(
504 equals(1.0e-5f),
505 hasType(asString("float"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000506}
507
Gabor Marton19f4f392018-06-25 13:04:37 +0000508TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000509 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000510 testImport("void declToImport() {"
511 " struct s { int x; long y; unsigned z; }; "
512 " (struct s){ 42, 0L, 1U }; }",
513 Lang_CXX, "", Lang_CXX, Verifier,
514 functionDecl(
515 hasBody(
516 compoundStmt(
517 has(
518 compoundLiteralExpr(
519 hasType(asString("struct s")),
520 has(initListExpr(
521 hasType(asString("struct s")),
522 has(integerLiteral(
523 equals(42), hasType(asString("int")))),
524 has(integerLiteral(
525 equals(0), hasType(asString("long")))),
526 has(integerLiteral(
527 equals(1),
528 hasType(asString("unsigned int"))))
529 ))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000530}
531
Gabor Marton19f4f392018-06-25 13:04:37 +0000532TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000533 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000534 testImport("class declToImport { void f() { this; } };",
535 Lang_CXX, "", Lang_CXX, Verifier,
536 cxxRecordDecl(
537 hasMethod(
538 hasBody(
539 compoundStmt(
540 has(
541 cxxThisExpr(
542 hasType(
543 asString("class declToImport *")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000544}
545
Gabor Marton19f4f392018-06-25 13:04:37 +0000546TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000547 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000548 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
549 Lang_C, "", Lang_C, Verifier,
550 functionDecl(hasBody(compoundStmt(has(atomicExpr(
551 has(ignoringParenImpCasts(
552 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
553 hasType(asString("int *"))))),
554 has(integerLiteral(equals(1), hasType(asString("int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000555}
556
Gabor Marton19f4f392018-06-25 13:04:37 +0000557TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000558 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000559 testImport(
560 "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C,
561 Verifier,
562 functionDecl(hasBody(compoundStmt(
563 has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
564 has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000565}
566
567AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
568 internal::Matcher<NamedDecl>, InnerMatcher) {
569 const NamedDecl *Template = Node.getTemplatedDecl();
570 return Template && InnerMatcher.matches(*Template, Finder, Builder);
571}
572
Gabor Marton19f4f392018-06-25 13:04:37 +0000573TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000574 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000575 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000576 "template<typename T> class dummy { void f() { dummy X(*this); } };"
577 "typedef dummy<int> declToImport;"
578 "template class dummy<int>;",
579 Lang_CXX, "", Lang_CXX, Verifier,
580 typedefDecl(hasType(templateSpecializationType(
581 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
582 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
583 hasName("f"),
584 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
585 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
586 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000587 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000588}
589
Gabor Marton19f4f392018-06-25 13:04:37 +0000590TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000591 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000592 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
593 Lang_C, "", Lang_C, Verifier,
594 functionDecl(hasBody(compoundStmt(
595 has(switchStmt(has(compoundStmt(has(caseStmt())))))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000596}
597
Gabor Marton19f4f392018-06-25 13:04:37 +0000598TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000599 MatchVerifier<Decl> Verifier;
600 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000601 testImport(
602 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
603 Lang_C, "", Lang_C, Verifier,
604 functionDecl(
605 hasBody(
606 compoundStmt(
607 has(
608 declStmt(
609 hasSingleDecl(
610 varDecl(
611 hasName("C"),
612 hasType(asString("int")),
613 hasInitializer(
614 stmtExpr(
615 hasAnySubstatement(
616 declStmt(
617 hasSingleDecl(
618 varDecl(
619 hasName("X"),
620 hasType(asString("int")),
621 hasInitializer(
622 integerLiteral(equals(4))))))),
623 hasDescendant(
624 implicitCastExpr()
625 )))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000626}
627
Gabor Marton19f4f392018-06-25 13:04:37 +0000628TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000629 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000630 testImport(
631 "void declToImport() { true ? 1 : -5; }",
632 Lang_CXX, "", Lang_CXX, Verifier,
633 functionDecl(
634 hasBody(
635 compoundStmt(
636 has(
637 conditionalOperator(
638 hasCondition(cxxBoolLiteral(equals(true))),
639 hasTrueExpression(integerLiteral(equals(1))),
640 hasFalseExpression(
641 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
642 )))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000643}
644
Gabor Marton19f4f392018-06-25 13:04:37 +0000645TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000646 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000647 testImport(
648 "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier,
649 functionDecl(
650 hasBody(
651 compoundStmt(
652 has(
653 binaryConditionalOperator(
654 hasCondition(
655 implicitCastExpr(
656 hasSourceExpression(
657 opaqueValueExpr(
658 hasSourceExpression(integerLiteral(equals(1))))),
659 hasType(booleanType()))),
660 hasTrueExpression(
661 opaqueValueExpr(hasSourceExpression(
662 integerLiteral(equals(1))))),
663 hasFalseExpression(
664 unaryOperator(hasOperatorName("-"),
665 hasUnaryOperand(integerLiteral(equals(5)))))
666 ))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000667}
668
Gabor Marton19f4f392018-06-25 13:04:37 +0000669TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000670 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000671 testImport("void declToImport() {"
672 " struct point { double x; double y; };"
673 " struct point ptarray[10] = "
674 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
675 Lang_C, "", Lang_C, Verifier,
676 functionDecl(
677 hasBody(
678 compoundStmt(
679 has(
680 declStmt(
681 hasSingleDecl(
682 varDecl(
683 hasInitializer(
684 initListExpr(
685 hasSyntacticForm(
686 initListExpr(
687 has(
688 designatedInitExpr(
689 designatorCountIs(2),
690 has(floatLiteral(
691 equals(1.0))),
692 has(integerLiteral(
693 equals(2))))),
694 has(
695 designatedInitExpr(
696 designatorCountIs(2),
697 has(floatLiteral(
698 equals(2.0))),
699 has(integerLiteral(
700 equals(2))))),
701 has(
702 designatedInitExpr(
703 designatorCountIs(2),
704 has(floatLiteral(
705 equals(1.0))),
706 has(integerLiteral(
707 equals(0)))))
708 ))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000709}
710
711
Gabor Marton19f4f392018-06-25 13:04:37 +0000712TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000713 MatchVerifier<Decl> Verifier;
714 // __func__ expands as StringLiteral("declToImport")
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000715 testImport("void declToImport() { __func__; }",
716 Lang_CXX, "", Lang_CXX, Verifier,
717 functionDecl(
718 hasBody(
719 compoundStmt(
720 has(
721 predefinedExpr(
722 hasType(
723 asString("const char [13]")),
724 has(
725 stringLiteral(
726 hasType(
727 asString("const char [13]"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000728}
729
Gabor Marton19f4f392018-06-25 13:04:37 +0000730TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000731 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000732 testImport(
733 "void declToImport() {"
734 " struct point { double x; double y; };"
735 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
736 " [0].x = 1.0 }; }",
737 Lang_CXX, "", Lang_CXX, Verifier,
738 functionDecl(
739 hasBody(
740 compoundStmt(
741 has(
742 declStmt(
743 hasSingleDecl(
744 varDecl(
745 hasInitializer(
746 initListExpr(
747 has(
748 cxxConstructExpr(
749 requiresZeroInitialization())),
750 has(
751 initListExpr(
752 hasType(asString("struct point")),
753 has(floatLiteral(equals(1.0))),
754 has(implicitValueInitExpr(
755 hasType(asString("double")))))),
756 has(
757 initListExpr(
758 hasType(asString("struct point")),
759 has(floatLiteral(equals(2.0))),
760 has(floatLiteral(equals(1.0)))))
761 ))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000762}
763
764
Aleksei Sidorina693b372016-09-28 10:16:56 +0000765const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
766
Gabor Marton19f4f392018-06-25 13:04:37 +0000767TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000768 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000769 testImport("void declToImport(__builtin_va_list list, ...) {"
770 " (void)__builtin_va_arg(list, int); }",
771 Lang_CXX, "", Lang_CXX, Verifier,
772 functionDecl(
773 hasBody(
774 compoundStmt(
775 has(
776 cStyleCastExpr(
777 hasSourceExpression(
778 vaArgExpr())))))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000779}
780
Gabor Marton19f4f392018-06-25 13:04:37 +0000781TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000782 MatchVerifier<Decl> Verifier;
783 testImport("struct C {};"
784 "void declToImport() { C c = C(); }",
785 Lang_CXX, "", Lang_CXX, Verifier,
786 functionDecl(hasBody(compoundStmt(has(
787 declStmt(has(varDecl(has(exprWithCleanups(has(cxxConstructExpr(
788 has(materializeTemporaryExpr(has(implicitCastExpr(
789 has(cxxTemporaryObjectExpr())))))))))))))))));
790}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000791
Gabor Marton19f4f392018-06-25 13:04:37 +0000792TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000793 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000794 testImport("void declToImport() { typedef _Atomic(int) a_int; }",
795 Lang_CXX11, "", Lang_CXX11, Verifier,
796 functionDecl(
797 hasBody(
798 compoundStmt(
799 has(
800 declStmt(
801 has(
802 typedefDecl(
803 has(atomicType())))))))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000804}
805
Gabor Marton19f4f392018-06-25 13:04:37 +0000806TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000807 MatchVerifier<Decl> Verifier;
808 testImport("template <typename T> void declToImport() { };", Lang_CXX, "",
809 Lang_CXX, Verifier, functionTemplateDecl());
810}
811
812const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
813 cxxDependentScopeMemberExpr;
814
Gabor Marton19f4f392018-06-25 13:04:37 +0000815TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000816 MatchVerifier<Decl> Verifier;
817 testImport("template <typename T> struct C { T t; };"
818 "template <typename T> void declToImport() {"
819 " C<T> d;"
820 " d.t;"
821 "}"
822 "void instantiate() { declToImport<int>(); }",
823 Lang_CXX, "", Lang_CXX, Verifier,
824 functionTemplateDecl(has(functionDecl(
825 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
826 testImport("template <typename T> struct C { T t; };"
827 "template <typename T> void declToImport() {"
828 " C<T> d;"
829 " (&d)->t;"
830 "}"
831 "void instantiate() { declToImport<int>(); }",
832 Lang_CXX, "", Lang_CXX, Verifier,
833 functionTemplateDecl(has(functionDecl(
834 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
835}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000836
Gabor Marton19f4f392018-06-25 13:04:37 +0000837TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000838 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000839 testImport(
840 "template <int K>"
841 "struct dummy { static const int i = K; };"
842 "template <int K> using dummy2 = dummy<K>;"
843 "int declToImport() { return dummy2<3>::i; }",
844 Lang_CXX11, "", Lang_CXX11, Verifier,
845 functionDecl(
846 hasBody(compoundStmt(
847 has(returnStmt(has(implicitCastExpr(has(declRefExpr()))))))),
848 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
849}
850
851const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
852 varTemplateSpecializationDecl;
853
Gabor Marton19f4f392018-06-25 13:04:37 +0000854TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000855 MatchVerifier<Decl> Verifier;
856 testImport(
857 "template <typename T>"
858 "T pi = T(3.1415926535897932385L);"
859 "void declToImport() { pi<int>; }",
860 Lang_CXX11, "", Lang_CXX11, Verifier,
861 functionDecl(
862 hasBody(has(declRefExpr(to(varTemplateSpecializationDecl())))),
863 unless(hasAncestor(translationUnitDecl(has(varDecl(
864 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000865}
866
Gabor Marton19f4f392018-06-25 13:04:37 +0000867TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000868 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000869 testImport("template <typename... Args>"
870 "struct dummy {"
871 " dummy(Args... args) {}"
872 " static const int i = 4;"
873 "};"
874 "int declToImport() { return dummy<int>::i; }",
875 Lang_CXX11, "", Lang_CXX11, Verifier,
876 functionDecl(
877 hasBody(
878 compoundStmt(
879 has(
880 returnStmt(
881 has(
882 implicitCastExpr(
883 has(
884 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000885}
886
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000887const internal::VariadicDynCastAllOfMatcher<Type,
888 DependentTemplateSpecializationType>
889 dependentTemplateSpecializationType;
890
Gabor Marton19f4f392018-06-25 13:04:37 +0000891TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000892 MatchVerifier<Decl> Verifier;
893 testImport("template<typename T>"
894 "struct A;"
895 "template<typename T>"
896 "struct declToImport {"
897 " typename A<T>::template B<T> a;"
898 "};",
899 Lang_CXX, "", Lang_CXX, Verifier,
900 classTemplateDecl(has(cxxRecordDecl(has(
901 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
902}
903
904const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
905 sizeOfPackExpr;
906
Gabor Marton19f4f392018-06-25 13:04:37 +0000907TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000908 MatchVerifier<Decl> Verifier;
909 testImport("template <typename... Ts>"
910 "void declToImport() {"
911 " const int i = sizeof...(Ts);"
912 "};"
913 "void g() { declToImport<int>(); }",
914 Lang_CXX11, "", Lang_CXX11, Verifier,
915 functionTemplateDecl(has(functionDecl(
916 hasBody(compoundStmt(has(declStmt(has(varDecl(hasInitializer(
917 implicitCastExpr(has(sizeOfPackExpr())))))))))))));
918 testImport(
919 "template <typename... Ts>"
920 "using X = int[sizeof...(Ts)];"
921 "template <typename... Us>"
922 "struct Y {"
923 " X<Us..., int, double, int, Us...> f;"
924 "};"
925 "Y<float, int> declToImport;",
926 Lang_CXX11, "", Lang_CXX11, Verifier,
927 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
928 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
929}
930
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000931/// \brief Matches __builtin_types_compatible_p:
932/// GNU extension to check equivalent types
933/// Given
934/// \code
935/// __builtin_types_compatible_p(int, int)
936/// \endcode
937// will generate TypeTraitExpr <...> 'int'
938const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
939
Gabor Marton19f4f392018-06-25 13:04:37 +0000940TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000941 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000942 testImport("void declToImport() { "
943 " __builtin_types_compatible_p(int, int);"
944 "}",
945 Lang_C, "", Lang_C, Verifier,
946 functionDecl(
947 hasBody(
948 compoundStmt(
949 has(
950 typeTraitExpr(hasType(asString("int"))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000951}
952
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000953const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
954
Gabor Marton19f4f392018-06-25 13:04:37 +0000955TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000956 MatchVerifier<Decl> Verifier;
957 testImport(
958 "namespace std { class type_info {}; }"
959 "void declToImport() {"
960 " int x;"
961 " auto a = typeid(int); auto b = typeid(x);"
962 "}",
963 Lang_CXX11, "", Lang_CXX11, Verifier,
964 functionDecl(
965 hasDescendant(varDecl(
966 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
967 hasDescendant(varDecl(
968 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
969}
970
Gabor Marton19f4f392018-06-25 13:04:37 +0000971TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000972 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000973 testImport("template<typename T> struct declToImport {"
974 " void m() { __is_pod(T); }"
975 "};"
976 "void f() { declToImport<int>().m(); }",
977 Lang_CXX11, "", Lang_CXX11, Verifier,
978 classTemplateDecl(
979 has(
980 cxxRecordDecl(
981 has(
982 functionDecl(
983 hasBody(
984 compoundStmt(
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000985 has(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000986 typeTraitExpr(
987 hasType(booleanType())
988 ))))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000989}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000990
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000991const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
992 cxxPseudoDestructorExpr;
993
Gabor Marton19f4f392018-06-25 13:04:37 +0000994TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000995 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000996 testImport("typedef int T;"
997 "void declToImport(int *p) {"
998 " T t;"
999 " p->T::~T();"
1000 "}",
1001 Lang_CXX, "", Lang_CXX, Verifier,
1002 functionDecl(has(compoundStmt(has(
1003 callExpr(has(cxxPseudoDestructorExpr())))))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001004}
1005
Gabor Marton19f4f392018-06-25 13:04:37 +00001006TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001007 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001008 testImport("namespace foo { int bar; }"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001009 "void declToImport() { using foo::bar; }",
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001010 Lang_CXX, "", Lang_CXX, Verifier,
1011 functionDecl(
1012 has(
1013 compoundStmt(
1014 has(
1015 declStmt(
1016 has(
1017 usingDecl())))))));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001018}
1019
1020/// \brief Matches shadow declarations introduced into a scope by a
1021/// (resolved) using declaration.
1022///
1023/// Given
1024/// \code
1025/// namespace n { int f; }
1026/// namespace declToImport { using n::f; }
1027/// \endcode
1028/// usingShadowDecl()
1029/// matches \code f \endcode
1030const internal::VariadicDynCastAllOfMatcher<Decl,
1031 UsingShadowDecl> usingShadowDecl;
1032
Gabor Marton19f4f392018-06-25 13:04:37 +00001033TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001034 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001035 testImport("namespace foo { int bar; }"
1036 "namespace declToImport { using foo::bar; }",
1037 Lang_CXX, "", Lang_CXX, Verifier,
1038 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001039}
1040
Gabor Marton19f4f392018-06-25 13:04:37 +00001041TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001042 MatchVerifier<Decl> Verifier;
1043 testImport("template<typename T> int foo();"
1044 "template <typename T> void declToImport() {"
1045 " ::foo<T>;"
1046 " ::template foo<T>;"
1047 "}"
1048 "void instantiate() { declToImport<int>(); }",
1049 Lang_CXX, "", Lang_CXX, Verifier,
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001050 functionTemplateDecl(has(functionDecl(
1051 has(compoundStmt(has(unresolvedLookupExpr())))))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001052}
1053
Gabor Marton19f4f392018-06-25 13:04:37 +00001054TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001055 MatchVerifier<Decl> Verifier;
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001056 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001057 "template <typename T> void declToImport() {"
1058 " C<T> d;"
1059 " d.t = T();"
1060 "}"
1061 "void instantiate() { declToImport<int>(); }",
1062 Lang_CXX, "", Lang_CXX, Verifier,
1063 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
1064 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001065 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001066 "template <typename T> void declToImport() {"
1067 " C<T> d;"
1068 " (&d)->t = T();"
1069 "}"
1070 "void instantiate() { declToImport<int>(); }",
1071 Lang_CXX, "", Lang_CXX, Verifier,
1072 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
1073 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
1074}
1075
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001076/// Check that function "declToImport()" (which is the templated function
1077/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1078/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001079TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001080 MatchVerifier<Decl> Verifier;
1081 testImport("template <typename T> void declToImport() { T a = 1; }"
1082 "void instantiate() { declToImport<int>(); }",
1083 Lang_CXX, "", Lang_CXX, Verifier,
1084 functionTemplateDecl(hasAncestor(translationUnitDecl(
1085 unless(has(functionDecl(hasName("declToImport"))))))));
1086 testImport("template <typename T> struct declToImport { T t; };"
1087 "void instantiate() { declToImport<int>(); }",
1088 Lang_CXX, "", Lang_CXX, Verifier,
1089 classTemplateDecl(hasAncestor(translationUnitDecl(
1090 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
1091}
1092
Gabor Marton19f4f392018-06-25 13:04:37 +00001093TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001094 MatchVerifier<Decl> Verifier;
1095 auto Code =
1096 R"s(
1097 struct declToImport {
1098 template <typename T0> struct X;
1099 template <typename T0> struct X<T0 *> {};
1100 };
1101 )s";
1102 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1103 recordDecl(has(classTemplateDecl()),
1104 has(classTemplateSpecializationDecl())));
1105}
1106
Gabor Marton19f4f392018-06-25 13:04:37 +00001107TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001108 MatchVerifier<Decl> Verifier;
1109 testImport("class declToImport {"
1110 " void f() { *this = declToImport(); }"
1111 "};",
1112 Lang_CXX, "", Lang_CXX, Verifier,
1113 cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt(
1114 has(exprWithCleanups(has(cxxOperatorCallExpr())))))))));
1115}
1116
Gabor Marton19f4f392018-06-25 13:04:37 +00001117TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001118 MatchVerifier<Decl> Verifier;
1119 testImport("template<typename T, int Size> class declToImport {"
1120 " T data[Size];"
1121 "};",
1122 Lang_CXX, "", Lang_CXX, Verifier,
1123 classTemplateDecl(has(cxxRecordDecl(
1124 has(fieldDecl(hasType(dependentSizedArrayType())))))));
1125}
1126
Gabor Martona0df7a92018-05-30 09:19:26 +00001127TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1128 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1129 auto From =
1130 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1131 ASSERT_TRUE(From);
1132 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1133 ASSERT_TRUE(To);
1134 Decl *ToTemplated = To->getTemplatedDecl();
1135 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1136 EXPECT_TRUE(ToTemplated1);
1137 EXPECT_EQ(ToTemplated1, ToTemplated);
1138}
1139
Gabor Marton6578a4a2018-06-25 11:38:43 +00001140TEST_P(ASTImporterTestBase,
1141 DISABLED_ImportOfTemplatedDeclOfFunctionTemplateDecl) {
1142 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1143 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1144 FromTU, functionTemplateDecl());
1145 ASSERT_TRUE(From);
1146 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1147 ASSERT_TRUE(To);
1148 Decl *ToTemplated = To->getTemplatedDecl();
1149 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1150 EXPECT_TRUE(ToTemplated1);
1151 EXPECT_EQ(ToTemplated1, ToTemplated);
1152}
1153
1154TEST_P(ASTImporterTestBase,
1155 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1156 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1157 auto FromFT =
1158 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1159 ASSERT_TRUE(FromFT);
1160
1161 auto ToTemplated =
1162 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1163 EXPECT_TRUE(ToTemplated);
1164 auto ToTU = ToTemplated->getTranslationUnitDecl();
1165 auto ToFT =
1166 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1167 EXPECT_TRUE(ToFT);
1168}
1169
1170TEST_P(ASTImporterTestBase,
1171 DISABLED_ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
1172 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1173 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1174 FromTU, functionTemplateDecl());
1175 ASSERT_TRUE(FromFT);
1176
1177 auto ToTemplated =
1178 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1179 EXPECT_TRUE(ToTemplated);
1180 auto ToTU = ToTemplated->getTranslationUnitDecl();
1181 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1182 ToTU, functionTemplateDecl());
1183 EXPECT_TRUE(ToFT);
1184}
1185
Gabor Martona0df7a92018-05-30 09:19:26 +00001186TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1187 auto Code =
1188 R"(
1189 namespace x {
1190 template<class X> struct S1{};
1191 template<class X> struct S2{};
1192 template<class X> struct S3{};
1193 }
1194 )";
1195 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1196 auto FromNs =
1197 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1198 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1199 ASSERT_TRUE(ToNs);
1200 auto From =
1201 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1202 classTemplateDecl(
1203 hasName("S2")));
1204 auto To =
1205 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1206 classTemplateDecl(
1207 hasName("S2")));
1208 ASSERT_TRUE(From);
1209 ASSERT_TRUE(To);
1210 auto ToTemplated = To->getTemplatedDecl();
1211 auto ToTemplated1 =
1212 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1213 EXPECT_TRUE(ToTemplated1);
1214 ASSERT_EQ(ToTemplated1, ToTemplated);
1215}
1216
Peter Szecsidedda6f2018-03-30 22:03:29 +00001217TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) {
1218 Decl *From, *To;
1219 std::tie(From, To) = getImportedDecl(
1220 R"(
1221 template <typename T> struct X {};
1222
1223 void declToImport(int y, X<int> &x) {}
1224
1225 template <> struct X<int> {
1226 void g() {
1227 X<int> x;
1228 declToImport(0, x);
1229 }
1230 };
1231 )",
1232 Lang_CXX, "", Lang_CXX);
1233
1234 MatchVerifier<Decl> Verifier;
1235 auto Matcher = functionDecl(hasName("declToImport"),
1236 parameterCountIs(2),
1237 hasParameter(0, hasName("y")),
1238 hasParameter(1, hasName("x")),
1239 hasParameter(1, hasType(asString("X<int> &"))));
1240 ASSERT_TRUE(Verifier.match(From, Matcher));
1241 EXPECT_TRUE(Verifier.match(To, Matcher));
1242}
1243
1244TEST_P(ASTImporterTestBase,
1245 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1246 Decl *From, *To;
1247 std::tie(From, To) =
1248 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1249 "void instantiate() { declToImport<int>(); }",
1250 Lang_CXX, "", Lang_CXX);
1251
1252 auto Check = [](Decl *D) -> bool {
1253 auto TU = D->getTranslationUnitDecl();
1254 for (auto Child : TU->decls()) {
1255 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1256 if (FD->getNameAsString() == "declToImport") {
1257 GTEST_NONFATAL_FAILURE_(
1258 "TU should not contain any FunctionDecl with name declToImport");
1259 return false;
1260 }
1261 }
1262 }
1263 return true;
1264 };
1265
1266 ASSERT_TRUE(Check(From));
1267 EXPECT_TRUE(Check(To));
1268}
1269
1270TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1271 Decl *From, *To;
1272 std::tie(From, To) =
1273 getImportedDecl("template <typename T> struct declToImport { T t; };"
1274 "void instantiate() { declToImport<int>(); }",
1275 Lang_CXX, "", Lang_CXX);
1276
1277 auto Check = [](Decl *D) -> bool {
1278 auto TU = D->getTranslationUnitDecl();
1279 for (auto Child : TU->decls()) {
1280 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1281 if (RD->getNameAsString() == "declToImport") {
1282 GTEST_NONFATAL_FAILURE_(
1283 "TU should not contain any CXXRecordDecl with name declToImport");
1284 return false;
1285 }
1286 }
1287 }
1288 return true;
1289 };
1290
1291 ASSERT_TRUE(Check(From));
1292 EXPECT_TRUE(Check(To));
1293}
1294
1295TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1296 Decl *From, *To;
1297 std::tie(From, To) =
1298 getImportedDecl(
1299 "template <typename T> struct X {};"
1300 "template <typename T> using declToImport = X<T>;"
1301 "void instantiate() { declToImport<int> a; }",
1302 Lang_CXX11, "", Lang_CXX11);
1303
1304 auto Check = [](Decl *D) -> bool {
1305 auto TU = D->getTranslationUnitDecl();
1306 for (auto Child : TU->decls()) {
1307 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1308 if (AD->getNameAsString() == "declToImport") {
1309 GTEST_NONFATAL_FAILURE_(
1310 "TU should not contain any TypeAliasDecl with name declToImport");
1311 return false;
1312 }
1313 }
1314 }
1315 return true;
1316 };
1317
1318 ASSERT_TRUE(Check(From));
1319 EXPECT_TRUE(Check(To));
1320}
1321
1322TEST_P(
1323 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001324 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001325
1326 Decl *From, *To;
1327 std::tie(From, To) = getImportedDecl(
1328 R"(
1329 template<class T>
1330 class Base {};
1331 class declToImport : public Base<declToImport> {};
1332 )",
1333 Lang_CXX, "", Lang_CXX);
1334
1335 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1336 auto Pattern =
1337 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1338 ASSERT_TRUE(
1339 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1340 EXPECT_TRUE(
1341 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1342
1343 // Check that the ClassTemplateSpecializationDecl is the child of the
1344 // ClassTemplateDecl.
1345 Pattern = translationUnitDecl(has(classTemplateDecl(
1346 hasName("Base"), has(classTemplateSpecializationDecl()))));
1347 ASSERT_TRUE(
1348 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1349 EXPECT_TRUE(
1350 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1351}
1352
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001353AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1354 size_t Index = 0;
1355 for (FieldDecl *Field : Node.fields()) {
1356 if (Index == Order.size())
1357 return false;
1358 if (Field->getName() != Order[Index])
1359 return false;
1360 ++Index;
1361 }
1362 return Index == Order.size();
1363}
1364
Peter Szecsidedda6f2018-03-30 22:03:29 +00001365TEST_P(ASTImporterTestBase,
1366 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1367 Decl *From, *To;
1368 std::tie(From, To) = getImportedDecl(
1369 R"(
1370 namespace NS {
1371 template<class T>
1372 class X {};
1373 template class X<int>;
1374 }
1375 )",
1376 Lang_CXX, "", Lang_CXX, "NS");
1377
1378 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1379 // ClassTemplateDecl.
1380 auto Pattern = namespaceDecl(has(classTemplateDecl(
1381 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1382 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1383 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1384
1385 // Check that the ClassTemplateSpecializationDecl is the child of the
1386 // NamespaceDecl.
1387 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1388 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1389 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1390}
1391
1392TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1393 Decl *From, *To;
1394 std::tie(From, To) =
1395 getImportedDecl(
1396 "struct declToImport { int a; int b; };",
1397 Lang_CXX11, "", Lang_CXX11);
1398
1399 MatchVerifier<Decl> Verifier;
1400 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1401 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1402}
1403
1404TEST_P(ASTImporterTestBase,
1405 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1406 Decl *From, *To;
1407 std::tie(From, To) = getImportedDecl(
1408 // The original recursive algorithm of ASTImporter first imports 'c' then
1409 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1410 R"s(
1411 struct declToImport {
1412 int a = c + b;
1413 int b = 1;
1414 int c = 2;
1415 };
1416 )s",
1417 Lang_CXX11, "", Lang_CXX11);
1418
1419 MatchVerifier<Decl> Verifier;
1420 ASSERT_TRUE(
1421 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1422 EXPECT_TRUE(
1423 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1424}
1425
Gabor Martonde8bf262018-05-17 09:46:07 +00001426TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001427 Decl *From, *To;
1428 std::tie(From, To) = getImportedDecl(
1429 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001430 struct declToImport {
1431 };
1432 )",
1433 Lang_CXX, "", Lang_CXX);
1434
1435 MatchVerifier<Decl> Verifier;
1436 // Match the implicit Decl.
1437 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1438 ASSERT_TRUE(Verifier.match(From, Matcher));
1439 EXPECT_TRUE(Verifier.match(To, Matcher));
1440}
1441
1442TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1443 Decl *From, *To;
1444 std::tie(From, To) = getImportedDecl(
1445 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001446 template <typename U>
1447 struct declToImport {
1448 };
1449 )",
1450 Lang_CXX, "", Lang_CXX);
1451
1452 MatchVerifier<Decl> Verifier;
1453 // Match the implicit Decl.
1454 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1455 ASSERT_TRUE(Verifier.match(From, Matcher));
1456 EXPECT_TRUE(Verifier.match(To, Matcher));
1457}
1458
1459TEST_P(
1460 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001461 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001462 Decl *From, *To;
1463 std::tie(From, To) = getImportedDecl(
1464 R"(
1465 template<class T>
1466 class Base {};
1467 class declToImport : public Base<declToImport> {};
1468 )",
1469 Lang_CXX, "", Lang_CXX);
1470
1471 auto hasImplicitClass = has(cxxRecordDecl());
1472 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1473 hasName("Base"),
1474 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1475 ASSERT_TRUE(
1476 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1477 EXPECT_TRUE(
1478 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1479}
1480
1481TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1482 Decl *From, *To;
1483 std::tie(From, To) =
1484 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1485
1486 MatchVerifier<Decl> Verifier;
1487 auto Matcher = functionDecl();
1488 ASSERT_TRUE(Verifier.match(From, Matcher));
1489 EXPECT_TRUE(Verifier.match(To, Matcher));
1490 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1491}
1492
Gabor Marton2ae9da32018-05-18 15:46:18 +00001493TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001494 Decl *FromTU = getTuDecl(
1495 R"(
1496 struct X {};
1497 void operator<<(int, X);
1498 )",
1499 Lang_CXX);
1500 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1501 const Decl *To = Import(From, Lang_CXX);
1502 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1503}
1504
1505TEST_P(ASTImporterTestBase,
1506 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1507 Decl *From, *To;
1508 std::tie(From, To) = getImportedDecl(
1509 R"(
1510 template<class T>
1511 class Base { int a; };
1512 class declToImport : Base<declToImport> {};
1513 )",
1514 Lang_CXX, "", Lang_CXX);
1515
1516 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1517 hasName("Base"),
1518 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1519 ASSERT_TRUE(
1520 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1521 EXPECT_TRUE(
1522 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1523}
1524
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001525TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1526 {
1527 Decl *FromTU = getTuDecl(
1528 R"(
1529 template <typename T>
1530 struct B;
1531 )",
1532 Lang_CXX, "input0.cc");
1533 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1534 FromTU, classTemplateDecl(hasName("B")));
1535
1536 Import(FromD, Lang_CXX);
1537 }
1538
1539 {
1540 Decl *FromTU = getTuDecl(
1541 R"(
1542 template <typename T>
1543 struct B {
1544 void f();
1545 };
1546 )",
1547 Lang_CXX, "input1.cc");
1548 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1549 FromTU, functionDecl(hasName("f")));
1550 Import(FromD, Lang_CXX);
1551 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1552 FromTU, classTemplateDecl(hasName("B")));
1553 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1554 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1555 }
1556}
1557
Gabor Marton9581c332018-05-23 13:53:36 +00001558TEST_P(ASTImporterTestBase,
1559 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1560 Decl *ToTU = getToTuDecl(
1561 R"(
1562 template <typename T>
1563 struct B {
1564 void f();
1565 };
1566
1567 template <typename T>
1568 struct B;
1569 )",
1570 Lang_CXX);
1571 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1572 [](const ClassTemplateDecl *T) {
1573 return T->isThisDeclarationADefinition();
1574 })
1575 .match(ToTU, classTemplateDecl()));
1576
1577 Decl *FromTU = getTuDecl(
1578 R"(
1579 template <typename T>
1580 struct B {
1581 void f();
1582 };
1583 )",
1584 Lang_CXX, "input1.cc");
1585 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1586 FromTU, classTemplateDecl(hasName("B")));
1587
1588 Import(FromD, Lang_CXX);
1589
1590 // We should have only one definition.
1591 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1592 [](const ClassTemplateDecl *T) {
1593 return T->isThisDeclarationADefinition();
1594 })
1595 .match(ToTU, classTemplateDecl()));
1596}
1597
1598TEST_P(ASTImporterTestBase,
1599 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1600 Decl *ToTU = getToTuDecl(
1601 R"(
1602 struct B {
1603 void f();
1604 };
1605
1606 struct B;
1607 )",
1608 Lang_CXX);
1609 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001610 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001611
1612 Decl *FromTU = getTuDecl(
1613 R"(
1614 struct B {
1615 void f();
1616 };
1617 )",
1618 Lang_CXX, "input1.cc");
1619 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1620 FromTU, cxxRecordDecl(hasName("B")));
1621
1622 Import(FromD, Lang_CXX);
1623
1624 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001625 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001626}
1627
1628TEST_P(
1629 ASTImporterTestBase,
1630 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1631{
1632 Decl *ToTU = getToTuDecl(
1633 R"(
1634 template <typename T>
1635 struct B;
1636
1637 template <>
1638 struct B<int> {};
1639
1640 template <>
1641 struct B<int>;
1642 )",
1643 Lang_CXX);
1644 // We should have only one definition.
1645 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1646 [](const ClassTemplateSpecializationDecl *T) {
1647 return T->isThisDeclarationADefinition();
1648 })
1649 .match(ToTU, classTemplateSpecializationDecl()));
1650
1651 Decl *FromTU = getTuDecl(
1652 R"(
1653 template <typename T>
1654 struct B;
1655
1656 template <>
1657 struct B<int> {};
1658 )",
1659 Lang_CXX, "input1.cc");
1660 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1661 FromTU, classTemplateSpecializationDecl(hasName("B")));
1662
1663 Import(FromD, Lang_CXX);
1664
1665 // We should have only one definition.
1666 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1667 [](const ClassTemplateSpecializationDecl *T) {
1668 return T->isThisDeclarationADefinition();
1669 })
1670 .match(ToTU, classTemplateSpecializationDecl()));
1671}
1672
Peter Szecsidedda6f2018-03-30 22:03:29 +00001673struct ImportFunctions : ASTImporterTestBase {};
1674
1675TEST_P(ImportFunctions,
1676 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
1677 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
1678 auto Pattern = functionDecl(hasName("f"));
1679 FunctionDecl *FromD =
1680 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1681
1682 Decl *ImportedD = Import(FromD, Lang_CXX);
1683 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1684
1685 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1686 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1687}
1688
1689TEST_P(ImportFunctions,
1690 PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) {
1691 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1692 auto Pattern = functionDecl(hasName("f"));
1693 FunctionDecl *FromD = // Prototype
1694 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1695
1696 Decl *ImportedD = Import(FromD, Lang_CXX);
1697 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1698
1699 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1700 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1701}
1702
1703TEST_P(ImportFunctions,
1704 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1705 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1706 auto Pattern = functionDecl(hasName("f"));
1707 FunctionDecl *FromD = // Definition
1708 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1709
1710 Decl *ImportedD = Import(FromD, Lang_CXX);
1711 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1712
1713 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1714 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1715}
1716
1717TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1718 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1719 auto Pattern = functionDecl(hasName("f"));
1720 FunctionDecl *FromD =
1721 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1722
1723 Decl *ImportedD = Import(FromD, Lang_CXX);
1724 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1725
1726 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1727 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1728}
1729
1730TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) {
1731 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1732 auto Pattern = functionDecl(hasName("f"));
1733 FunctionDecl *PrototypeFD =
1734 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1735
1736 Decl *ImportedD = Import(PrototypeFD, Lang_CXX);
1737 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1738
1739 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1740 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1741}
1742
1743TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1744 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1745 auto Pattern = functionDecl(hasName("f"));
1746 FunctionDecl *DefinitionFD =
1747 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1748
1749 Decl *ImportedD = Import(DefinitionFD, Lang_CXX);
1750 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1751
1752 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1753 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1754}
1755
1756TEST_P(ImportFunctions, ImportPrototypes) {
1757 auto Pattern = functionDecl(hasName("f"));
1758
1759 Decl *ImportedD;
1760 {
1761 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1762 FunctionDecl *FromD =
1763 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1764
1765 ImportedD = Import(FromD, Lang_CXX);
1766 }
1767 Decl *ImportedD1;
1768 {
1769 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1770 FunctionDecl *FromD =
1771 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1772 ImportedD1 = Import(FromD, Lang_CXX);
1773 }
1774
1775 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1776 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1777 EXPECT_EQ(ImportedD, ImportedD1);
1778 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1779}
1780
1781TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1782 auto Pattern = functionDecl(hasName("f"));
1783
1784 Decl *ImportedD;
1785 {
1786 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1787 FunctionDecl *FromD =
1788 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1789
1790 ImportedD = Import(FromD, Lang_CXX);
1791 }
1792 Decl *ImportedD1;
1793 {
1794 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1795 FunctionDecl *FromD =
1796 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1797 ImportedD1 = Import(FromD, Lang_CXX);
1798 }
1799
1800 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1801 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1802 EXPECT_EQ(ImportedD, ImportedD1);
1803 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1804}
1805
1806TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1807 auto Pattern = functionDecl(hasName("f"));
1808
1809 {
1810 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1811 FunctionDecl *FromD =
1812 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1813
1814 Import(FromD, Lang_CXX);
1815 }
1816 {
1817 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1818 FunctionDecl *FromD =
1819 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1820 Import(FromD, Lang_CXX);
1821 }
1822
1823 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1824 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1825 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1826 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1827 FunctionDecl *DefinitionD =
1828 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1829 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1830 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1831}
1832
1833TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) {
1834 auto Pattern = functionDecl(hasName("f"));
1835
1836 {
1837 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1838 FunctionDecl *FromD =
1839 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1840
1841 Import(FromD, Lang_CXX);
1842 }
1843 {
1844 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
1845 FunctionDecl *FromD =
1846 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1847 Import(FromD, Lang_CXX);
1848 }
1849
1850 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1851 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1852 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1853 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1854 FunctionDecl *DefinitionD =
1855 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1856 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1857 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1858}
1859
1860TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1861 auto Code =
1862 R"(
1863 struct B { virtual void f(); };
1864 void B::f() {}
1865 struct D : B { void f(); };
1866 )";
1867 auto Pattern =
1868 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1869 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1870 CXXMethodDecl *Proto =
1871 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1872
1873 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1874 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1875 EXPECT_EQ(To->size_overridden_methods(), 1u);
1876}
1877
1878TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1879 auto Code =
1880 R"(
1881 struct B { virtual void f(); };
1882 void B::f() {}
1883 )";
1884 auto Pattern =
1885 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1886 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1887 CXXMethodDecl *Proto =
1888 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1889 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1890
1891 ASSERT_TRUE(Proto->isVirtual());
1892 ASSERT_TRUE(Def->isVirtual());
1893 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1894 EXPECT_TRUE(To->isVirtual());
1895}
1896
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001897AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
1898 InnerMatcher) {
1899 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
1900 return InnerMatcher.matches(*Typedef, Finder, Builder);
1901 return false;
1902}
1903
Gabor Marton19f4f392018-06-25 13:04:37 +00001904TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001905 CodeFiles Samples{{"main.c",
1906 {"void foo();"
1907 "void moo();"
1908 "int main() { foo(); moo(); }",
1909 Lang_C}},
1910
1911 {"foo.c",
1912 {"typedef enum { THING_VALUE } thing_t;"
1913 "void conflict(thing_t type);"
1914 "void foo() { (void)THING_VALUE; }"
1915 "void conflict(thing_t type) {}",
1916 Lang_C}},
1917
1918 {"moo.c",
1919 {"typedef enum { THING_VALUE } thing_t;"
1920 "void conflict(thing_t type);"
1921 "void moo() { conflict(THING_VALUE); }",
1922 Lang_C}}};
1923
1924 auto VerificationMatcher =
1925 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
1926 hasTypedefForAnonDecl(hasName("thing_t")));
1927
1928 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
1929 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
1930
1931 testImportSequence(
1932 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
1933 // Just check that there is only one enum decl in the result AST.
1934 "main.c", enumDecl(), VerificationMatcher);
1935
1936 // For different import order, result should be the same.
1937 testImportSequence(
1938 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
1939 // Check that there is only one enum decl in the result AST.
1940 "main.c", enumDecl(), VerificationMatcher);
1941}
1942
Peter Szecsice7f3182018-05-07 12:08:27 +00001943const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
1944 dependentScopeDeclRefExpr;
1945
Gabor Marton19f4f392018-06-25 13:04:37 +00001946TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00001947 MatchVerifier<Decl> Verifier;
1948 testImport("template <typename T> struct S { static T foo; };"
1949 "template <typename T> void declToImport() {"
1950 " (void) S<T>::foo;"
1951 "}"
1952 "void instantiate() { declToImport<int>(); }",
1953 Lang_CXX11, "", Lang_CXX11, Verifier,
1954 functionTemplateDecl(has(functionDecl(has(compoundStmt(
1955 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
1956
1957 testImport("template <typename T> struct S {"
1958 "template<typename S> static void foo(){};"
1959 "};"
1960 "template <typename T> void declToImport() {"
1961 " S<T>::template foo<T>();"
1962 "}"
1963 "void instantiate() { declToImport<int>(); }",
1964 Lang_CXX11, "", Lang_CXX11, Verifier,
1965 functionTemplateDecl(has(functionDecl(has(compoundStmt(
1966 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
1967}
1968
1969const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
1970 dependentNameType;
1971
Gabor Marton19f4f392018-06-25 13:04:37 +00001972TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00001973 MatchVerifier<Decl> Verifier;
1974 testImport("template <typename T> struct declToImport {"
1975 " typedef typename T::type dependent_name;"
1976 "};",
1977 Lang_CXX11, "", Lang_CXX11, Verifier,
1978 classTemplateDecl(has(
1979 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
1980}
1981
1982const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
1983 unresolvedMemberExpr;
1984
Gabor Marton19f4f392018-06-25 13:04:37 +00001985TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00001986 MatchVerifier<Decl> Verifier;
1987 testImport("struct S { template <typename T> void mem(); };"
1988 "template <typename U> void declToImport() {"
1989 " S s;"
1990 " s.mem<U>();"
1991 "}"
1992 "void instantiate() { declToImport<int>(); }",
1993 Lang_CXX11, "", Lang_CXX11, Verifier,
1994 functionTemplateDecl(has(functionDecl(has(
1995 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
1996}
1997
Gabor Marton61d862a2018-05-18 09:08:47 +00001998struct DeclContextTest : ASTImporterTestBase {};
1999
2000TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
2001 Decl *TU = getTuDecl(
2002 R"(
2003 namespace NS {
2004
2005 template <typename T>
2006 struct S {};
2007 template struct S<int>;
2008
2009 inline namespace INS {
2010 template <typename T>
2011 struct S {};
2012 template struct S<int>;
2013 }
2014
2015 }
2016 )", Lang_CXX11, "input0.cc");
2017 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
2018 TU, namespaceDecl());
2019 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2020 TU, classTemplateSpecializationDecl());
2021 ASSERT_TRUE(NS->containsDecl(Spec));
2022
2023 NS->removeDecl(Spec);
2024 EXPECT_FALSE(NS->containsDecl(Spec));
2025}
2026
Gabor Marton19f4f392018-06-25 13:04:37 +00002027INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
2028 ::testing::Values(ArgVector()), );
2029
2030auto DefaultTestValuesForRunOptions = ::testing::Values(
2031 ArgVector(),
2032 ArgVector{"-fdelayed-template-parsing"},
2033 ArgVector{"-fms-compatibility"},
2034 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
2035
2036INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
2037 DefaultTestValuesForRunOptions, );
2038
2039INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
2040 DefaultTestValuesForRunOptions, );
2041
2042INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
2043 DefaultTestValuesForRunOptions, );
2044
2045INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
2046 DefaultTestValuesForRunOptions, );
2047
2048INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
2049 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00002050
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00002051} // end namespace ast_matchers
2052} // end namespace clang