blob: 18c8f4cc02c3f70874824613e18805578c284309 [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"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000022#include "gtest/gtest.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000023#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000024
25namespace clang {
26namespace ast_matchers {
27
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000028using internal::Matcher;
29using internal::BindableMatcher;
30using llvm::StringMap;
31
Aleksei Sidorine45ab562017-12-21 17:41:06 +000032typedef std::vector<std::string> ArgVector;
33typedef std::vector<ArgVector> RunOptions;
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000034
Aleksei Sidorine45ab562017-12-21 17:41:06 +000035static bool isCXX(Language Lang) {
36 return Lang == Lang_CXX || Lang == Lang_CXX11;
37}
38
Peter Szecsidedda6f2018-03-30 22:03:29 +000039static ArgVector getBasicRunOptionsForLanguage(Language Lang) {
Aleksei Sidorine45ab562017-12-21 17:41:06 +000040 ArgVector BasicArgs;
41 // Test with basic arguments.
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000042 switch (Lang) {
43 case Lang_C:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000044 BasicArgs = {"-x", "c", "-std=c99"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000045 break;
46 case Lang_C89:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000047 BasicArgs = {"-x", "c", "-std=c89"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000048 break;
49 case Lang_CXX:
Gabor Horvathd2c562d2018-01-27 16:38:56 +000050 BasicArgs = {"-std=c++98", "-frtti"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000051 break;
52 case Lang_CXX11:
Gabor Horvathd2c562d2018-01-27 16:38:56 +000053 BasicArgs = {"-std=c++11", "-frtti"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000054 break;
55 case Lang_OpenCL:
56 case Lang_OBJCXX:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000057 llvm_unreachable("Not implemented yet!");
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000058 }
Peter Szecsidedda6f2018-03-30 22:03:29 +000059 return BasicArgs;
60}
61
62static RunOptions getRunOptionsForLanguage(Language Lang) {
63 ArgVector BasicArgs = getBasicRunOptionsForLanguage(Lang);
Aleksei Sidorine45ab562017-12-21 17:41:06 +000064
65 // For C++, test with "-fdelayed-template-parsing" enabled to handle MSVC
66 // default behaviour.
67 if (isCXX(Lang)) {
68 ArgVector ArgsForDelayedTemplateParse = BasicArgs;
69 ArgsForDelayedTemplateParse.emplace_back("-fdelayed-template-parsing");
70 return {BasicArgs, ArgsForDelayedTemplateParse};
71 }
72
73 return {BasicArgs};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000074}
75
Peter Szecsidedda6f2018-03-30 22:03:29 +000076// Creates a virtual file and assigns that to the context of given AST. If the
77// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000078static void
79createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
80 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000081 assert(ToAST);
82 ASTContext &ToCtx = ToAST->getASTContext();
83 auto *OFS = static_cast<vfs::OverlayFileSystem *>(
84 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
85 auto *MFS =
86 static_cast<vfs::InMemoryFileSystem *>(OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000087 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000088}
89
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000090static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
91 StringRef Code) {
92 return createVirtualFileIfNeeded(ToAST, FileName,
93 llvm::MemoryBuffer::getMemBuffer(Code));
94}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000095
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000096template <typename NodeType>
97NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
98 NodeType Node) {
99 ASTContext &ToCtx = To->getASTContext();
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000100
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000101 // Add 'From' file to virtual file system so importer can 'find' it
102 // while importing SourceLocations. It is safe to add same file multiple
103 // times - it just isn't replaced.
104 StringRef FromFileName = From->getMainFileName();
105 createVirtualFileIfNeeded(To, FromFileName,
106 From->getBufferForFile(FromFileName));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000107
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000108 auto Imported = Importer.Import(Node);
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000109
110 // This should dump source locations and assert if some source locations
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000111 // were not imported.
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000112 SmallString<1024> ImportChecker;
113 llvm::raw_svector_ostream ToNothing(ImportChecker);
114 ToCtx.getTranslationUnitDecl()->print(ToNothing);
115
Gabor Horvath480892b2017-10-18 09:25:18 +0000116 // This traverses the AST to catch certain bugs like poorly or not
117 // implemented subtrees.
118 Imported->dump(ToNothing);
119
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000120 return Imported;
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000121}
122
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000123const StringRef DeclToImportID = "declToImport";
124const StringRef DeclToVerifyID = "declToVerify";
125
126template <typename NodeType>
127testing::AssertionResult
128testImport(const std::string &FromCode, const ArgVector &FromArgs,
129 const std::string &ToCode, const ArgVector &ToArgs,
130 MatchVerifier<NodeType> &Verifier,
131 const BindableMatcher<NodeType> &SearchMatcher,
132 const BindableMatcher<NodeType> &VerificationMatcher) {
133 const char *const InputFileName = "input.cc";
134 const char *const OutputFileName = "output.cc";
135
136 std::unique_ptr<ASTUnit>
137 FromAST = tooling::buildASTFromCodeWithArgs(
138 FromCode, FromArgs, InputFileName),
139 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
140
141 ASTContext &FromCtx = FromAST->getASTContext(),
142 &ToCtx = ToAST->getASTContext();
143
144 ASTImporter Importer(ToCtx, ToAST->getFileManager(),
145 FromCtx, FromAST->getFileManager(), false);
146
147 auto FoundNodes = match(SearchMatcher, FromCtx);
148 if (FoundNodes.size() != 1)
149 return testing::AssertionFailure()
150 << "Multiple potential nodes were found!";
151
152 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
153 if (!ToImport)
154 return testing::AssertionFailure() << "Node type mismatch!";
155
156 // Sanity check: the node being imported should match in the same way as
157 // the result node.
158 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
159 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
160
161 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
162 if (!Imported)
163 return testing::AssertionFailure() << "Import failed, nullptr returned!";
164
165 return Verifier.match(Imported, WrapperMatcher);
166}
167
168template <typename NodeType>
169testing::AssertionResult
170testImport(const std::string &FromCode, const ArgVector &FromArgs,
171 const std::string &ToCode, const ArgVector &ToArgs,
172 MatchVerifier<NodeType> &Verifier,
173 const BindableMatcher<NodeType> &VerificationMatcher) {
174 return testImport(
175 FromCode, FromArgs, ToCode, ToArgs, Verifier,
176 translationUnitDecl(
177 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
178 VerificationMatcher);
179}
180
181/// Test how AST node named "declToImport" located in the translation unit
182/// of "FromCode" virtual file is imported to "ToCode" virtual file.
183/// The verification is done by running AMatcher over the imported node.
184template <typename NodeType, typename MatcherType>
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000185void testImport(const std::string &FromCode, Language FromLang,
186 const std::string &ToCode, Language ToLang,
187 MatchVerifier<NodeType> &Verifier,
188 const MatcherType &AMatcher) {
189 auto RunOptsFrom = getRunOptionsForLanguage(FromLang);
190 auto RunOptsTo = getRunOptionsForLanguage(ToLang);
191 for (const auto &FromArgs : RunOptsFrom)
192 for (const auto &ToArgs : RunOptsTo)
193 EXPECT_TRUE(testImport(FromCode, FromArgs, ToCode, ToArgs,
194 Verifier, AMatcher));
195}
196
Peter Szecsidedda6f2018-03-30 22:03:29 +0000197// This class provides generic methods to write tests which can check internal
198// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
199// this fixture makes it possible to import from several "From" contexts.
200class ASTImporterTestBase : public ::testing::TestWithParam<ArgVector> {
201
202 const char *const InputFileName = "input.cc";
203 const char *const OutputFileName = "output.cc";
204
205 // Buffer for the To context, must live in the test scope.
206 std::string ToCode;
207
208 struct TU {
209 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000210 std::string Code;
211 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000212 std::unique_ptr<ASTUnit> Unit;
213 TranslationUnitDecl *TUDecl = nullptr;
214 TU(StringRef Code, StringRef FileName, ArgVector Args)
215 : Code(Code), FileName(FileName),
216 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
217 this->FileName)),
218 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {}
219 };
220
221 // We may have several From contexts and related translation units. In each
222 // AST, the buffers for the source are handled via references and are set
223 // during the creation of the AST. These references must point to a valid
224 // buffer until the AST is alive. Thus, we must use a list in order to avoid
225 // moving of the stored objects because that would mean breaking the
226 // references in the AST. By using a vector a move could happen when the
227 // vector is expanding, with the list we won't have these issues.
228 std::list<TU> FromTUs;
229
230public:
231 // We may have several From context but only one To context.
232 std::unique_ptr<ASTUnit> ToAST;
233
234 // Returns the argument vector used for a specific language, this set
235 // can be tweaked by the test parameters.
236 ArgVector getArgVectorForLanguage(Language Lang) {
237 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
238 ArgVector ExtraArgs = GetParam();
239 for (const auto& Arg : ExtraArgs) {
240 Args.push_back(Arg);
241 }
242 return Args;
243 }
244
245 // Creates an AST both for the From and To source code and imports the Decl
246 // of the identifier into the To context.
247 // Must not be called more than once within the same test.
248 std::tuple<Decl *, Decl *>
249 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
250 Language ToLang, StringRef Identifier = DeclToImportID) {
251 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
252 ToArgs = getArgVectorForLanguage(ToLang);
253
254 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
255 TU &FromTU = FromTUs.back();
256
257 ToCode = ToSrcCode;
258 assert(!ToAST);
259 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
260
261 ASTContext &FromCtx = FromTU.Unit->getASTContext(),
262 &ToCtx = ToAST->getASTContext();
263
264 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
265
266 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
267 FromTU.Unit->getFileManager(), false);
268
269 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
270 assert(ImportedII && "Declaration with the given identifier "
271 "should be specified in test!");
272 DeclarationName ImportDeclName(ImportedII);
273 SmallVector<NamedDecl *, 4> FoundDecls;
274 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
275 FoundDecls);
276
277 assert(FoundDecls.size() == 1);
278
279 Decl *Imported = Importer.Import(FoundDecls.front());
280 assert(Imported);
281 return std::make_tuple(*FoundDecls.begin(), Imported);
282 }
283
Gabor Marton9581c332018-05-23 13:53:36 +0000284 // Creates a TU decl for the given source code which can be used as a From
285 // context. May be called several times in a given test (with different file
286 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000287 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
288 StringRef FileName = "input.cc") {
289 assert(
290 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
291 return E.FileName == FileName;
292 }) == FromTUs.end());
293
294 ArgVector Args = getArgVectorForLanguage(Lang);
295 FromTUs.emplace_back(SrcCode, FileName, Args);
296 TU &Tu = FromTUs.back();
297
298 return Tu.TUDecl;
299 }
300
Gabor Marton9581c332018-05-23 13:53:36 +0000301 // Creates the To context with the given source code and returns the TU decl.
302 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
303 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
304 ToCode = ToSrcCode;
305 assert(!ToAST);
306 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
307
308 return ToAST->getASTContext().getTranslationUnitDecl();
309 }
310
Peter Szecsidedda6f2018-03-30 22:03:29 +0000311 // Import the given Decl into the ToCtx.
312 // May be called several times in a given test.
313 // The different instances of the param From may have different ASTContext.
314 Decl *Import(Decl *From, Language ToLang) {
315 if (!ToAST) {
316 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
317 // Build the AST from an empty file.
318 ToAST =
319 tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
320 }
321
322 // Create a virtual file in the To Ctx which corresponds to the file from
323 // which we want to import the `From` Decl. Without this source locations
324 // will be invalid in the ToCtx.
325 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
326 return E.TUDecl == From->getTranslationUnitDecl();
327 });
328 assert(It != FromTUs.end());
329 createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code);
330
331 ASTContext &FromCtx = From->getASTContext(),
332 &ToCtx = ToAST->getASTContext();
333 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
334 FromCtx.getSourceManager().getFileManager(), false);
335 return Importer.Import(From);
336 }
337
338 ~ASTImporterTestBase() {
339 if (!::testing::Test::HasFailure()) return;
340
341 for (auto &Tu : FromTUs) {
342 assert(Tu.Unit);
343 llvm::errs() << "FromAST:\n";
344 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
345 llvm::errs() << "\n";
346 }
347 if (ToAST) {
348 llvm::errs() << "ToAST:\n";
349 ToAST->getASTContext().getTranslationUnitDecl()->dump();
350 }
351 }
352};
353
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000354
355struct ImportAction {
356 StringRef FromFilename;
357 StringRef ToFilename;
358 // FIXME: Generalize this to support other node kinds.
359 BindableMatcher<Decl> ImportPredicate;
360
361 ImportAction(StringRef FromFilename, StringRef ToFilename,
362 DeclarationMatcher ImportPredicate)
363 : FromFilename(FromFilename), ToFilename(ToFilename),
364 ImportPredicate(ImportPredicate) {}
365
366 ImportAction(StringRef FromFilename, StringRef ToFilename,
367 const std::string &DeclName)
368 : FromFilename(FromFilename), ToFilename(ToFilename),
369 ImportPredicate(namedDecl(hasName(DeclName))) {}
370};
371
372using SingleASTUnitForAllOpts = std::vector<std::unique_ptr<ASTUnit>>;
373using AllASTUnitsForAllOpts = StringMap<SingleASTUnitForAllOpts>;
374
375struct CodeEntry {
376 std::string CodeSample;
377 Language Lang;
378
379 /// Builds N copies of ASTUnits for each potential compile options set
380 /// for further import actions. N is equal to size of this option set.
381 SingleASTUnitForAllOpts createASTUnits(StringRef FileName) const {
382 auto RunOpts = getRunOptionsForLanguage(Lang);
383 size_t NumOpts = RunOpts.size();
384 SingleASTUnitForAllOpts ResultASTs(NumOpts);
385 for (size_t CompileOpt = 0; CompileOpt < NumOpts; ++CompileOpt) {
386 auto AST = tooling::buildASTFromCodeWithArgs(
387 CodeSample, RunOpts[CompileOpt], FileName);
388 EXPECT_TRUE(AST.get());
389 ResultASTs[CompileOpt] = std::move(AST);
390 }
391 return ResultASTs;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000392 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000393};
394
395using CodeFiles = StringMap<CodeEntry>;
396
397/// Test an arbitrary sequence of imports for a set of given in-memory files.
398/// The verification is done by running VerificationMatcher against a specified
399/// AST node inside of one of given files.
400/// \param CodeSamples Map whose key is the file name and the value is the file
401/// content.
402/// \param ImportActions Sequence of imports. Each import in sequence
403/// specifies "from file" and "to file" and a matcher that is used for
404/// searching a declaration for import in "from file".
405/// \param FileForFinalCheck Name of virtual file for which the final check is
406/// applied.
407/// \param FinalSelectPredicate Matcher that specifies the AST node in the
408/// FileForFinalCheck for which the verification will be done.
409/// \param VerificationMatcher Matcher that will be used for verification after
410/// all imports in sequence are done.
411void testImportSequence(const CodeFiles &CodeSamples,
412 const std::vector<ImportAction> &ImportActions,
413 StringRef FileForFinalCheck,
414 BindableMatcher<Decl> FinalSelectPredicate,
415 BindableMatcher<Decl> VerificationMatcher) {
416 AllASTUnitsForAllOpts AllASTUnits;
417 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
418 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
419
420 auto GenASTsIfNeeded = [&AllASTUnits, &CodeSamples](StringRef Filename) {
421 if (!AllASTUnits.count(Filename)) {
422 auto Found = CodeSamples.find(Filename);
423 assert(Found != CodeSamples.end() && "Wrong file for import!");
424 AllASTUnits[Filename] = Found->getValue().createASTUnits(Filename);
425 }
426 };
427
428 size_t NumCompileOpts = 0;
429 for (const ImportAction &Action : ImportActions) {
430 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
431 GenASTsIfNeeded(FromFile);
432 GenASTsIfNeeded(ToFile);
433 NumCompileOpts = AllASTUnits[FromFile].size();
434
435 for (size_t CompileOpt = 0; CompileOpt < NumCompileOpts; ++CompileOpt) {
436 ASTUnit *From = AllASTUnits[FromFile][CompileOpt].get();
437 ASTUnit *To = AllASTUnits[ToFile][CompileOpt].get();
438
439 // Create a new importer if needed.
440 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
441 if (!ImporterRef)
442 ImporterRef.reset(new ASTImporter(
443 To->getASTContext(), To->getFileManager(), From->getASTContext(),
444 From->getFileManager(), false));
445
446 // Find the declaration and import it.
447 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
448 From->getASTContext());
449 EXPECT_TRUE(FoundDecl.size() == 1);
450 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
451 auto Imported = importNode(From, To, *ImporterRef, ToImport);
452 EXPECT_TRUE(Imported);
453 }
454 }
455
456 // NOTE: We don't do cross-option import check here due to fast growth of
457 // potential option sets.
458 for (size_t CompileOpt = 0; CompileOpt < NumCompileOpts; ++CompileOpt) {
459 // Find the declaration and import it.
460 auto FoundDecl =
461 match(FinalSelectPredicate.bind(DeclToVerifyID),
462 AllASTUnits[FileForFinalCheck][CompileOpt]->getASTContext());
463 EXPECT_TRUE(FoundDecl.size() == 1);
464 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
465 MatchVerifier<Decl> Verifier;
466 EXPECT_TRUE(Verifier.match(ToVerify,
467 BindableMatcher<Decl>(VerificationMatcher)));
468 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000469}
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000470
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000471TEST(ImportExpr, ImportStringLiteral) {
472 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000473 testImport("void declToImport() { \"foo\"; }",
474 Lang_CXX, "", Lang_CXX, Verifier,
475 functionDecl(
476 hasBody(
477 compoundStmt(
478 has(
479 stringLiteral(
480 hasType(
481 asString("const char [4]"))))))));
482 testImport("void declToImport() { L\"foo\"; }",
483 Lang_CXX, "", Lang_CXX, Verifier,
484 functionDecl(
485 hasBody(
486 compoundStmt(
487 has(
488 stringLiteral(
489 hasType(
490 asString("const wchar_t [4]"))))))));
491 testImport("void declToImport() { \"foo\" \"bar\"; }",
492 Lang_CXX, "", Lang_CXX, Verifier,
493 functionDecl(
494 hasBody(
495 compoundStmt(
496 has(
497 stringLiteral(
498 hasType(
499 asString("const char [7]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000500}
501
502TEST(ImportExpr, ImportGNUNullExpr) {
503 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000504 testImport("void declToImport() { __null; }",
505 Lang_CXX, "", Lang_CXX, Verifier,
506 functionDecl(
507 hasBody(
508 compoundStmt(
509 has(
510 gnuNullExpr(
511 hasType(isInteger())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000512}
513
514TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
515 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000516 testImport("void declToImport() { nullptr; }",
517 Lang_CXX11, "", Lang_CXX11, Verifier,
518 functionDecl(
519 hasBody(
520 compoundStmt(
521 has(
522 cxxNullPtrLiteralExpr())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000523}
524
525
526TEST(ImportExpr, ImportFloatinglLiteralExpr) {
527 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000528 testImport("void declToImport() { 1.0; }",
529 Lang_C, "", Lang_C, Verifier,
530 functionDecl(
531 hasBody(
532 compoundStmt(
533 has(
534 floatLiteral(
535 equals(1.0),
536 hasType(asString("double"))))))));
537 testImport("void declToImport() { 1.0e-5f; }",
538 Lang_C, "", Lang_C, Verifier,
539 functionDecl(
540 hasBody(
541 compoundStmt(
542 has(
543 floatLiteral(
544 equals(1.0e-5f),
545 hasType(asString("float"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000546}
547
548TEST(ImportExpr, ImportCompoundLiteralExpr) {
549 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000550 testImport("void declToImport() {"
551 " struct s { int x; long y; unsigned z; }; "
552 " (struct s){ 42, 0L, 1U }; }",
553 Lang_CXX, "", Lang_CXX, Verifier,
554 functionDecl(
555 hasBody(
556 compoundStmt(
557 has(
558 compoundLiteralExpr(
559 hasType(asString("struct s")),
560 has(initListExpr(
561 hasType(asString("struct s")),
562 has(integerLiteral(
563 equals(42), hasType(asString("int")))),
564 has(integerLiteral(
565 equals(0), hasType(asString("long")))),
566 has(integerLiteral(
567 equals(1),
568 hasType(asString("unsigned int"))))
569 ))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000570}
571
572TEST(ImportExpr, ImportCXXThisExpr) {
573 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000574 testImport("class declToImport { void f() { this; } };",
575 Lang_CXX, "", Lang_CXX, Verifier,
576 cxxRecordDecl(
577 hasMethod(
578 hasBody(
579 compoundStmt(
580 has(
581 cxxThisExpr(
582 hasType(
583 asString("class declToImport *")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000584}
585
586TEST(ImportExpr, ImportAtomicExpr) {
587 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000588 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
589 Lang_C, "", Lang_C, Verifier,
590 functionDecl(hasBody(compoundStmt(has(atomicExpr(
591 has(ignoringParenImpCasts(
592 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
593 hasType(asString("int *"))))),
594 has(integerLiteral(equals(1), hasType(asString("int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000595}
596
597TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
598 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000599 testImport(
600 "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C,
601 Verifier,
602 functionDecl(hasBody(compoundStmt(
603 has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
604 has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000605}
606
607AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
608 internal::Matcher<NamedDecl>, InnerMatcher) {
609 const NamedDecl *Template = Node.getTemplatedDecl();
610 return Template && InnerMatcher.matches(*Template, Finder, Builder);
611}
612
613TEST(ImportExpr, ImportParenListExpr) {
614 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000615 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000616 "template<typename T> class dummy { void f() { dummy X(*this); } };"
617 "typedef dummy<int> declToImport;"
618 "template class dummy<int>;",
619 Lang_CXX, "", Lang_CXX, Verifier,
620 typedefDecl(hasType(templateSpecializationType(
621 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
622 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
623 hasName("f"),
624 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
625 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
626 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000627 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000628}
629
Gabor Horvath480892b2017-10-18 09:25:18 +0000630TEST(ImportExpr, ImportSwitch) {
631 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000632 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
633 Lang_C, "", Lang_C, Verifier,
634 functionDecl(hasBody(compoundStmt(
635 has(switchStmt(has(compoundStmt(has(caseStmt())))))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000636}
637
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000638TEST(ImportExpr, ImportStmtExpr) {
639 MatchVerifier<Decl> Verifier;
640 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000641 testImport(
642 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
643 Lang_C, "", Lang_C, Verifier,
644 functionDecl(
645 hasBody(
646 compoundStmt(
647 has(
648 declStmt(
649 hasSingleDecl(
650 varDecl(
651 hasName("C"),
652 hasType(asString("int")),
653 hasInitializer(
654 stmtExpr(
655 hasAnySubstatement(
656 declStmt(
657 hasSingleDecl(
658 varDecl(
659 hasName("X"),
660 hasType(asString("int")),
661 hasInitializer(
662 integerLiteral(equals(4))))))),
663 hasDescendant(
664 implicitCastExpr()
665 )))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000666}
667
668TEST(ImportExpr, ImportConditionalOperator) {
669 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000670 testImport(
671 "void declToImport() { true ? 1 : -5; }",
672 Lang_CXX, "", Lang_CXX, Verifier,
673 functionDecl(
674 hasBody(
675 compoundStmt(
676 has(
677 conditionalOperator(
678 hasCondition(cxxBoolLiteral(equals(true))),
679 hasTrueExpression(integerLiteral(equals(1))),
680 hasFalseExpression(
681 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
682 )))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000683}
684
685TEST(ImportExpr, ImportBinaryConditionalOperator) {
686 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000687 testImport(
688 "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier,
689 functionDecl(
690 hasBody(
691 compoundStmt(
692 has(
693 binaryConditionalOperator(
694 hasCondition(
695 implicitCastExpr(
696 hasSourceExpression(
697 opaqueValueExpr(
698 hasSourceExpression(integerLiteral(equals(1))))),
699 hasType(booleanType()))),
700 hasTrueExpression(
701 opaqueValueExpr(hasSourceExpression(
702 integerLiteral(equals(1))))),
703 hasFalseExpression(
704 unaryOperator(hasOperatorName("-"),
705 hasUnaryOperand(integerLiteral(equals(5)))))
706 ))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000707}
708
709TEST(ImportExpr, ImportDesignatedInitExpr) {
710 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000711 testImport("void declToImport() {"
712 " struct point { double x; double y; };"
713 " struct point ptarray[10] = "
714 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
715 Lang_C, "", Lang_C, Verifier,
716 functionDecl(
717 hasBody(
718 compoundStmt(
719 has(
720 declStmt(
721 hasSingleDecl(
722 varDecl(
723 hasInitializer(
724 initListExpr(
725 hasSyntacticForm(
726 initListExpr(
727 has(
728 designatedInitExpr(
729 designatorCountIs(2),
730 has(floatLiteral(
731 equals(1.0))),
732 has(integerLiteral(
733 equals(2))))),
734 has(
735 designatedInitExpr(
736 designatorCountIs(2),
737 has(floatLiteral(
738 equals(2.0))),
739 has(integerLiteral(
740 equals(2))))),
741 has(
742 designatedInitExpr(
743 designatorCountIs(2),
744 has(floatLiteral(
745 equals(1.0))),
746 has(integerLiteral(
747 equals(0)))))
748 ))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000749}
750
751
752TEST(ImportExpr, ImportPredefinedExpr) {
753 MatchVerifier<Decl> Verifier;
754 // __func__ expands as StringLiteral("declToImport")
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000755 testImport("void declToImport() { __func__; }",
756 Lang_CXX, "", Lang_CXX, Verifier,
757 functionDecl(
758 hasBody(
759 compoundStmt(
760 has(
761 predefinedExpr(
762 hasType(
763 asString("const char [13]")),
764 has(
765 stringLiteral(
766 hasType(
767 asString("const char [13]"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000768}
769
770TEST(ImportExpr, ImportInitListExpr) {
771 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000772 testImport(
773 "void declToImport() {"
774 " struct point { double x; double y; };"
775 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
776 " [0].x = 1.0 }; }",
777 Lang_CXX, "", Lang_CXX, Verifier,
778 functionDecl(
779 hasBody(
780 compoundStmt(
781 has(
782 declStmt(
783 hasSingleDecl(
784 varDecl(
785 hasInitializer(
786 initListExpr(
787 has(
788 cxxConstructExpr(
789 requiresZeroInitialization())),
790 has(
791 initListExpr(
792 hasType(asString("struct point")),
793 has(floatLiteral(equals(1.0))),
794 has(implicitValueInitExpr(
795 hasType(asString("double")))))),
796 has(
797 initListExpr(
798 hasType(asString("struct point")),
799 has(floatLiteral(equals(2.0))),
800 has(floatLiteral(equals(1.0)))))
801 ))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000802}
803
804
Aleksei Sidorina693b372016-09-28 10:16:56 +0000805const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
806
807TEST(ImportExpr, ImportVAArgExpr) {
808 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000809 testImport("void declToImport(__builtin_va_list list, ...) {"
810 " (void)__builtin_va_arg(list, int); }",
811 Lang_CXX, "", Lang_CXX, Verifier,
812 functionDecl(
813 hasBody(
814 compoundStmt(
815 has(
816 cStyleCastExpr(
817 hasSourceExpression(
818 vaArgExpr())))))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000819}
820
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000821TEST(ImportExpr, CXXTemporaryObjectExpr) {
822 MatchVerifier<Decl> Verifier;
823 testImport("struct C {};"
824 "void declToImport() { C c = C(); }",
825 Lang_CXX, "", Lang_CXX, Verifier,
826 functionDecl(hasBody(compoundStmt(has(
827 declStmt(has(varDecl(has(exprWithCleanups(has(cxxConstructExpr(
828 has(materializeTemporaryExpr(has(implicitCastExpr(
829 has(cxxTemporaryObjectExpr())))))))))))))))));
830}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000831
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000832TEST(ImportType, ImportAtomicType) {
833 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000834 testImport("void declToImport() { typedef _Atomic(int) a_int; }",
835 Lang_CXX11, "", Lang_CXX11, Verifier,
836 functionDecl(
837 hasBody(
838 compoundStmt(
839 has(
840 declStmt(
841 has(
842 typedefDecl(
843 has(atomicType())))))))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000844}
845
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000846TEST(ImportDecl, ImportFunctionTemplateDecl) {
847 MatchVerifier<Decl> Verifier;
848 testImport("template <typename T> void declToImport() { };", Lang_CXX, "",
849 Lang_CXX, Verifier, functionTemplateDecl());
850}
851
852const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
853 cxxDependentScopeMemberExpr;
854
855TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) {
856 MatchVerifier<Decl> Verifier;
857 testImport("template <typename T> struct C { T t; };"
858 "template <typename T> void declToImport() {"
859 " C<T> d;"
860 " d.t;"
861 "}"
862 "void instantiate() { declToImport<int>(); }",
863 Lang_CXX, "", Lang_CXX, Verifier,
864 functionTemplateDecl(has(functionDecl(
865 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
866 testImport("template <typename T> struct C { T t; };"
867 "template <typename T> void declToImport() {"
868 " C<T> d;"
869 " (&d)->t;"
870 "}"
871 "void instantiate() { declToImport<int>(); }",
872 Lang_CXX, "", Lang_CXX, Verifier,
873 functionTemplateDecl(has(functionDecl(
874 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
875}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000876
Gabor Horvath7a91c082017-11-14 11:30:38 +0000877TEST(ImportType, ImportTypeAliasTemplate) {
878 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000879 testImport(
880 "template <int K>"
881 "struct dummy { static const int i = K; };"
882 "template <int K> using dummy2 = dummy<K>;"
883 "int declToImport() { return dummy2<3>::i; }",
884 Lang_CXX11, "", Lang_CXX11, Verifier,
885 functionDecl(
886 hasBody(compoundStmt(
887 has(returnStmt(has(implicitCastExpr(has(declRefExpr()))))))),
888 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
889}
890
891const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
892 varTemplateSpecializationDecl;
893
894TEST(ImportDecl, ImportVarTemplate) {
895 MatchVerifier<Decl> Verifier;
896 testImport(
897 "template <typename T>"
898 "T pi = T(3.1415926535897932385L);"
899 "void declToImport() { pi<int>; }",
900 Lang_CXX11, "", Lang_CXX11, Verifier,
901 functionDecl(
902 hasBody(has(declRefExpr(to(varTemplateSpecializationDecl())))),
903 unless(hasAncestor(translationUnitDecl(has(varDecl(
904 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000905}
906
Gabor Horvath7a91c082017-11-14 11:30:38 +0000907TEST(ImportType, ImportPackExpansion) {
908 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000909 testImport("template <typename... Args>"
910 "struct dummy {"
911 " dummy(Args... args) {}"
912 " static const int i = 4;"
913 "};"
914 "int declToImport() { return dummy<int>::i; }",
915 Lang_CXX11, "", Lang_CXX11, Verifier,
916 functionDecl(
917 hasBody(
918 compoundStmt(
919 has(
920 returnStmt(
921 has(
922 implicitCastExpr(
923 has(
924 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000925}
926
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000927const internal::VariadicDynCastAllOfMatcher<Type,
928 DependentTemplateSpecializationType>
929 dependentTemplateSpecializationType;
930
931TEST(ImportType, ImportDependentTemplateSpecialization) {
932 MatchVerifier<Decl> Verifier;
933 testImport("template<typename T>"
934 "struct A;"
935 "template<typename T>"
936 "struct declToImport {"
937 " typename A<T>::template B<T> a;"
938 "};",
939 Lang_CXX, "", Lang_CXX, Verifier,
940 classTemplateDecl(has(cxxRecordDecl(has(
941 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
942}
943
944const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
945 sizeOfPackExpr;
946
947TEST(ImportExpr, ImportSizeOfPackExpr) {
948 MatchVerifier<Decl> Verifier;
949 testImport("template <typename... Ts>"
950 "void declToImport() {"
951 " const int i = sizeof...(Ts);"
952 "};"
953 "void g() { declToImport<int>(); }",
954 Lang_CXX11, "", Lang_CXX11, Verifier,
955 functionTemplateDecl(has(functionDecl(
956 hasBody(compoundStmt(has(declStmt(has(varDecl(hasInitializer(
957 implicitCastExpr(has(sizeOfPackExpr())))))))))))));
958 testImport(
959 "template <typename... Ts>"
960 "using X = int[sizeof...(Ts)];"
961 "template <typename... Us>"
962 "struct Y {"
963 " X<Us..., int, double, int, Us...> f;"
964 "};"
965 "Y<float, int> declToImport;",
966 Lang_CXX11, "", Lang_CXX11, Verifier,
967 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
968 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
969}
970
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000971/// \brief Matches __builtin_types_compatible_p:
972/// GNU extension to check equivalent types
973/// Given
974/// \code
975/// __builtin_types_compatible_p(int, int)
976/// \endcode
977// will generate TypeTraitExpr <...> 'int'
978const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
979
980TEST(ImportExpr, ImportTypeTraitExpr) {
981 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000982 testImport("void declToImport() { "
983 " __builtin_types_compatible_p(int, int);"
984 "}",
985 Lang_C, "", Lang_C, Verifier,
986 functionDecl(
987 hasBody(
988 compoundStmt(
989 has(
990 typeTraitExpr(hasType(asString("int"))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000991}
992
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000993const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
994
995TEST(ImportExpr, ImportCXXTypeidExpr) {
996 MatchVerifier<Decl> Verifier;
997 testImport(
998 "namespace std { class type_info {}; }"
999 "void declToImport() {"
1000 " int x;"
1001 " auto a = typeid(int); auto b = typeid(x);"
1002 "}",
1003 Lang_CXX11, "", Lang_CXX11, Verifier,
1004 functionDecl(
1005 hasDescendant(varDecl(
1006 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
1007 hasDescendant(varDecl(
1008 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
1009}
1010
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001011TEST(ImportExpr, ImportTypeTraitExprValDep) {
1012 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001013 testImport("template<typename T> struct declToImport {"
1014 " void m() { __is_pod(T); }"
1015 "};"
1016 "void f() { declToImport<int>().m(); }",
1017 Lang_CXX11, "", Lang_CXX11, Verifier,
1018 classTemplateDecl(
1019 has(
1020 cxxRecordDecl(
1021 has(
1022 functionDecl(
1023 hasBody(
1024 compoundStmt(
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001025 has(
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001026 typeTraitExpr(
1027 hasType(booleanType())
1028 ))))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001029}
Gabor Horvath7a91c082017-11-14 11:30:38 +00001030
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001031const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1032 cxxPseudoDestructorExpr;
1033
1034TEST(ImportExpr, ImportCXXPseudoDestructorExpr) {
1035 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001036 testImport("typedef int T;"
1037 "void declToImport(int *p) {"
1038 " T t;"
1039 " p->T::~T();"
1040 "}",
1041 Lang_CXX, "", Lang_CXX, Verifier,
1042 functionDecl(has(compoundStmt(has(
1043 callExpr(has(cxxPseudoDestructorExpr())))))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001044}
1045
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001046TEST(ImportDecl, ImportUsingDecl) {
1047 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001048 testImport("namespace foo { int bar; }"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001049 "void declToImport() { using foo::bar; }",
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001050 Lang_CXX, "", Lang_CXX, Verifier,
1051 functionDecl(
1052 has(
1053 compoundStmt(
1054 has(
1055 declStmt(
1056 has(
1057 usingDecl())))))));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001058}
1059
1060/// \brief Matches shadow declarations introduced into a scope by a
1061/// (resolved) using declaration.
1062///
1063/// Given
1064/// \code
1065/// namespace n { int f; }
1066/// namespace declToImport { using n::f; }
1067/// \endcode
1068/// usingShadowDecl()
1069/// matches \code f \endcode
1070const internal::VariadicDynCastAllOfMatcher<Decl,
1071 UsingShadowDecl> usingShadowDecl;
1072
1073TEST(ImportDecl, ImportUsingShadowDecl) {
1074 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001075 testImport("namespace foo { int bar; }"
1076 "namespace declToImport { using foo::bar; }",
1077 Lang_CXX, "", Lang_CXX, Verifier,
1078 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001079}
1080
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001081TEST(ImportExpr, ImportUnresolvedLookupExpr) {
1082 MatchVerifier<Decl> Verifier;
1083 testImport("template<typename T> int foo();"
1084 "template <typename T> void declToImport() {"
1085 " ::foo<T>;"
1086 " ::template foo<T>;"
1087 "}"
1088 "void instantiate() { declToImport<int>(); }",
1089 Lang_CXX, "", Lang_CXX, Verifier,
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001090 functionTemplateDecl(has(functionDecl(
1091 has(compoundStmt(has(unresolvedLookupExpr())))))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001092}
1093
1094TEST(ImportExpr, ImportCXXUnresolvedConstructExpr) {
1095 MatchVerifier<Decl> Verifier;
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001096 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001097 "template <typename T> void declToImport() {"
1098 " C<T> d;"
1099 " d.t = T();"
1100 "}"
1101 "void instantiate() { declToImport<int>(); }",
1102 Lang_CXX, "", Lang_CXX, Verifier,
1103 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
1104 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001105 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001106 "template <typename T> void declToImport() {"
1107 " C<T> d;"
1108 " (&d)->t = T();"
1109 "}"
1110 "void instantiate() { declToImport<int>(); }",
1111 Lang_CXX, "", Lang_CXX, Verifier,
1112 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
1113 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
1114}
1115
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001116/// Check that function "declToImport()" (which is the templated function
1117/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1118/// Same for class template declarations.
1119TEST(ImportDecl, ImportTemplatedDeclForTemplate) {
1120 MatchVerifier<Decl> Verifier;
1121 testImport("template <typename T> void declToImport() { T a = 1; }"
1122 "void instantiate() { declToImport<int>(); }",
1123 Lang_CXX, "", Lang_CXX, Verifier,
1124 functionTemplateDecl(hasAncestor(translationUnitDecl(
1125 unless(has(functionDecl(hasName("declToImport"))))))));
1126 testImport("template <typename T> struct declToImport { T t; };"
1127 "void instantiate() { declToImport<int>(); }",
1128 Lang_CXX, "", Lang_CXX, Verifier,
1129 classTemplateDecl(hasAncestor(translationUnitDecl(
1130 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
1131}
1132
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001133TEST(ImportExpr, CXXOperatorCallExpr) {
1134 MatchVerifier<Decl> Verifier;
1135 testImport("class declToImport {"
1136 " void f() { *this = declToImport(); }"
1137 "};",
1138 Lang_CXX, "", Lang_CXX, Verifier,
1139 cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt(
1140 has(exprWithCleanups(has(cxxOperatorCallExpr())))))))));
1141}
1142
1143TEST(ImportExpr, DependentSizedArrayType) {
1144 MatchVerifier<Decl> Verifier;
1145 testImport("template<typename T, int Size> class declToImport {"
1146 " T data[Size];"
1147 "};",
1148 Lang_CXX, "", Lang_CXX, Verifier,
1149 classTemplateDecl(has(cxxRecordDecl(
1150 has(fieldDecl(hasType(dependentSizedArrayType())))))));
1151}
1152
Peter Szecsidedda6f2018-03-30 22:03:29 +00001153TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) {
1154 Decl *From, *To;
1155 std::tie(From, To) = getImportedDecl(
1156 R"(
1157 template <typename T> struct X {};
1158
1159 void declToImport(int y, X<int> &x) {}
1160
1161 template <> struct X<int> {
1162 void g() {
1163 X<int> x;
1164 declToImport(0, x);
1165 }
1166 };
1167 )",
1168 Lang_CXX, "", Lang_CXX);
1169
1170 MatchVerifier<Decl> Verifier;
1171 auto Matcher = functionDecl(hasName("declToImport"),
1172 parameterCountIs(2),
1173 hasParameter(0, hasName("y")),
1174 hasParameter(1, hasName("x")),
1175 hasParameter(1, hasType(asString("X<int> &"))));
1176 ASSERT_TRUE(Verifier.match(From, Matcher));
1177 EXPECT_TRUE(Verifier.match(To, Matcher));
1178}
1179
1180TEST_P(ASTImporterTestBase,
1181 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1182 Decl *From, *To;
1183 std::tie(From, To) =
1184 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1185 "void instantiate() { declToImport<int>(); }",
1186 Lang_CXX, "", Lang_CXX);
1187
1188 auto Check = [](Decl *D) -> bool {
1189 auto TU = D->getTranslationUnitDecl();
1190 for (auto Child : TU->decls()) {
1191 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1192 if (FD->getNameAsString() == "declToImport") {
1193 GTEST_NONFATAL_FAILURE_(
1194 "TU should not contain any FunctionDecl with name declToImport");
1195 return false;
1196 }
1197 }
1198 }
1199 return true;
1200 };
1201
1202 ASSERT_TRUE(Check(From));
1203 EXPECT_TRUE(Check(To));
1204}
1205
1206TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1207 Decl *From, *To;
1208 std::tie(From, To) =
1209 getImportedDecl("template <typename T> struct declToImport { T t; };"
1210 "void instantiate() { declToImport<int>(); }",
1211 Lang_CXX, "", Lang_CXX);
1212
1213 auto Check = [](Decl *D) -> bool {
1214 auto TU = D->getTranslationUnitDecl();
1215 for (auto Child : TU->decls()) {
1216 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1217 if (RD->getNameAsString() == "declToImport") {
1218 GTEST_NONFATAL_FAILURE_(
1219 "TU should not contain any CXXRecordDecl with name declToImport");
1220 return false;
1221 }
1222 }
1223 }
1224 return true;
1225 };
1226
1227 ASSERT_TRUE(Check(From));
1228 EXPECT_TRUE(Check(To));
1229}
1230
1231TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1232 Decl *From, *To;
1233 std::tie(From, To) =
1234 getImportedDecl(
1235 "template <typename T> struct X {};"
1236 "template <typename T> using declToImport = X<T>;"
1237 "void instantiate() { declToImport<int> a; }",
1238 Lang_CXX11, "", Lang_CXX11);
1239
1240 auto Check = [](Decl *D) -> bool {
1241 auto TU = D->getTranslationUnitDecl();
1242 for (auto Child : TU->decls()) {
1243 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1244 if (AD->getNameAsString() == "declToImport") {
1245 GTEST_NONFATAL_FAILURE_(
1246 "TU should not contain any TypeAliasDecl with name declToImport");
1247 return false;
1248 }
1249 }
1250 }
1251 return true;
1252 };
1253
1254 ASSERT_TRUE(Check(From));
1255 EXPECT_TRUE(Check(To));
1256}
1257
1258TEST_P(
1259 ASTImporterTestBase,
1260 DISABLED_TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
1261
1262 Decl *From, *To;
1263 std::tie(From, To) = getImportedDecl(
1264 R"(
1265 template<class T>
1266 class Base {};
1267 class declToImport : public Base<declToImport> {};
1268 )",
1269 Lang_CXX, "", Lang_CXX);
1270
1271 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1272 auto Pattern =
1273 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1274 ASSERT_TRUE(
1275 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1276 EXPECT_TRUE(
1277 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1278
1279 // Check that the ClassTemplateSpecializationDecl is the child of the
1280 // ClassTemplateDecl.
1281 Pattern = translationUnitDecl(has(classTemplateDecl(
1282 hasName("Base"), has(classTemplateSpecializationDecl()))));
1283 ASSERT_TRUE(
1284 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1285 EXPECT_TRUE(
1286 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1287}
1288
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001289AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1290 size_t Index = 0;
1291 for (FieldDecl *Field : Node.fields()) {
1292 if (Index == Order.size())
1293 return false;
1294 if (Field->getName() != Order[Index])
1295 return false;
1296 ++Index;
1297 }
1298 return Index == Order.size();
1299}
1300
Peter Szecsidedda6f2018-03-30 22:03:29 +00001301TEST_P(ASTImporterTestBase,
1302 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1303 Decl *From, *To;
1304 std::tie(From, To) = getImportedDecl(
1305 R"(
1306 namespace NS {
1307 template<class T>
1308 class X {};
1309 template class X<int>;
1310 }
1311 )",
1312 Lang_CXX, "", Lang_CXX, "NS");
1313
1314 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1315 // ClassTemplateDecl.
1316 auto Pattern = namespaceDecl(has(classTemplateDecl(
1317 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1318 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1319 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1320
1321 // Check that the ClassTemplateSpecializationDecl is the child of the
1322 // NamespaceDecl.
1323 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1324 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1325 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1326}
1327
1328TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1329 Decl *From, *To;
1330 std::tie(From, To) =
1331 getImportedDecl(
1332 "struct declToImport { int a; int b; };",
1333 Lang_CXX11, "", Lang_CXX11);
1334
1335 MatchVerifier<Decl> Verifier;
1336 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1337 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1338}
1339
1340TEST_P(ASTImporterTestBase,
1341 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1342 Decl *From, *To;
1343 std::tie(From, To) = getImportedDecl(
1344 // The original recursive algorithm of ASTImporter first imports 'c' then
1345 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1346 R"s(
1347 struct declToImport {
1348 int a = c + b;
1349 int b = 1;
1350 int c = 2;
1351 };
1352 )s",
1353 Lang_CXX11, "", Lang_CXX11);
1354
1355 MatchVerifier<Decl> Verifier;
1356 ASSERT_TRUE(
1357 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1358 EXPECT_TRUE(
1359 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1360}
1361
Gabor Martonde8bf262018-05-17 09:46:07 +00001362TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001363 Decl *From, *To;
1364 std::tie(From, To) = getImportedDecl(
1365 R"(
1366 template <typename U>
1367 struct declToImport {
1368 };
1369 )",
1370 Lang_CXX, "", Lang_CXX);
1371
1372 MatchVerifier<Decl> Verifier;
1373 // Match the implicit Decl.
1374 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1375 ASSERT_TRUE(Verifier.match(From, Matcher));
1376 EXPECT_TRUE(Verifier.match(To, Matcher));
1377}
1378
1379TEST_P(
1380 ASTImporterTestBase,
1381 DISABLED_ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
1382 Decl *From, *To;
1383 std::tie(From, To) = getImportedDecl(
1384 R"(
1385 template<class T>
1386 class Base {};
1387 class declToImport : public Base<declToImport> {};
1388 )",
1389 Lang_CXX, "", Lang_CXX);
1390
1391 auto hasImplicitClass = has(cxxRecordDecl());
1392 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1393 hasName("Base"),
1394 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1395 ASSERT_TRUE(
1396 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1397 EXPECT_TRUE(
1398 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1399}
1400
1401TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1402 Decl *From, *To;
1403 std::tie(From, To) =
1404 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1405
1406 MatchVerifier<Decl> Verifier;
1407 auto Matcher = functionDecl();
1408 ASSERT_TRUE(Verifier.match(From, Matcher));
1409 EXPECT_TRUE(Verifier.match(To, Matcher));
1410 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1411}
1412
Gabor Marton2ae9da32018-05-18 15:46:18 +00001413TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001414 Decl *FromTU = getTuDecl(
1415 R"(
1416 struct X {};
1417 void operator<<(int, X);
1418 )",
1419 Lang_CXX);
1420 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1421 const Decl *To = Import(From, Lang_CXX);
1422 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1423}
1424
1425TEST_P(ASTImporterTestBase,
1426 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1427 Decl *From, *To;
1428 std::tie(From, To) = getImportedDecl(
1429 R"(
1430 template<class T>
1431 class Base { int a; };
1432 class declToImport : Base<declToImport> {};
1433 )",
1434 Lang_CXX, "", Lang_CXX);
1435
1436 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1437 hasName("Base"),
1438 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1439 ASSERT_TRUE(
1440 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1441 EXPECT_TRUE(
1442 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1443}
1444
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001445TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1446 {
1447 Decl *FromTU = getTuDecl(
1448 R"(
1449 template <typename T>
1450 struct B;
1451 )",
1452 Lang_CXX, "input0.cc");
1453 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1454 FromTU, classTemplateDecl(hasName("B")));
1455
1456 Import(FromD, Lang_CXX);
1457 }
1458
1459 {
1460 Decl *FromTU = getTuDecl(
1461 R"(
1462 template <typename T>
1463 struct B {
1464 void f();
1465 };
1466 )",
1467 Lang_CXX, "input1.cc");
1468 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1469 FromTU, functionDecl(hasName("f")));
1470 Import(FromD, Lang_CXX);
1471 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1472 FromTU, classTemplateDecl(hasName("B")));
1473 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1474 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1475 }
1476}
1477
Gabor Marton9581c332018-05-23 13:53:36 +00001478TEST_P(ASTImporterTestBase,
1479 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1480 Decl *ToTU = getToTuDecl(
1481 R"(
1482 template <typename T>
1483 struct B {
1484 void f();
1485 };
1486
1487 template <typename T>
1488 struct B;
1489 )",
1490 Lang_CXX);
1491 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1492 [](const ClassTemplateDecl *T) {
1493 return T->isThisDeclarationADefinition();
1494 })
1495 .match(ToTU, classTemplateDecl()));
1496
1497 Decl *FromTU = getTuDecl(
1498 R"(
1499 template <typename T>
1500 struct B {
1501 void f();
1502 };
1503 )",
1504 Lang_CXX, "input1.cc");
1505 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1506 FromTU, classTemplateDecl(hasName("B")));
1507
1508 Import(FromD, Lang_CXX);
1509
1510 // We should have only one definition.
1511 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1512 [](const ClassTemplateDecl *T) {
1513 return T->isThisDeclarationADefinition();
1514 })
1515 .match(ToTU, classTemplateDecl()));
1516}
1517
1518TEST_P(ASTImporterTestBase,
1519 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1520 Decl *ToTU = getToTuDecl(
1521 R"(
1522 struct B {
1523 void f();
1524 };
1525
1526 struct B;
1527 )",
1528 Lang_CXX);
1529 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1530 ToTU, cxxRecordDecl(hasParent(translationUnitDecl()))));
1531
1532 Decl *FromTU = getTuDecl(
1533 R"(
1534 struct B {
1535 void f();
1536 };
1537 )",
1538 Lang_CXX, "input1.cc");
1539 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1540 FromTU, cxxRecordDecl(hasName("B")));
1541
1542 Import(FromD, Lang_CXX);
1543
1544 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1545 ToTU, cxxRecordDecl(hasParent(translationUnitDecl()))));
1546}
1547
1548TEST_P(
1549 ASTImporterTestBase,
1550 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1551{
1552 Decl *ToTU = getToTuDecl(
1553 R"(
1554 template <typename T>
1555 struct B;
1556
1557 template <>
1558 struct B<int> {};
1559
1560 template <>
1561 struct B<int>;
1562 )",
1563 Lang_CXX);
1564 // We should have only one definition.
1565 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1566 [](const ClassTemplateSpecializationDecl *T) {
1567 return T->isThisDeclarationADefinition();
1568 })
1569 .match(ToTU, classTemplateSpecializationDecl()));
1570
1571 Decl *FromTU = getTuDecl(
1572 R"(
1573 template <typename T>
1574 struct B;
1575
1576 template <>
1577 struct B<int> {};
1578 )",
1579 Lang_CXX, "input1.cc");
1580 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1581 FromTU, classTemplateSpecializationDecl(hasName("B")));
1582
1583 Import(FromD, Lang_CXX);
1584
1585 // We should have only one definition.
1586 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1587 [](const ClassTemplateSpecializationDecl *T) {
1588 return T->isThisDeclarationADefinition();
1589 })
1590 .match(ToTU, classTemplateSpecializationDecl()));
1591}
1592
Peter Szecsidedda6f2018-03-30 22:03:29 +00001593INSTANTIATE_TEST_CASE_P(
1594 ParameterizedTests, ASTImporterTestBase,
1595 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1596
1597struct ImportFunctions : ASTImporterTestBase {};
1598
1599TEST_P(ImportFunctions,
1600 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
1601 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
1602 auto Pattern = functionDecl(hasName("f"));
1603 FunctionDecl *FromD =
1604 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1605
1606 Decl *ImportedD = Import(FromD, Lang_CXX);
1607 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1608
1609 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1610 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1611}
1612
1613TEST_P(ImportFunctions,
1614 PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) {
1615 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1616 auto Pattern = functionDecl(hasName("f"));
1617 FunctionDecl *FromD = // Prototype
1618 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1619
1620 Decl *ImportedD = Import(FromD, Lang_CXX);
1621 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1622
1623 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1624 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1625}
1626
1627TEST_P(ImportFunctions,
1628 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1629 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1630 auto Pattern = functionDecl(hasName("f"));
1631 FunctionDecl *FromD = // Definition
1632 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1633
1634 Decl *ImportedD = Import(FromD, Lang_CXX);
1635 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1636
1637 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1638 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1639}
1640
1641TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1642 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1643 auto Pattern = functionDecl(hasName("f"));
1644 FunctionDecl *FromD =
1645 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1646
1647 Decl *ImportedD = Import(FromD, Lang_CXX);
1648 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1649
1650 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1651 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1652}
1653
1654TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) {
1655 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1656 auto Pattern = functionDecl(hasName("f"));
1657 FunctionDecl *PrototypeFD =
1658 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1659
1660 Decl *ImportedD = Import(PrototypeFD, Lang_CXX);
1661 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1662
1663 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1664 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1665}
1666
1667TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1668 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1669 auto Pattern = functionDecl(hasName("f"));
1670 FunctionDecl *DefinitionFD =
1671 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1672
1673 Decl *ImportedD = Import(DefinitionFD, Lang_CXX);
1674 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1675
1676 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1677 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1678}
1679
1680TEST_P(ImportFunctions, ImportPrototypes) {
1681 auto Pattern = functionDecl(hasName("f"));
1682
1683 Decl *ImportedD;
1684 {
1685 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1686 FunctionDecl *FromD =
1687 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1688
1689 ImportedD = Import(FromD, Lang_CXX);
1690 }
1691 Decl *ImportedD1;
1692 {
1693 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1694 FunctionDecl *FromD =
1695 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1696 ImportedD1 = Import(FromD, Lang_CXX);
1697 }
1698
1699 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1700 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1701 EXPECT_EQ(ImportedD, ImportedD1);
1702 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1703}
1704
1705TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1706 auto Pattern = functionDecl(hasName("f"));
1707
1708 Decl *ImportedD;
1709 {
1710 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1711 FunctionDecl *FromD =
1712 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1713
1714 ImportedD = Import(FromD, Lang_CXX);
1715 }
1716 Decl *ImportedD1;
1717 {
1718 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1719 FunctionDecl *FromD =
1720 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1721 ImportedD1 = Import(FromD, Lang_CXX);
1722 }
1723
1724 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1725 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1726 EXPECT_EQ(ImportedD, ImportedD1);
1727 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1728}
1729
1730TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1731 auto Pattern = functionDecl(hasName("f"));
1732
1733 {
1734 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1735 FunctionDecl *FromD =
1736 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1737
1738 Import(FromD, Lang_CXX);
1739 }
1740 {
1741 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1742 FunctionDecl *FromD =
1743 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1744 Import(FromD, Lang_CXX);
1745 }
1746
1747 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1748 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1749 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1750 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1751 FunctionDecl *DefinitionD =
1752 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1753 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1754 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1755}
1756
1757TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) {
1758 auto Pattern = functionDecl(hasName("f"));
1759
1760 {
1761 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1762 FunctionDecl *FromD =
1763 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1764
1765 Import(FromD, Lang_CXX);
1766 }
1767 {
1768 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
1769 FunctionDecl *FromD =
1770 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1771 Import(FromD, Lang_CXX);
1772 }
1773
1774 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1775 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1776 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1777 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1778 FunctionDecl *DefinitionD =
1779 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1780 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1781 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1782}
1783
1784TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1785 auto Code =
1786 R"(
1787 struct B { virtual void f(); };
1788 void B::f() {}
1789 struct D : B { void f(); };
1790 )";
1791 auto Pattern =
1792 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1793 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1794 CXXMethodDecl *Proto =
1795 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1796
1797 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1798 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1799 EXPECT_EQ(To->size_overridden_methods(), 1u);
1800}
1801
1802TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1803 auto Code =
1804 R"(
1805 struct B { virtual void f(); };
1806 void B::f() {}
1807 )";
1808 auto Pattern =
1809 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1810 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1811 CXXMethodDecl *Proto =
1812 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1813 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1814
1815 ASSERT_TRUE(Proto->isVirtual());
1816 ASSERT_TRUE(Def->isVirtual());
1817 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1818 EXPECT_TRUE(To->isVirtual());
1819}
1820
1821INSTANTIATE_TEST_CASE_P(
1822 ParameterizedTests, ImportFunctions,
1823 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1824
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001825AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
1826 InnerMatcher) {
1827 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
1828 return InnerMatcher.matches(*Typedef, Finder, Builder);
1829 return false;
1830}
1831
1832TEST(ImportDecl, ImportEnumSequential) {
1833 CodeFiles Samples{{"main.c",
1834 {"void foo();"
1835 "void moo();"
1836 "int main() { foo(); moo(); }",
1837 Lang_C}},
1838
1839 {"foo.c",
1840 {"typedef enum { THING_VALUE } thing_t;"
1841 "void conflict(thing_t type);"
1842 "void foo() { (void)THING_VALUE; }"
1843 "void conflict(thing_t type) {}",
1844 Lang_C}},
1845
1846 {"moo.c",
1847 {"typedef enum { THING_VALUE } thing_t;"
1848 "void conflict(thing_t type);"
1849 "void moo() { conflict(THING_VALUE); }",
1850 Lang_C}}};
1851
1852 auto VerificationMatcher =
1853 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
1854 hasTypedefForAnonDecl(hasName("thing_t")));
1855
1856 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
1857 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
1858
1859 testImportSequence(
1860 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
1861 // Just check that there is only one enum decl in the result AST.
1862 "main.c", enumDecl(), VerificationMatcher);
1863
1864 // For different import order, result should be the same.
1865 testImportSequence(
1866 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
1867 // Check that there is only one enum decl in the result AST.
1868 "main.c", enumDecl(), VerificationMatcher);
1869}
1870
Peter Szecsice7f3182018-05-07 12:08:27 +00001871const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
1872 dependentScopeDeclRefExpr;
1873
1874TEST(ImportExpr, DependentScopeDeclRefExpr) {
1875 MatchVerifier<Decl> Verifier;
1876 testImport("template <typename T> struct S { static T foo; };"
1877 "template <typename T> void declToImport() {"
1878 " (void) S<T>::foo;"
1879 "}"
1880 "void instantiate() { declToImport<int>(); }",
1881 Lang_CXX11, "", Lang_CXX11, Verifier,
1882 functionTemplateDecl(has(functionDecl(has(compoundStmt(
1883 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
1884
1885 testImport("template <typename T> struct S {"
1886 "template<typename S> static void foo(){};"
1887 "};"
1888 "template <typename T> void declToImport() {"
1889 " S<T>::template foo<T>();"
1890 "}"
1891 "void instantiate() { declToImport<int>(); }",
1892 Lang_CXX11, "", Lang_CXX11, Verifier,
1893 functionTemplateDecl(has(functionDecl(has(compoundStmt(
1894 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
1895}
1896
1897const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
1898 dependentNameType;
1899
1900TEST(ImportExpr, DependentNameType) {
1901 MatchVerifier<Decl> Verifier;
1902 testImport("template <typename T> struct declToImport {"
1903 " typedef typename T::type dependent_name;"
1904 "};",
1905 Lang_CXX11, "", Lang_CXX11, Verifier,
1906 classTemplateDecl(has(
1907 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
1908}
1909
1910const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
1911 unresolvedMemberExpr;
1912
1913TEST(ImportExpr, UnresolvedMemberExpr) {
1914 MatchVerifier<Decl> Verifier;
1915 testImport("struct S { template <typename T> void mem(); };"
1916 "template <typename U> void declToImport() {"
1917 " S s;"
1918 " s.mem<U>();"
1919 "}"
1920 "void instantiate() { declToImport<int>(); }",
1921 Lang_CXX11, "", Lang_CXX11, Verifier,
1922 functionTemplateDecl(has(functionDecl(has(
1923 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
1924}
1925
Gabor Marton61d862a2018-05-18 09:08:47 +00001926struct DeclContextTest : ASTImporterTestBase {};
1927
1928TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
1929 Decl *TU = getTuDecl(
1930 R"(
1931 namespace NS {
1932
1933 template <typename T>
1934 struct S {};
1935 template struct S<int>;
1936
1937 inline namespace INS {
1938 template <typename T>
1939 struct S {};
1940 template struct S<int>;
1941 }
1942
1943 }
1944 )", Lang_CXX11, "input0.cc");
1945 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
1946 TU, namespaceDecl());
1947 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1948 TU, classTemplateSpecializationDecl());
1949 ASSERT_TRUE(NS->containsDecl(Spec));
1950
1951 NS->removeDecl(Spec);
1952 EXPECT_FALSE(NS->containsDecl(Spec));
1953}
1954
1955INSTANTIATE_TEST_CASE_P(
1956 ParameterizedTests, DeclContextTest,
1957 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1958
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001959} // end namespace ast_matchers
1960} // end namespace clang