blob: 7cac2b5703662a2e95a55d54cc3cd526a9e7d483 [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Tests for the correct import of AST nodes from one AST context to another.
10//
11//===----------------------------------------------------------------------===//
12
Gabor Marton458d1452019-02-14 13:07:03 +000013// Define this to have ::testing::Combine available.
14// FIXME: Better solution for this?
15#define GTEST_HAS_COMBINE 1
16
Gabor Marton7df342a2018-12-17 12:42:12 +000017#include "clang/AST/ASTImporter.h"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +000018#include "MatchVerifier.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000019#include "clang/AST/ASTContext.h"
Gabor Marton7df342a2018-12-17 12:42:12 +000020#include "clang/AST/DeclContextInternals.h"
Gabor Marton54058b52018-12-17 13:53:12 +000021#include "clang/AST/ASTImporter.h"
22#include "clang/AST/ASTImporterLookupTable.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000023#include "clang/ASTMatchers/ASTMatchFinder.h"
24#include "clang/ASTMatchers/ASTMatchers.h"
25#include "clang/Tooling/Tooling.h"
Peter Szecsidedda6f2018-03-30 22:03:29 +000026
27#include "DeclMatcher.h"
Gabor Marton1f667532018-05-24 08:41:07 +000028#include "Language.h"
Gabor Marton5254e642018-06-27 13:32:50 +000029#include "gmock/gmock.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000030#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000031
32namespace clang {
33namespace ast_matchers {
34
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000035using internal::Matcher;
36using internal::BindableMatcher;
37using llvm::StringMap;
38
Peter Szecsidedda6f2018-03-30 22:03:29 +000039// Creates a virtual file and assigns that to the context of given AST. If the
40// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000041static void
42createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
43 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000044 assert(ToAST);
45 ASTContext &ToCtx = ToAST->getASTContext();
Jonas Devliegherefc514902018-10-10 13:27:25 +000046 auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +000047 &ToCtx.getSourceManager().getFileManager().getVirtualFileSystem());
Jonas Devliegherefc514902018-10-10 13:27:25 +000048 auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
49 OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000050 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000051}
52
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000053static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
54 StringRef Code) {
55 return createVirtualFileIfNeeded(ToAST, FileName,
56 llvm::MemoryBuffer::getMemBuffer(Code));
57}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000058
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000059const StringRef DeclToImportID = "declToImport";
60const StringRef DeclToVerifyID = "declToVerify";
61
Gabor Marton19f4f392018-06-25 13:04:37 +000062// Common base for the different families of ASTImporter tests that are
63// parameterized on the compiler options which may result a different AST. E.g.
64// -fms-compatibility or -fdelayed-template-parsing.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000065class CompilerOptionSpecificTest : public ::testing::Test {
66protected:
67 // Return the extra arguments appended to runtime options at compilation.
68 virtual ArgVector getExtraArgs() const { return ArgVector(); }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000069
Gabor Marton19f4f392018-06-25 13:04:37 +000070 // Returns the argument vector used for a specific language option, this set
71 // can be tweaked by the test parameters.
72 ArgVector getArgVectorForLanguage(Language Lang) const {
73 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
Gabor Marton0b57ccb2019-02-07 16:52:48 +000074 ArgVector ExtraArgs = getExtraArgs();
Gabor Marton19f4f392018-06-25 13:04:37 +000075 for (const auto &Arg : ExtraArgs) {
76 Args.push_back(Arg);
77 }
78 return Args;
79 }
Gabor Marton19f4f392018-06-25 13:04:37 +000080};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000081
Gabor Marton0b57ccb2019-02-07 16:52:48 +000082auto DefaultTestValuesForRunOptions = ::testing::Values(
83 ArgVector(), ArgVector{"-fdelayed-template-parsing"},
84 ArgVector{"-fms-compatibility"},
85 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
86
Gabor Marton19f4f392018-06-25 13:04:37 +000087// Base class for those tests which use the family of `testImport` functions.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000088class TestImportBase : public CompilerOptionSpecificTest,
89 public ::testing::WithParamInterface<ArgVector> {
Adam Baloghe4192a82018-06-15 06:45:39 +000090
Gabor Marton19f4f392018-06-25 13:04:37 +000091 template <typename NodeType>
Balazs Keria1f6b102019-04-08 13:59:15 +000092 llvm::Expected<NodeType> importNode(ASTUnit *From, ASTUnit *To,
93 ASTImporter &Importer, NodeType Node) {
Gabor Marton19f4f392018-06-25 13:04:37 +000094 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000095
Gabor Marton19f4f392018-06-25 13:04:37 +000096 // Add 'From' file to virtual file system so importer can 'find' it
97 // while importing SourceLocations. It is safe to add same file multiple
98 // times - it just isn't replaced.
99 StringRef FromFileName = From->getMainFileName();
100 createVirtualFileIfNeeded(To, FromFileName,
101 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000102
Balazs Keria1f6b102019-04-08 13:59:15 +0000103 auto Imported = Importer.Import_New(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000104
Balazs Keria1f6b102019-04-08 13:59:15 +0000105 if (Imported) {
106 // This should dump source locations and assert if some source locations
107 // were not imported.
108 SmallString<1024> ImportChecker;
109 llvm::raw_svector_ostream ToNothing(ImportChecker);
110 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000111
Balazs Keria1f6b102019-04-08 13:59:15 +0000112 // This traverses the AST to catch certain bugs like poorly or not
113 // implemented subtrees.
114 (*Imported)->dump(ToNothing);
115 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000116
Gabor Marton19f4f392018-06-25 13:04:37 +0000117 return Imported;
118 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000119
Gabor Marton19f4f392018-06-25 13:04:37 +0000120 template <typename NodeType>
121 testing::AssertionResult
122 testImport(const std::string &FromCode, const ArgVector &FromArgs,
123 const std::string &ToCode, const ArgVector &ToArgs,
124 MatchVerifier<NodeType> &Verifier,
125 const BindableMatcher<NodeType> &SearchMatcher,
126 const BindableMatcher<NodeType> &VerificationMatcher) {
127 const char *const InputFileName = "input.cc";
128 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000129
Gabor Marton19f4f392018-06-25 13:04:37 +0000130 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
131 FromCode, FromArgs, InputFileName),
132 ToAST = tooling::buildASTFromCodeWithArgs(
133 ToCode, ToArgs, OutputFileName);
134
135 ASTContext &FromCtx = FromAST->getASTContext(),
136 &ToCtx = ToAST->getASTContext();
137
138 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
139 FromAST->getFileManager(), false);
140
141 auto FoundNodes = match(SearchMatcher, FromCtx);
142 if (FoundNodes.size() != 1)
143 return testing::AssertionFailure()
144 << "Multiple potential nodes were found!";
145
146 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
147 if (!ToImport)
148 return testing::AssertionFailure() << "Node type mismatch!";
149
150 // Sanity check: the node being imported should match in the same way as
151 // the result node.
152 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
153 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
154
155 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +0000156 if (!Imported) {
157 std::string ErrorText;
158 handleAllErrors(
159 Imported.takeError(),
160 [&ErrorText](const ImportError &Err) { ErrorText = Err.message(); });
161 return testing::AssertionFailure()
162 << "Import failed, error: \"" << ErrorText << "\"!";
163 }
Gabor Marton19f4f392018-06-25 13:04:37 +0000164
Balazs Keria1f6b102019-04-08 13:59:15 +0000165 return Verifier.match(*Imported, WrapperMatcher);
Gabor Marton19f4f392018-06-25 13:04:37 +0000166 }
167
168 template <typename NodeType>
169 testing::AssertionResult
170 testImport(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
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000181protected:
182 ArgVector getExtraArgs() const override { return GetParam(); }
183
Gabor Marton19f4f392018-06-25 13:04:37 +0000184public:
185
186 /// Test how AST node named "declToImport" located in the translation unit
187 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
188 /// The verification is done by running AMatcher over the imported node.
189 template <typename NodeType, typename MatcherType>
190 void testImport(const std::string &FromCode, Language FromLang,
191 const std::string &ToCode, Language ToLang,
192 MatchVerifier<NodeType> &Verifier,
193 const MatcherType &AMatcher) {
194 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
195 ToArgs = getArgVectorForLanguage(ToLang);
196 EXPECT_TRUE(
197 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
198 }
199
200 struct ImportAction {
201 StringRef FromFilename;
202 StringRef ToFilename;
203 // FIXME: Generalize this to support other node kinds.
204 BindableMatcher<Decl> ImportPredicate;
205
206 ImportAction(StringRef FromFilename, StringRef ToFilename,
207 DeclarationMatcher ImportPredicate)
208 : FromFilename(FromFilename), ToFilename(ToFilename),
209 ImportPredicate(ImportPredicate) {}
210
211 ImportAction(StringRef FromFilename, StringRef ToFilename,
212 const std::string &DeclName)
213 : FromFilename(FromFilename), ToFilename(ToFilename),
214 ImportPredicate(namedDecl(hasName(DeclName))) {}
215 };
216
217 using SingleASTUnit = std::unique_ptr<ASTUnit>;
218 using AllASTUnits = StringMap<SingleASTUnit>;
219
220 struct CodeEntry {
221 std::string CodeSample;
222 Language Lang;
223 };
224
225 using CodeFiles = StringMap<CodeEntry>;
226
227 /// Builds an ASTUnit for one potential compile options set.
228 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
229 ArgVector Args = getArgVectorForLanguage(CE.Lang);
230 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
231 EXPECT_TRUE(AST.get());
232 return AST;
233 }
234
235 /// Test an arbitrary sequence of imports for a set of given in-memory files.
236 /// The verification is done by running VerificationMatcher against a
237 /// specified AST node inside of one of given files.
238 /// \param CodeSamples Map whose key is the file name and the value is the
239 /// file content.
240 /// \param ImportActions Sequence of imports. Each import in sequence
241 /// specifies "from file" and "to file" and a matcher that is used for
242 /// searching a declaration for import in "from file".
243 /// \param FileForFinalCheck Name of virtual file for which the final check is
244 /// applied.
245 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
246 /// FileForFinalCheck for which the verification will be done.
247 /// \param VerificationMatcher Matcher that will be used for verification
248 /// after all imports in sequence are done.
249 void testImportSequence(const CodeFiles &CodeSamples,
250 const std::vector<ImportAction> &ImportActions,
251 StringRef FileForFinalCheck,
252 BindableMatcher<Decl> FinalSelectPredicate,
253 BindableMatcher<Decl> VerificationMatcher) {
254 AllASTUnits AllASTs;
255 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
256 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
257
258 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
259 if (!AllASTs.count(Filename)) {
260 auto Found = CodeSamples.find(Filename);
261 assert(Found != CodeSamples.end() && "Wrong file for import!");
262 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
263 }
264 };
265
266 for (const ImportAction &Action : ImportActions) {
267 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
268 GenASTsIfNeeded(FromFile);
269 GenASTsIfNeeded(ToFile);
270
271 ASTUnit *From = AllASTs[FromFile].get();
272 ASTUnit *To = AllASTs[ToFile].get();
273
274 // Create a new importer if needed.
275 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
276 if (!ImporterRef)
277 ImporterRef.reset(new ASTImporter(
278 To->getASTContext(), To->getFileManager(), From->getASTContext(),
279 From->getFileManager(), false));
280
281 // Find the declaration and import it.
282 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
283 From->getASTContext());
284 EXPECT_TRUE(FoundDecl.size() == 1);
285 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
286 auto Imported = importNode(From, To, *ImporterRef, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +0000287 EXPECT_TRUE(static_cast<bool>(Imported));
288 if (!Imported)
289 llvm::consumeError(Imported.takeError());
Gabor Marton19f4f392018-06-25 13:04:37 +0000290 }
291
292 // Find the declaration and import it.
293 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
294 AllASTs[FileForFinalCheck]->getASTContext());
295 EXPECT_TRUE(FoundDecl.size() == 1);
296 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
297 MatchVerifier<Decl> Verifier;
298 EXPECT_TRUE(
299 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
300 }
301};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000302
Gabor Martonf086fa82018-07-17 12:06:36 +0000303template <typename T> RecordDecl *getRecordDecl(T *D) {
304 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
305 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000306}
Gabor Martonf086fa82018-07-17 12:06:36 +0000307
Peter Szecsidedda6f2018-03-30 22:03:29 +0000308// This class provides generic methods to write tests which can check internal
Balazs Keri21f938c2018-07-02 14:14:07 +0000309// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000310// this fixture makes it possible to import from several "From" contexts.
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000311class ASTImporterTestBase : public CompilerOptionSpecificTest {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000312
313 const char *const InputFileName = "input.cc";
314 const char *const OutputFileName = "output.cc";
315
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000316public:
317 /// Allocates an ASTImporter (or one of its subclasses).
318 typedef std::function<ASTImporter *(ASTContext &, FileManager &, ASTContext &,
319 FileManager &, bool,
320 ASTImporterLookupTable *)>
321 ImporterConstructor;
322
323 // The lambda that constructs the ASTImporter we use in this test.
324 ImporterConstructor Creator;
325
326private:
Peter Szecsidedda6f2018-03-30 22:03:29 +0000327 // Buffer for the To context, must live in the test scope.
328 std::string ToCode;
329
Gabor Marton26f72a92018-07-12 09:42:05 +0000330 // Represents a "From" translation unit and holds an importer object which we
331 // use to import from this translation unit.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000332 struct TU {
333 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000334 std::string Code;
335 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000336 std::unique_ptr<ASTUnit> Unit;
337 TranslationUnitDecl *TUDecl = nullptr;
Gabor Marton26f72a92018-07-12 09:42:05 +0000338 std::unique_ptr<ASTImporter> Importer;
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000339 ImporterConstructor Creator;
340 TU(StringRef Code, StringRef FileName, ArgVector Args,
341 ImporterConstructor C = ImporterConstructor())
Peter Szecsidedda6f2018-03-30 22:03:29 +0000342 : Code(Code), FileName(FileName),
343 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
344 this->FileName)),
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000345 TUDecl(Unit->getASTContext().getTranslationUnitDecl()), Creator(C) {
Adam Baloghe4192a82018-06-15 06:45:39 +0000346 Unit->enableSourceFileDiagnostics();
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000347
348 // If the test doesn't need a specific ASTImporter, we just create a
349 // normal ASTImporter with it.
350 if (!Creator)
351 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
352 ASTContext &FromContext, FileManager &FromFileManager,
353 bool MinimalImport, ASTImporterLookupTable *LookupTable) {
354 return new ASTImporter(ToContext, ToFileManager, FromContext,
355 FromFileManager, MinimalImport, LookupTable);
356 };
Adam Baloghe4192a82018-06-15 06:45:39 +0000357 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000358
Gabor Marton54058b52018-12-17 13:53:12 +0000359 void lazyInitImporter(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST) {
Gabor Marton26f72a92018-07-12 09:42:05 +0000360 assert(ToAST);
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000361 if (!Importer)
362 Importer.reset(Creator(ToAST->getASTContext(), ToAST->getFileManager(),
363 Unit->getASTContext(), Unit->getFileManager(),
364 false, &LookupTable));
Gabor Marton6e1510c2018-07-12 11:50:21 +0000365 assert(&ToAST->getASTContext() == &Importer->getToContext());
366 createVirtualFileIfNeeded(ToAST, FileName, Code);
367 }
368
Gabor Marton54058b52018-12-17 13:53:12 +0000369 Decl *import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
370 Decl *FromDecl) {
371 lazyInitImporter(LookupTable, ToAST);
Balazs Keria1f6b102019-04-08 13:59:15 +0000372 if (auto ImportedOrErr = Importer->Import_New(FromDecl))
373 return *ImportedOrErr;
374 else {
375 llvm::consumeError(ImportedOrErr.takeError());
376 return nullptr;
377 }
Gabor Marton54058b52018-12-17 13:53:12 +0000378 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000379
Gabor Marton54058b52018-12-17 13:53:12 +0000380 QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
381 QualType FromType) {
382 lazyInitImporter(LookupTable, ToAST);
Balazs Keria1f6b102019-04-08 13:59:15 +0000383 if (auto ImportedOrErr = Importer->Import_New(FromType))
384 return *ImportedOrErr;
385 else {
386 llvm::consumeError(ImportedOrErr.takeError());
387 return QualType{};
388 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000389 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000390 };
391
392 // We may have several From contexts and related translation units. In each
393 // AST, the buffers for the source are handled via references and are set
394 // during the creation of the AST. These references must point to a valid
395 // buffer until the AST is alive. Thus, we must use a list in order to avoid
396 // moving of the stored objects because that would mean breaking the
397 // references in the AST. By using a vector a move could happen when the
398 // vector is expanding, with the list we won't have these issues.
399 std::list<TU> FromTUs;
400
Gabor Marton54058b52018-12-17 13:53:12 +0000401 // Initialize the lookup table if not initialized already.
402 void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
403 assert(ToTU);
404 if (!LookupTablePtr)
405 LookupTablePtr = llvm::make_unique<ASTImporterLookupTable>(*ToTU);
406 }
407
408 void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000409 if (ToAST)
410 return;
411 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton54058b52018-12-17 13:53:12 +0000412 // Source code must be a valid live buffer through the tests lifetime.
413 ToCode = ToSrcCode;
Gabor Marton6e1510c2018-07-12 11:50:21 +0000414 // Build the AST from an empty file.
Gabor Marton54058b52018-12-17 13:53:12 +0000415 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000416 ToAST->enableSourceFileDiagnostics();
Gabor Marton54058b52018-12-17 13:53:12 +0000417 lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
Gabor Marton6e1510c2018-07-12 11:50:21 +0000418 }
419
420 TU *findFromTU(Decl *From) {
421 // Create a virtual file in the To Ctx which corresponds to the file from
422 // which we want to import the `From` Decl. Without this source locations
423 // will be invalid in the ToCtx.
Fangrui Song75e74e02019-03-31 08:48:19 +0000424 auto It = llvm::find_if(FromTUs, [From](const TU &E) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000425 return E.TUDecl == From->getTranslationUnitDecl();
426 });
427 assert(It != FromTUs.end());
428 return &*It;
429 }
430
Gabor Marton54058b52018-12-17 13:53:12 +0000431protected:
432
433 std::unique_ptr<ASTImporterLookupTable> LookupTablePtr;
434
Peter Szecsidedda6f2018-03-30 22:03:29 +0000435public:
436 // We may have several From context but only one To context.
437 std::unique_ptr<ASTUnit> ToAST;
438
Peter Szecsidedda6f2018-03-30 22:03:29 +0000439 // Creates an AST both for the From and To source code and imports the Decl
440 // of the identifier into the To context.
441 // Must not be called more than once within the same test.
442 std::tuple<Decl *, Decl *>
443 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
444 Language ToLang, StringRef Identifier = DeclToImportID) {
445 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
446 ToArgs = getArgVectorForLanguage(ToLang);
447
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000448 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs, Creator);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000449 TU &FromTU = FromTUs.back();
450
Peter Szecsidedda6f2018-03-30 22:03:29 +0000451 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000452 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000453
Gabor Marton26f72a92018-07-12 09:42:05 +0000454 ASTContext &FromCtx = FromTU.Unit->getASTContext();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000455
Peter Szecsidedda6f2018-03-30 22:03:29 +0000456 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
457 assert(ImportedII && "Declaration with the given identifier "
458 "should be specified in test!");
459 DeclarationName ImportDeclName(ImportedII);
Gabor Marton54058b52018-12-17 13:53:12 +0000460 SmallVector<NamedDecl *, 1> FoundDecls;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000461 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
462 FoundDecls);
463
464 assert(FoundDecls.size() == 1);
465
Gabor Marton54058b52018-12-17 13:53:12 +0000466 Decl *Imported =
467 FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
Gabor Marton26f72a92018-07-12 09:42:05 +0000468
Peter Szecsidedda6f2018-03-30 22:03:29 +0000469 assert(Imported);
470 return std::make_tuple(*FoundDecls.begin(), Imported);
471 }
472
Gabor Marton9581c332018-05-23 13:53:36 +0000473 // Creates a TU decl for the given source code which can be used as a From
474 // context. May be called several times in a given test (with different file
475 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000476 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
477 StringRef FileName = "input.cc") {
Fangrui Song75e74e02019-03-31 08:48:19 +0000478 assert(llvm::find_if(FromTUs, [FileName](const TU &E) {
479 return E.FileName == FileName;
480 }) == FromTUs.end());
Peter Szecsidedda6f2018-03-30 22:03:29 +0000481
482 ArgVector Args = getArgVectorForLanguage(Lang);
483 FromTUs.emplace_back(SrcCode, FileName, Args);
484 TU &Tu = FromTUs.back();
485
486 return Tu.TUDecl;
487 }
488
Gabor Marton9581c332018-05-23 13:53:36 +0000489 // Creates the To context with the given source code and returns the TU decl.
490 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
491 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton9581c332018-05-23 13:53:36 +0000492 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000493 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Gabor Marton9581c332018-05-23 13:53:36 +0000494 return ToAST->getASTContext().getTranslationUnitDecl();
495 }
496
Peter Szecsidedda6f2018-03-30 22:03:29 +0000497 // Import the given Decl into the ToCtx.
498 // May be called several times in a given test.
499 // The different instances of the param From may have different ASTContext.
500 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000501 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000502 TU *FromTU = findFromTU(From);
Gabor Marton54058b52018-12-17 13:53:12 +0000503 assert(LookupTablePtr);
504 return FromTU->import(*LookupTablePtr, ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000505 }
506
Gabor Marton458d1452019-02-14 13:07:03 +0000507 template <class DeclT> DeclT *Import(DeclT *From, Language Lang) {
508 return cast_or_null<DeclT>(Import(cast<Decl>(From), Lang));
509 }
510
Gabor Marton6e1510c2018-07-12 11:50:21 +0000511 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000512 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000513 TU *FromTU = findFromTU(TUDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000514 assert(LookupTablePtr);
515 return FromTU->import(*LookupTablePtr, ToAST.get(), FromType);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000516 }
517
Peter Szecsidedda6f2018-03-30 22:03:29 +0000518 ~ASTImporterTestBase() {
519 if (!::testing::Test::HasFailure()) return;
520
521 for (auto &Tu : FromTUs) {
522 assert(Tu.Unit);
523 llvm::errs() << "FromAST:\n";
524 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
525 llvm::errs() << "\n";
526 }
527 if (ToAST) {
528 llvm::errs() << "ToAST:\n";
529 ToAST->getASTContext().getTranslationUnitDecl()->dump();
530 }
531 }
532};
533
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000534class ASTImporterOptionSpecificTestBase
535 : public ASTImporterTestBase,
536 public ::testing::WithParamInterface<ArgVector> {
537protected:
538 ArgVector getExtraArgs() const override { return GetParam(); }
539};
540
Gabor Marton19f4f392018-06-25 13:04:37 +0000541struct ImportExpr : TestImportBase {};
542struct ImportType : TestImportBase {};
543struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000544
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000545struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +0000546
547TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
548 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
549 auto Pattern = functionDecl(hasName("f"));
550 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
551
552 auto Redecls = getCanonicalForwardRedeclChain(D0);
553 ASSERT_EQ(Redecls.size(), 1u);
554 EXPECT_EQ(D0, Redecls[0]);
555}
556
557TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
558 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
559 auto Pattern = functionDecl(hasName("f"));
560 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
561 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
562 FunctionDecl *D1 = D2->getPreviousDecl();
563
564 auto Redecls = getCanonicalForwardRedeclChain(D0);
565 ASSERT_EQ(Redecls.size(), 3u);
566 EXPECT_EQ(D0, Redecls[0]);
567 EXPECT_EQ(D1, Redecls[1]);
568 EXPECT_EQ(D2, Redecls[2]);
569}
570
571TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
572 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
573 auto Pattern = functionDecl(hasName("f"));
574 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
575 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
576 FunctionDecl *D1 = D2->getPreviousDecl();
577
578 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
579 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
580 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
581
582 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
583 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
584}
585
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000586namespace {
587struct RedirectingImporter : public ASTImporter {
588 using ASTImporter::ASTImporter;
589
590protected:
591 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
592 auto *ND = dyn_cast<NamedDecl>(FromD);
593 if (!ND || ND->getName() != "shouldNotBeImported")
594 return ASTImporter::ImportImpl(FromD);
595 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {
596 if (auto *ND = dyn_cast<NamedDecl>(D))
597 if (ND->getName() == "realDecl") {
598 RegisterImportedDecl(FromD, ND);
599 return ND;
600 }
601 }
602 return ASTImporter::ImportImpl(FromD);
603 }
604};
605
606} // namespace
607
608struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
609 RedirectingImporterTest() {
610 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
611 ASTContext &FromContext, FileManager &FromFileManager,
612 bool MinimalImport, ASTImporterLookupTable *LookupTable) {
613 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
614 FromFileManager, MinimalImport,
615 LookupTable);
616 };
617 }
618};
619
620// Test that an ASTImporter subclass can intercept an import call.
621TEST_P(RedirectingImporterTest, InterceptImport) {
622 Decl *From, *To;
623 std::tie(From, To) =
624 getImportedDecl("class shouldNotBeImported {};", Lang_CXX,
625 "class realDecl {};", Lang_CXX, "shouldNotBeImported");
626 auto *Imported = cast<CXXRecordDecl>(To);
627 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
628
629 // Make sure our importer prevented the importing of the decl.
630 auto *ToTU = Imported->getTranslationUnitDecl();
631 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
632 unsigned count =
633 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
634 EXPECT_EQ(0U, count);
635}
636
637// Test that when we indirectly import a declaration the custom ASTImporter
638// is still intercepting the import.
639TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
640 Decl *From, *To;
641 std::tie(From, To) =
642 getImportedDecl("class shouldNotBeImported {};"
643 "class F { shouldNotBeImported f; };",
644 Lang_CXX, "class realDecl {};", Lang_CXX, "F");
645
646 // Make sure our ASTImporter prevented the importing of the decl.
647 auto *ToTU = To->getTranslationUnitDecl();
648 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
649 unsigned count =
650 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
651 EXPECT_EQ(0U, count);
652}
653
Gabor Marton19f4f392018-06-25 13:04:37 +0000654TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000655 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000656 testImport(
657 "void declToImport() { (void)\"foo\"; }",
658 Lang_CXX, "", Lang_CXX, Verifier,
659 functionDecl(hasDescendant(
660 stringLiteral(hasType(asString("const char [4]"))))));
661 testImport(
662 "void declToImport() { (void)L\"foo\"; }",
663 Lang_CXX, "", Lang_CXX, Verifier,
664 functionDecl(hasDescendant(
665 stringLiteral(hasType(asString("const wchar_t [4]"))))));
666 testImport(
667 "void declToImport() { (void) \"foo\" \"bar\"; }",
668 Lang_CXX, "", Lang_CXX, Verifier,
669 functionDecl(hasDescendant(
670 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000671}
672
Tom Roeder521f0042019-02-26 19:26:41 +0000673TEST_P(ImportExpr, ImportChooseExpr) {
674 MatchVerifier<Decl> Verifier;
675
676 // This case tests C code that is not condition-dependent and has a true
677 // condition.
678 testImport(
679 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
680 Lang_C, "", Lang_C, Verifier,
681 functionDecl(hasDescendant(chooseExpr())));
682}
683
Gabor Marton19f4f392018-06-25 13:04:37 +0000684TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000685 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000686 testImport(
687 "void declToImport() { (void)__null; }",
688 Lang_CXX, "", Lang_CXX, Verifier,
689 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000690}
691
Gabor Marton19f4f392018-06-25 13:04:37 +0000692TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000693 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000694 testImport(
695 "void declToImport() { (void)nullptr; }",
696 Lang_CXX11, "", Lang_CXX11, Verifier,
697 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000698}
699
700
Gabor Marton19f4f392018-06-25 13:04:37 +0000701TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000702 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000703 testImport(
704 "void declToImport() { (void)1.0; }",
705 Lang_C, "", Lang_C, Verifier,
706 functionDecl(hasDescendant(
707 floatLiteral(equals(1.0), hasType(asString("double"))))));
708 testImport(
709 "void declToImport() { (void)1.0e-5f; }",
710 Lang_C, "", Lang_C, Verifier,
711 functionDecl(hasDescendant(
712 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000713}
714
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000715TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
716 MatchVerifier<Decl> Verifier;
717 testImport(
718 "void declToImport() { (void)1.0i; }",
719 Lang_CXX14, "", Lang_CXX14, Verifier,
720 functionDecl(hasDescendant(imaginaryLiteral())));
721}
722
Gabor Marton19f4f392018-06-25 13:04:37 +0000723TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000724 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000725 testImport(
726 "void declToImport() {"
727 " struct s { int x; long y; unsigned z; }; "
728 " (void)(struct s){ 42, 0L, 1U }; }",
729 Lang_CXX, "", Lang_CXX, Verifier,
730 functionDecl(hasDescendant(
731 compoundLiteralExpr(
732 hasType(asString("struct s")),
733 has(initListExpr(
734 hasType(asString("struct s")),
735 has(integerLiteral(
736 equals(42), hasType(asString("int")))),
737 has(integerLiteral(
738 equals(0), hasType(asString("long")))),
739 has(integerLiteral(
740 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000741}
742
Gabor Marton19f4f392018-06-25 13:04:37 +0000743TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000744 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000745 testImport(
746 "class declToImport { void f() { (void)this; } };",
747 Lang_CXX, "", Lang_CXX, Verifier,
748 cxxRecordDecl(
749 hasMethod(
750 hasDescendant(
751 cxxThisExpr(
752 hasType(
753 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000754}
755
Gabor Marton19f4f392018-06-25 13:04:37 +0000756TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000757 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000758 testImport(
759 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
760 Lang_C, "", Lang_C, Verifier,
761 functionDecl(hasDescendant(
762 atomicExpr(
763 has(ignoringParenImpCasts(
764 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
765 hasType(asString("int *"))))),
766 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000767}
768
Gabor Marton19f4f392018-06-25 13:04:37 +0000769TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000770 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000771 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000772 "void declToImport() { loop: goto loop; (void)&&loop; }",
773 Lang_C, "", Lang_C, Verifier,
774 functionDecl(
775 hasDescendant(
776 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
777 hasDescendant(
778 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000779}
780
781AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
782 internal::Matcher<NamedDecl>, InnerMatcher) {
783 const NamedDecl *Template = Node.getTemplatedDecl();
784 return Template && InnerMatcher.matches(*Template, Finder, Builder);
785}
786
Gabor Marton19f4f392018-06-25 13:04:37 +0000787TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000788 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000789 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000790 "template<typename T> class dummy { void f() { dummy X(*this); } };"
791 "typedef dummy<int> declToImport;"
792 "template class dummy<int>;",
793 Lang_CXX, "", Lang_CXX, Verifier,
794 typedefDecl(hasType(templateSpecializationType(
795 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
796 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
797 hasName("f"),
798 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
799 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
800 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000801 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000802}
803
Gabor Marton19f4f392018-06-25 13:04:37 +0000804TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000805 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000806 testImport(
807 "void declToImport() { int b; switch (b) { case 1: break; } }",
808 Lang_C, "", Lang_C, Verifier,
809 functionDecl(hasDescendant(
810 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000811}
812
Gabor Marton19f4f392018-06-25 13:04:37 +0000813TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000814 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000815 testImport(
816 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
817 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000818 functionDecl(hasDescendant(
819 varDecl(
820 hasName("C"),
821 hasType(asString("int")),
822 hasInitializer(
823 stmtExpr(
824 hasAnySubstatement(declStmt(hasSingleDecl(
825 varDecl(
826 hasName("X"),
827 hasType(asString("int")),
828 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000829 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000830 hasDescendant(
831 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000832}
833
Gabor Marton19f4f392018-06-25 13:04:37 +0000834TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000835 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000836 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000837 "void declToImport() { (void)(true ? 1 : -5); }",
838 Lang_CXX, "", Lang_CXX, Verifier,
839 functionDecl(hasDescendant(
840 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000841 hasCondition(cxxBoolLiteral(equals(true))),
842 hasTrueExpression(integerLiteral(equals(1))),
843 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000844 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
845 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000846}
847
Gabor Marton19f4f392018-06-25 13:04:37 +0000848TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000849 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000850 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000851 "void declToImport() { (void)(1 ?: -5); }",
852 Lang_CXX, "", Lang_CXX, Verifier,
853 functionDecl(hasDescendant(
854 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000855 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000856 implicitCastExpr(
857 hasSourceExpression(opaqueValueExpr(
858 hasSourceExpression(integerLiteral(equals(1))))),
859 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000860 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000861 opaqueValueExpr(
862 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000863 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000864 unaryOperator(
865 hasOperatorName("-"),
866 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000867}
868
Gabor Marton19f4f392018-06-25 13:04:37 +0000869TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000870 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000871 testImport(
872 "void declToImport() {"
873 " struct point { double x; double y; };"
874 " struct point ptarray[10] = "
875 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
876 Lang_C, "", Lang_C, Verifier,
877 functionDecl(hasDescendant(
878 initListExpr(
879 has(designatedInitExpr(
880 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000881 hasDescendant(floatLiteral(equals(1.0))),
882 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000883 has(designatedInitExpr(
884 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000885 hasDescendant(floatLiteral(equals(2.0))),
886 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000887 has(designatedInitExpr(
888 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000889 hasDescendant(floatLiteral(equals(1.0))),
890 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000891}
892
Gabor Marton19f4f392018-06-25 13:04:37 +0000893TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000894 MatchVerifier<Decl> Verifier;
895 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000896 testImport(
897 "void declToImport() { (void)__func__; }",
898 Lang_CXX, "", Lang_CXX, Verifier,
899 functionDecl(hasDescendant(
900 predefinedExpr(
901 hasType(
902 asString("const char [13]")),
903 has(stringLiteral(hasType(
904 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000905}
906
Gabor Marton19f4f392018-06-25 13:04:37 +0000907TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000908 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000909 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000910 "void declToImport() {"
911 " struct point { double x; double y; };"
912 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
913 " [0].x = 1.0 }; }",
914 Lang_CXX, "", Lang_CXX, Verifier,
915 functionDecl(hasDescendant(
916 initListExpr(
917 has(
918 cxxConstructExpr(
919 requiresZeroInitialization())),
920 has(
921 initListExpr(
922 hasType(asString("struct point")),
923 has(floatLiteral(equals(1.0))),
924 has(implicitValueInitExpr(
925 hasType(asString("double")))))),
926 has(
927 initListExpr(
928 hasType(asString("struct point")),
929 has(floatLiteral(equals(2.0))),
930 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000931}
932
933
Aleksei Sidorina693b372016-09-28 10:16:56 +0000934const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
935
Gabor Marton19f4f392018-06-25 13:04:37 +0000936TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000937 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000938 testImport(
939 "void declToImport(__builtin_va_list list, ...) {"
940 " (void)__builtin_va_arg(list, int); }",
941 Lang_CXX, "", Lang_CXX, Verifier,
942 functionDecl(hasDescendant(
943 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000944}
945
Gabor Marton19f4f392018-06-25 13:04:37 +0000946TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000947 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000948 testImport(
949 "struct C {};"
950 "void declToImport() { C c = C(); }",
951 Lang_CXX, "", Lang_CXX, Verifier,
952 functionDecl(hasDescendant(
953 exprWithCleanups(has(cxxConstructExpr(
954 has(materializeTemporaryExpr(has(implicitCastExpr(
955 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000956}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000957
Gabor Marton19f4f392018-06-25 13:04:37 +0000958TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000959 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000960 testImport(
961 "void declToImport() { typedef _Atomic(int) a_int; }",
962 Lang_CXX11, "", Lang_CXX11, Verifier,
963 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000964}
965
Gabor Marton19f4f392018-06-25 13:04:37 +0000966TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000967 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000968 testImport(
969 "template <typename T> void declToImport() { };",
970 Lang_CXX, "", Lang_CXX, Verifier,
971 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000972}
973
Gabor Marton19f4f392018-06-25 13:04:37 +0000974TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000975 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000976 testImport(
977 "template <typename T> struct C { T t; };"
978 "template <typename T> void declToImport() {"
979 " C<T> d;"
980 " (void)d.t;"
981 "}"
982 "void instantiate() { declToImport<int>(); }",
983 Lang_CXX, "", Lang_CXX, Verifier,
984 functionTemplateDecl(hasDescendant(
985 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
986 testImport(
987 "template <typename T> struct C { T t; };"
988 "template <typename T> void declToImport() {"
989 " C<T> d;"
990 " (void)(&d)->t;"
991 "}"
992 "void instantiate() { declToImport<int>(); }",
993 Lang_CXX, "", Lang_CXX, Verifier,
994 functionTemplateDecl(hasDescendant(
995 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000996}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000997
Gabor Marton19f4f392018-06-25 13:04:37 +0000998TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000999 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +00001000 testImport(
1001 "template <int K>"
1002 "struct dummy { static const int i = K; };"
1003 "template <int K> using dummy2 = dummy<K>;"
1004 "int declToImport() { return dummy2<3>::i; }",
1005 Lang_CXX11, "", Lang_CXX11, Verifier,
1006 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +00001007 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +00001008 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
1009}
1010
1011const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
1012 varTemplateSpecializationDecl;
1013
Gabor Marton19f4f392018-06-25 13:04:37 +00001014TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +00001015 MatchVerifier<Decl> Verifier;
1016 testImport(
1017 "template <typename T>"
1018 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +00001019 "void declToImport() { (void)pi<int>; }",
1020 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +00001021 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +00001022 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +00001023 unless(hasAncestor(translationUnitDecl(has(varDecl(
1024 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +00001025}
1026
Gabor Marton19f4f392018-06-25 13:04:37 +00001027TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +00001028 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001029 testImport(
1030 "template <typename... Args>"
1031 "struct dummy {"
1032 " dummy(Args... args) {}"
1033 " static const int i = 4;"
1034 "};"
1035 "int declToImport() { return dummy<int>::i; }",
1036 Lang_CXX11, "", Lang_CXX11, Verifier,
1037 functionDecl(hasDescendant(
1038 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +00001039}
1040
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001041const internal::VariadicDynCastAllOfMatcher<Type,
1042 DependentTemplateSpecializationType>
1043 dependentTemplateSpecializationType;
1044
Gabor Marton19f4f392018-06-25 13:04:37 +00001045TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001046 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001047 testImport(
1048 "template<typename T>"
1049 "struct A;"
1050 "template<typename T>"
1051 "struct declToImport {"
1052 " typename A<T>::template B<T> a;"
1053 "};",
1054 Lang_CXX, "", Lang_CXX, Verifier,
1055 classTemplateDecl(has(cxxRecordDecl(has(
1056 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001057}
1058
1059const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
1060 sizeOfPackExpr;
1061
Gabor Marton19f4f392018-06-25 13:04:37 +00001062TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001063 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001064 testImport(
1065 "template <typename... Ts>"
1066 "void declToImport() {"
1067 " const int i = sizeof...(Ts);"
1068 "};"
1069 "void g() { declToImport<int>(); }",
1070 Lang_CXX11, "", Lang_CXX11, Verifier,
1071 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001072 testImport(
1073 "template <typename... Ts>"
1074 "using X = int[sizeof...(Ts)];"
1075 "template <typename... Us>"
1076 "struct Y {"
1077 " X<Us..., int, double, int, Us...> f;"
1078 "};"
1079 "Y<float, int> declToImport;",
1080 Lang_CXX11, "", Lang_CXX11, Verifier,
1081 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
1082 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
1083}
1084
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001085/// \brief Matches __builtin_types_compatible_p:
1086/// GNU extension to check equivalent types
1087/// Given
1088/// \code
1089/// __builtin_types_compatible_p(int, int)
1090/// \endcode
1091// will generate TypeTraitExpr <...> 'int'
1092const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
1093
Gabor Marton19f4f392018-06-25 13:04:37 +00001094TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001095 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001096 testImport(
1097 "void declToImport() { "
1098 " (void)__builtin_types_compatible_p(int, int);"
1099 "}",
1100 Lang_C, "", Lang_C, Verifier,
1101 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001102}
1103
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001104const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
1105
Gabor Marton19f4f392018-06-25 13:04:37 +00001106TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001107 MatchVerifier<Decl> Verifier;
1108 testImport(
1109 "namespace std { class type_info {}; }"
1110 "void declToImport() {"
1111 " int x;"
1112 " auto a = typeid(int); auto b = typeid(x);"
1113 "}",
1114 Lang_CXX11, "", Lang_CXX11, Verifier,
1115 functionDecl(
1116 hasDescendant(varDecl(
1117 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
1118 hasDescendant(varDecl(
1119 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
1120}
1121
Gabor Marton19f4f392018-06-25 13:04:37 +00001122TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001123 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001124 testImport(
1125 "template<typename T> struct declToImport {"
1126 " void m() { (void)__is_pod(T); }"
1127 "};"
1128 "void f() { declToImport<int>().m(); }",
1129 Lang_CXX11, "", Lang_CXX11, Verifier,
1130 classTemplateDecl(has(cxxRecordDecl(has(
1131 functionDecl(hasDescendant(
1132 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001133}
Gabor Horvath7a91c082017-11-14 11:30:38 +00001134
Gabor Marton6e1510c2018-07-12 11:50:21 +00001135TEST_P(ImportDecl, ImportRecordDeclInFunc) {
1136 MatchVerifier<Decl> Verifier;
1137 testImport("int declToImport() { "
1138 " struct data_t {int a;int b;};"
1139 " struct data_t d;"
1140 " return 0;"
1141 "}",
1142 Lang_C, "", Lang_C, Verifier,
1143 functionDecl(hasBody(compoundStmt(
1144 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
1145}
1146
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001147TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001148 Decl *FromTU = getTuDecl("int declToImport() { "
1149 " struct data_t {int a;int b;};"
1150 " struct data_t d;"
1151 " return 0;"
1152 "}",
1153 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +00001154 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +00001155 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
1156 ASSERT_TRUE(FromVar);
1157 auto ToType =
1158 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
1159 EXPECT_FALSE(ToType.isNull());
1160}
1161
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001162TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001163 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +00001164 Decl *FromTU = getTuDecl(
1165 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1166 Lang_C, "input.c");
1167 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1168 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001169 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001170 auto *To = Import(From, Lang_C);
1171 EXPECT_EQ(To, nullptr);
1172}
1173
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001174TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001175 Decl *FromTU = getTuDecl(
1176 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1177 "int declToImport(){ return NONAME_SIZEOF(int); }",
1178 Lang_C, "input.c");
1179 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1180 FromTU, functionDecl(hasName("declToImport")));
1181 ASSERT_TRUE(From);
1182 auto *To = Import(From, Lang_C);
1183 ASSERT_TRUE(To);
1184 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1185 To, functionDecl(hasName("declToImport"),
1186 hasDescendant(unaryExprOrTypeTraitExpr()))));
1187}
1188
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001189TEST_P(ASTImporterOptionSpecificTestBase,
1190 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001191 // This construct is not supported by ASTImporter.
1192 Decl *FromTU = getTuDecl(
1193 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1194 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1195 Lang_C, "input.c");
1196 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1197 FromTU, functionDecl(hasName("declToImport")));
1198 ASSERT_TRUE(From);
1199 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001200 EXPECT_EQ(To, nullptr);
1201}
1202
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001203const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1204 cxxPseudoDestructorExpr;
1205
Gabor Marton19f4f392018-06-25 13:04:37 +00001206TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001207 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001208 testImport(
1209 "typedef int T;"
1210 "void declToImport(int *p) {"
1211 " T t;"
1212 " p->T::~T();"
1213 "}",
1214 Lang_CXX, "", Lang_CXX, Verifier,
1215 functionDecl(hasDescendant(
1216 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001217}
1218
Gabor Marton19f4f392018-06-25 13:04:37 +00001219TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001220 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001221 testImport(
1222 "namespace foo { int bar; }"
1223 "void declToImport() { using foo::bar; }",
1224 Lang_CXX, "", Lang_CXX, Verifier,
1225 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001226}
1227
1228/// \brief Matches shadow declarations introduced into a scope by a
1229/// (resolved) using declaration.
1230///
1231/// Given
1232/// \code
1233/// namespace n { int f; }
1234/// namespace declToImport { using n::f; }
1235/// \endcode
1236/// usingShadowDecl()
1237/// matches \code f \endcode
1238const internal::VariadicDynCastAllOfMatcher<Decl,
1239 UsingShadowDecl> usingShadowDecl;
1240
Gabor Marton19f4f392018-06-25 13:04:37 +00001241TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001242 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001243 testImport(
1244 "namespace foo { int bar; }"
1245 "namespace declToImport { using foo::bar; }",
1246 Lang_CXX, "", Lang_CXX, Verifier,
1247 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001248}
1249
Gabor Marton19f4f392018-06-25 13:04:37 +00001250TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001251 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001252 testImport(
1253 "template<typename T> int foo();"
1254 "template <typename T> void declToImport() {"
1255 " (void)::foo<T>;"
1256 " (void)::template foo<T>;"
1257 "}"
1258 "void instantiate() { declToImport<int>(); }",
1259 Lang_CXX, "", Lang_CXX, Verifier,
1260 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001261}
1262
Gabor Marton19f4f392018-06-25 13:04:37 +00001263TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001264 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001265 testImport(
1266 "template <typename T> struct C { T t; };"
1267 "template <typename T> void declToImport() {"
1268 " C<T> d;"
1269 " d.t = T();"
1270 "}"
1271 "void instantiate() { declToImport<int>(); }",
1272 Lang_CXX, "", Lang_CXX, Verifier,
1273 functionTemplateDecl(hasDescendant(
1274 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1275 testImport(
1276 "template <typename T> struct C { T t; };"
1277 "template <typename T> void declToImport() {"
1278 " C<T> d;"
1279 " (&d)->t = T();"
1280 "}"
1281 "void instantiate() { declToImport<int>(); }",
1282 Lang_CXX, "", Lang_CXX, Verifier,
1283 functionTemplateDecl(hasDescendant(
1284 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001285}
1286
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001287/// Check that function "declToImport()" (which is the templated function
1288/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1289/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001290TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001291 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001292 testImport(
1293 "template <typename T> void declToImport() { T a = 1; }"
1294 "void instantiate() { declToImport<int>(); }",
1295 Lang_CXX, "", Lang_CXX, Verifier,
1296 functionTemplateDecl(hasAncestor(translationUnitDecl(
1297 unless(has(functionDecl(hasName("declToImport"))))))));
1298 testImport(
1299 "template <typename T> struct declToImport { T t; };"
1300 "void instantiate() { declToImport<int>(); }",
1301 Lang_CXX, "", Lang_CXX, Verifier,
1302 classTemplateDecl(hasAncestor(translationUnitDecl(
1303 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001304}
1305
Gabor Marton19f4f392018-06-25 13:04:37 +00001306TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001307 MatchVerifier<Decl> Verifier;
1308 auto Code =
1309 R"s(
1310 struct declToImport {
1311 template <typename T0> struct X;
1312 template <typename T0> struct X<T0 *> {};
1313 };
1314 )s";
1315 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1316 recordDecl(has(classTemplateDecl()),
1317 has(classTemplateSpecializationDecl())));
1318}
1319
Gabor Marton19f4f392018-06-25 13:04:37 +00001320TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001321 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001322 testImport(
1323 "class declToImport {"
1324 " void f() { *this = declToImport(); }"
1325 "};",
1326 Lang_CXX, "", Lang_CXX, Verifier,
1327 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1328 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001329}
1330
Gabor Marton19f4f392018-06-25 13:04:37 +00001331TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001332 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001333 testImport(
1334 "template<typename T, int Size> class declToImport {"
1335 " T data[Size];"
1336 "};",
1337 Lang_CXX, "", Lang_CXX, Verifier,
1338 classTemplateDecl(has(cxxRecordDecl(
1339 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001340}
1341
Balazs Keri5f4fd8b2019-03-14 14:20:23 +00001342TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1343 Decl *FromTU = getTuDecl(
1344 "class A { public: static int X; }; void f() { (void)A::X; }", Lang_CXX);
1345 auto From = FirstDeclMatcher<FunctionDecl>().match(
1346 FromTU, functionDecl(hasName("f")));
1347 ASSERT_TRUE(From);
1348 ASSERT_TRUE(
1349 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1350 ->getSubExpr()
1351 ->getBeginLoc()
1352 .isValid());
1353 FunctionDecl *To = Import(From, Lang_CXX);
1354 ASSERT_TRUE(To);
1355 ASSERT_TRUE(
1356 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1357 ->getSubExpr()
1358 ->getBeginLoc()
1359 .isValid());
1360}
1361
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001362TEST_P(ASTImporterOptionSpecificTestBase,
1363 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001364 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1365 auto From =
1366 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1367 ASSERT_TRUE(From);
1368 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1369 ASSERT_TRUE(To);
1370 Decl *ToTemplated = To->getTemplatedDecl();
1371 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1372 EXPECT_TRUE(ToTemplated1);
1373 EXPECT_EQ(ToTemplated1, ToTemplated);
1374}
1375
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001376TEST_P(ASTImporterOptionSpecificTestBase,
1377 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001378 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1379 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1380 FromTU, functionTemplateDecl());
1381 ASSERT_TRUE(From);
1382 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1383 ASSERT_TRUE(To);
1384 Decl *ToTemplated = To->getTemplatedDecl();
1385 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1386 EXPECT_TRUE(ToTemplated1);
1387 EXPECT_EQ(ToTemplated1, ToTemplated);
1388}
1389
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001390TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001391 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1392 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1393 auto FromFT =
1394 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1395 ASSERT_TRUE(FromFT);
1396
1397 auto ToTemplated =
1398 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1399 EXPECT_TRUE(ToTemplated);
1400 auto ToTU = ToTemplated->getTranslationUnitDecl();
1401 auto ToFT =
1402 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1403 EXPECT_TRUE(ToFT);
1404}
1405
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001406TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001407 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001408 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1409 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1410 FromTU, functionTemplateDecl());
1411 ASSERT_TRUE(FromFT);
1412
1413 auto ToTemplated =
1414 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1415 EXPECT_TRUE(ToTemplated);
1416 auto ToTU = ToTemplated->getTranslationUnitDecl();
1417 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1418 ToTU, functionTemplateDecl());
1419 EXPECT_TRUE(ToFT);
1420}
1421
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001422TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001423 auto Code =
1424 R"(
1425 namespace x {
1426 template<class X> struct S1{};
1427 template<class X> struct S2{};
1428 template<class X> struct S3{};
1429 }
1430 )";
1431 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1432 auto FromNs =
1433 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1434 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1435 ASSERT_TRUE(ToNs);
1436 auto From =
1437 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1438 classTemplateDecl(
1439 hasName("S2")));
1440 auto To =
1441 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1442 classTemplateDecl(
1443 hasName("S2")));
1444 ASSERT_TRUE(From);
1445 ASSERT_TRUE(To);
1446 auto ToTemplated = To->getTemplatedDecl();
1447 auto ToTemplated1 =
1448 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1449 EXPECT_TRUE(ToTemplated1);
1450 ASSERT_EQ(ToTemplated1, ToTemplated);
1451}
1452
Tom Roeder521f0042019-02-26 19:26:41 +00001453TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1454 // This tests the import of isConditionTrue directly to make sure the importer
1455 // gets it right.
1456 Decl *From, *To;
1457 std::tie(From, To) = getImportedDecl(
1458 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1459 Lang_C, "", Lang_C);
1460
1461 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1462 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1463
1464 const ChooseExpr *FromChooseExpr =
1465 selectFirst<ChooseExpr>("choose", FromResults);
1466 ASSERT_TRUE(FromChooseExpr);
1467
1468 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1469 ASSERT_TRUE(ToChooseExpr);
1470
1471 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1472 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1473 ToChooseExpr->isConditionDependent());
1474}
1475
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001476TEST_P(ASTImporterOptionSpecificTestBase,
1477 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001478 Decl *From, *To;
1479 std::tie(From, To) = getImportedDecl(
1480 R"(
1481 template <typename T> struct X {};
1482
1483 void declToImport(int y, X<int> &x) {}
1484
1485 template <> struct X<int> {
1486 void g() {
1487 X<int> x;
1488 declToImport(0, x);
1489 }
1490 };
1491 )",
1492 Lang_CXX, "", Lang_CXX);
1493
1494 MatchVerifier<Decl> Verifier;
1495 auto Matcher = functionDecl(hasName("declToImport"),
1496 parameterCountIs(2),
1497 hasParameter(0, hasName("y")),
1498 hasParameter(1, hasName("x")),
1499 hasParameter(1, hasType(asString("X<int> &"))));
1500 ASSERT_TRUE(Verifier.match(From, Matcher));
1501 EXPECT_TRUE(Verifier.match(To, Matcher));
1502}
1503
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001504TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001505 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1506 Decl *From, *To;
1507 std::tie(From, To) =
1508 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1509 "void instantiate() { declToImport<int>(); }",
1510 Lang_CXX, "", Lang_CXX);
1511
1512 auto Check = [](Decl *D) -> bool {
1513 auto TU = D->getTranslationUnitDecl();
1514 for (auto Child : TU->decls()) {
1515 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1516 if (FD->getNameAsString() == "declToImport") {
1517 GTEST_NONFATAL_FAILURE_(
1518 "TU should not contain any FunctionDecl with name declToImport");
1519 return false;
1520 }
1521 }
1522 }
1523 return true;
1524 };
1525
1526 ASSERT_TRUE(Check(From));
1527 EXPECT_TRUE(Check(To));
1528}
1529
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001530TEST_P(ASTImporterOptionSpecificTestBase,
1531 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001532 Decl *From, *To;
1533 std::tie(From, To) =
1534 getImportedDecl("template <typename T> struct declToImport { T t; };"
1535 "void instantiate() { declToImport<int>(); }",
1536 Lang_CXX, "", Lang_CXX);
1537
1538 auto Check = [](Decl *D) -> bool {
1539 auto TU = D->getTranslationUnitDecl();
1540 for (auto Child : TU->decls()) {
1541 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1542 if (RD->getNameAsString() == "declToImport") {
1543 GTEST_NONFATAL_FAILURE_(
1544 "TU should not contain any CXXRecordDecl with name declToImport");
1545 return false;
1546 }
1547 }
1548 }
1549 return true;
1550 };
1551
1552 ASSERT_TRUE(Check(From));
1553 EXPECT_TRUE(Check(To));
1554}
1555
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001556TEST_P(ASTImporterOptionSpecificTestBase,
1557 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001558 Decl *From, *To;
1559 std::tie(From, To) =
1560 getImportedDecl(
1561 "template <typename T> struct X {};"
1562 "template <typename T> using declToImport = X<T>;"
1563 "void instantiate() { declToImport<int> a; }",
1564 Lang_CXX11, "", Lang_CXX11);
1565
1566 auto Check = [](Decl *D) -> bool {
1567 auto TU = D->getTranslationUnitDecl();
1568 for (auto Child : TU->decls()) {
1569 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1570 if (AD->getNameAsString() == "declToImport") {
1571 GTEST_NONFATAL_FAILURE_(
1572 "TU should not contain any TypeAliasDecl with name declToImport");
1573 return false;
1574 }
1575 }
1576 }
1577 return true;
1578 };
1579
1580 ASSERT_TRUE(Check(From));
1581 EXPECT_TRUE(Check(To));
1582}
1583
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001584TEST_P(ASTImporterOptionSpecificTestBase,
1585 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001586
1587 Decl *From, *To;
1588 std::tie(From, To) = getImportedDecl(
1589 R"(
1590 template<class T>
1591 class Base {};
1592 class declToImport : public Base<declToImport> {};
1593 )",
1594 Lang_CXX, "", Lang_CXX);
1595
1596 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1597 auto Pattern =
1598 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1599 ASSERT_TRUE(
1600 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1601 EXPECT_TRUE(
1602 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1603
1604 // Check that the ClassTemplateSpecializationDecl is the child of the
1605 // ClassTemplateDecl.
1606 Pattern = translationUnitDecl(has(classTemplateDecl(
1607 hasName("Base"), has(classTemplateSpecializationDecl()))));
1608 ASSERT_TRUE(
1609 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1610 EXPECT_TRUE(
1611 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1612}
1613
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001614AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1615 size_t Index = 0;
1616 for (FieldDecl *Field : Node.fields()) {
1617 if (Index == Order.size())
1618 return false;
1619 if (Field->getName() != Order[Index])
1620 return false;
1621 ++Index;
1622 }
1623 return Index == Order.size();
1624}
1625
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001626TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001627 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1628 Decl *From, *To;
1629 std::tie(From, To) = getImportedDecl(
1630 R"(
1631 namespace NS {
1632 template<class T>
1633 class X {};
1634 template class X<int>;
1635 }
1636 )",
1637 Lang_CXX, "", Lang_CXX, "NS");
1638
1639 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1640 // ClassTemplateDecl.
1641 auto Pattern = namespaceDecl(has(classTemplateDecl(
1642 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1643 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1644 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1645
1646 // Check that the ClassTemplateSpecializationDecl is the child of the
1647 // NamespaceDecl.
1648 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1649 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1650 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1651}
1652
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001653TEST_P(ASTImporterOptionSpecificTestBase,
1654 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001655 Decl *From, *To;
1656 std::tie(From, To) =
1657 getImportedDecl(
1658 "struct declToImport { int a; int b; };",
1659 Lang_CXX11, "", Lang_CXX11);
1660
1661 MatchVerifier<Decl> Verifier;
1662 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1663 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1664}
1665
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001666TEST_P(ASTImporterOptionSpecificTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001667 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001668 Decl *From, *To;
1669 std::tie(From, To) = getImportedDecl(
1670 // The original recursive algorithm of ASTImporter first imports 'c' then
1671 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1672 R"s(
1673 struct declToImport {
1674 int a = c + b;
1675 int b = 1;
1676 int c = 2;
1677 };
1678 )s",
1679 Lang_CXX11, "", Lang_CXX11);
1680
1681 MatchVerifier<Decl> Verifier;
1682 ASSERT_TRUE(
1683 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1684 EXPECT_TRUE(
1685 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1686}
1687
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001688TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001689 Decl *From, *To;
1690 std::tie(From, To) = getImportedDecl(
1691 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001692 struct declToImport {
1693 };
1694 )",
1695 Lang_CXX, "", Lang_CXX);
1696
1697 MatchVerifier<Decl> Verifier;
1698 // Match the implicit Decl.
1699 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1700 ASSERT_TRUE(Verifier.match(From, Matcher));
1701 EXPECT_TRUE(Verifier.match(To, Matcher));
1702}
1703
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001704TEST_P(ASTImporterOptionSpecificTestBase,
1705 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001706 Decl *From, *To;
1707 std::tie(From, To) = getImportedDecl(
1708 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001709 template <typename U>
1710 struct declToImport {
1711 };
1712 )",
1713 Lang_CXX, "", Lang_CXX);
1714
1715 MatchVerifier<Decl> Verifier;
1716 // Match the implicit Decl.
1717 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1718 ASSERT_TRUE(Verifier.match(From, Matcher));
1719 EXPECT_TRUE(Verifier.match(To, Matcher));
1720}
1721
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001722TEST_P(ASTImporterOptionSpecificTestBase,
1723 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001724 Decl *From, *To;
1725 std::tie(From, To) = getImportedDecl(
1726 R"(
1727 template<class T>
1728 class Base {};
1729 class declToImport : public Base<declToImport> {};
1730 )",
1731 Lang_CXX, "", Lang_CXX);
1732
1733 auto hasImplicitClass = has(cxxRecordDecl());
1734 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1735 hasName("Base"),
1736 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1737 ASSERT_TRUE(
1738 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1739 EXPECT_TRUE(
1740 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1741}
1742
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001743TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001744 Decl *From, *To;
1745 std::tie(From, To) =
1746 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1747
1748 MatchVerifier<Decl> Verifier;
1749 auto Matcher = functionDecl();
1750 ASSERT_TRUE(Verifier.match(From, Matcher));
1751 EXPECT_TRUE(Verifier.match(To, Matcher));
1752 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1753}
1754
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001755TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001756 Decl *FromTU = getTuDecl(
1757 R"(
1758 struct X {};
1759 void operator<<(int, X);
1760 )",
1761 Lang_CXX);
1762 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1763 const Decl *To = Import(From, Lang_CXX);
1764 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1765}
1766
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001767TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001768 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1769 Decl *From, *To;
1770 std::tie(From, To) = getImportedDecl(
1771 R"(
1772 template<class T>
1773 class Base { int a; };
1774 class declToImport : Base<declToImport> {};
1775 )",
1776 Lang_CXX, "", Lang_CXX);
1777
1778 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1779 hasName("Base"),
1780 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1781 ASSERT_TRUE(
1782 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1783 EXPECT_TRUE(
1784 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1785}
1786
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001787TEST_P(ASTImporterOptionSpecificTestBase,
1788 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001789 {
1790 Decl *FromTU = getTuDecl(
1791 R"(
1792 template <typename T>
1793 struct B;
1794 )",
1795 Lang_CXX, "input0.cc");
1796 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1797 FromTU, classTemplateDecl(hasName("B")));
1798
1799 Import(FromD, Lang_CXX);
1800 }
1801
1802 {
1803 Decl *FromTU = getTuDecl(
1804 R"(
1805 template <typename T>
1806 struct B {
1807 void f();
1808 };
1809 )",
1810 Lang_CXX, "input1.cc");
1811 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1812 FromTU, functionDecl(hasName("f")));
1813 Import(FromD, Lang_CXX);
1814 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1815 FromTU, classTemplateDecl(hasName("B")));
1816 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1817 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1818 }
1819}
1820
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001821TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001822 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1823 Decl *ToTU = getToTuDecl(
1824 R"(
1825 template <typename T>
1826 struct B {
1827 void f();
1828 };
1829
1830 template <typename T>
1831 struct B;
1832 )",
1833 Lang_CXX);
1834 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1835 [](const ClassTemplateDecl *T) {
1836 return T->isThisDeclarationADefinition();
1837 })
1838 .match(ToTU, classTemplateDecl()));
1839
1840 Decl *FromTU = getTuDecl(
1841 R"(
1842 template <typename T>
1843 struct B {
1844 void f();
1845 };
1846 )",
1847 Lang_CXX, "input1.cc");
1848 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1849 FromTU, classTemplateDecl(hasName("B")));
1850
1851 Import(FromD, Lang_CXX);
1852
1853 // We should have only one definition.
1854 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1855 [](const ClassTemplateDecl *T) {
1856 return T->isThisDeclarationADefinition();
1857 })
1858 .match(ToTU, classTemplateDecl()));
1859}
1860
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001861TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001862 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1863 Decl *ToTU = getToTuDecl(
1864 R"(
1865 struct B {
1866 void f();
1867 };
1868
1869 struct B;
1870 )",
1871 Lang_CXX);
1872 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001873 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001874
1875 Decl *FromTU = getTuDecl(
1876 R"(
1877 struct B {
1878 void f();
1879 };
1880 )",
1881 Lang_CXX, "input1.cc");
1882 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1883 FromTU, cxxRecordDecl(hasName("B")));
1884
1885 Import(FromD, Lang_CXX);
1886
1887 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001888 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001889}
1890
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001891static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1892 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1893 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1894 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1895 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1896}
1897static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1898 SourceManager &SM1, SourceManager &SM2) {
1899 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1900 FullSourceLoc{ Range2.getBegin(), SM2 });
1901 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1902 FullSourceLoc{ Range2.getEnd(), SM2 });
1903}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001904TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001905 Decl *FromTU = getTuDecl(
1906 R"(
1907 #define MFOO(arg) arg = arg + 1
1908
1909 void foo() {
1910 int a = 5;
1911 MFOO(a);
1912 }
1913 )",
1914 Lang_CXX);
1915 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1916 auto ToD = Import(FromD, Lang_CXX);
1917
1918 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1919 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1920 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1921 auto FromRHS =
1922 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1923
1924 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1925 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1926 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1927 FromSM);
1928 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1929 FromSM);
1930 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1931 FromSM);
1932}
1933
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001934TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001935 Decl *FromTU = getTuDecl(
1936 R"(
1937 #define FUNC_INT void declToImport
1938 #define FUNC FUNC_INT
1939 FUNC(int a);
1940 )",
1941 Lang_CXX);
1942 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1943 auto ToD = Import(FromD, Lang_CXX);
1944
1945 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1946 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1947 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1948 FromSM);
1949}
1950
Gabor Marton9581c332018-05-23 13:53:36 +00001951TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001952 ASTImporterOptionSpecificTestBase,
1953 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001954 Decl *ToTU = getToTuDecl(
1955 R"(
1956 template <typename T>
1957 struct B;
1958
1959 template <>
1960 struct B<int> {};
1961
1962 template <>
1963 struct B<int>;
1964 )",
1965 Lang_CXX);
1966 // We should have only one definition.
1967 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1968 [](const ClassTemplateSpecializationDecl *T) {
1969 return T->isThisDeclarationADefinition();
1970 })
1971 .match(ToTU, classTemplateSpecializationDecl()));
1972
1973 Decl *FromTU = getTuDecl(
1974 R"(
1975 template <typename T>
1976 struct B;
1977
1978 template <>
1979 struct B<int> {};
1980 )",
1981 Lang_CXX, "input1.cc");
1982 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1983 FromTU, classTemplateSpecializationDecl(hasName("B")));
1984
1985 Import(FromD, Lang_CXX);
1986
1987 // We should have only one definition.
1988 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1989 [](const ClassTemplateSpecializationDecl *T) {
1990 return T->isThisDeclarationADefinition();
1991 })
1992 .match(ToTU, classTemplateSpecializationDecl()));
1993}
1994
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001995TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001996 Decl *FromTU = getTuDecl(
1997 R"(
1998 struct { int a; int b; } object0 = { 2, 3 };
1999 struct { int x; int y; int z; } object1;
2000 )",
2001 Lang_CXX, "input0.cc");
2002
Gabor Marton0bebf952018-07-05 09:51:13 +00002003 auto *Obj0 =
2004 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
2005 auto *From0 = getRecordDecl(Obj0);
2006 auto *Obj1 =
2007 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
2008 auto *From1 = getRecordDecl(Obj1);
2009
2010 auto *To0 = Import(From0, Lang_CXX);
2011 auto *To1 = Import(From1, Lang_CXX);
2012
2013 EXPECT_TRUE(To0);
2014 EXPECT_TRUE(To1);
2015 EXPECT_NE(To0, To1);
2016 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
2017}
2018
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002019TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00002020 auto *Code =
2021 R"(
2022 struct X {
2023 struct { int a; };
2024 struct { int b; };
2025 };
2026 )";
2027 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
2028
2029 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
2030
2031 auto *X0 =
2032 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
2033 auto *X1 =
2034 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
2035 Import(X0, Lang_C);
2036 Import(X1, Lang_C);
2037
2038 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2039 // We expect no (ODR) warning during the import.
2040 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
2041 EXPECT_EQ(1u,
2042 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
2043}
2044
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002045TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00002046 Decl *FromTU0 = getTuDecl(
2047 R"(
2048 struct X {
2049 struct { int a; };
2050 struct { int b; };
2051 };
2052 )",
2053 Lang_C, "input0.c");
2054
2055 Decl *FromTU1 = getTuDecl(
2056 R"(
2057 struct X { // reversed order
2058 struct { int b; };
2059 struct { int a; };
2060 };
2061 )",
2062 Lang_C, "input1.c");
2063
2064 auto *X0 =
2065 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
2066 auto *X1 =
2067 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
2068 Import(X0, Lang_C);
2069 Import(X1, Lang_C);
2070
2071 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2072 // We expect one (ODR) warning during the import.
2073 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
2074 EXPECT_EQ(2u,
2075 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
2076}
2077
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002078TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00002079 auto Pattern = varDecl(hasName("x"));
2080 VarDecl *Imported1;
2081 {
2082 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
2083 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2084 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
2085 }
2086 VarDecl *Imported2;
2087 {
2088 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
2089 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2090 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2091 }
2092 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
2093 EXPECT_FALSE(Imported2->isUsed(false));
2094 {
2095 Decl *FromTU =
2096 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00002097 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2098 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00002099 Import(FromD, Lang_CXX);
2100 }
2101 EXPECT_TRUE(Imported2->isUsed(false));
2102}
2103
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002104TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00002105 auto Pattern = varDecl(hasName("x"));
2106 VarDecl *ExistingD;
2107 {
2108 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
2109 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2110 }
2111 EXPECT_FALSE(ExistingD->isUsed(false));
2112 {
2113 Decl *FromTU = getTuDecl(
2114 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
2115 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2116 FromTU, functionDecl(hasName("f")));
2117 Import(FromD, Lang_CXX);
2118 }
2119 EXPECT_TRUE(ExistingD->isUsed(false));
2120}
2121
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002122TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00002123 auto Pattern = varDecl(hasName("a"));
2124 VarDecl *ExistingD;
2125 {
2126 Decl *ToTU = getToTuDecl(
2127 R"(
2128 struct A {
2129 static const int a = 1;
2130 };
2131 )", Lang_CXX);
2132 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2133 }
2134 EXPECT_FALSE(ExistingD->isUsed(false));
2135 {
2136 Decl *FromTU = getTuDecl(
2137 R"(
2138 struct A {
2139 static const int a = 1;
2140 };
2141 const int *f() { return &A::a; } // requires storage,
2142 // thus used flag will be set
2143 )", Lang_CXX, "input1.cc");
2144 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
2145 FromTU, functionDecl(hasName("f")));
2146 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2147 ASSERT_TRUE(FromD->isUsed(false));
2148 Import(FromFunD, Lang_CXX);
2149 }
2150 EXPECT_TRUE(ExistingD->isUsed(false));
2151}
2152
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002153TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00002154 auto Pattern = varDecl(hasName("x"));
2155
2156 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
2157 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2158
2159 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
2160
2161 ASSERT_FALSE(Imported1->isUsed(false));
2162
2163 FromD->setIsUsed();
2164 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2165
2166 EXPECT_EQ(Imported1, Imported2);
2167 EXPECT_TRUE(Imported2->isUsed(false));
2168}
2169
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002170struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00002171
Gabor Marton5254e642018-06-27 13:32:50 +00002172TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002173 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2174 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002175 auto *From =
2176 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002177
Gabor Marton5254e642018-06-27 13:32:50 +00002178 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002179 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2180
Gabor Marton5254e642018-06-27 13:32:50 +00002181 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2182 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2183 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2184 EXPECT_TRUE(ImportedD == To0);
2185 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2186 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2187 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002188}
2189
2190TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2191 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2192 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002193 auto *From =
2194 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002195
Gabor Marton5254e642018-06-27 13:32:50 +00002196 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002197 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2198
Gabor Marton5254e642018-06-27 13:32:50 +00002199 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2200 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2201 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2202 EXPECT_TRUE(ImportedD == To1);
2203 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2204 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2205 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002206}
2207
Peter Szecsidedda6f2018-03-30 22:03:29 +00002208TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2209 auto Code =
2210 R"(
2211 struct B { virtual void f(); };
2212 void B::f() {}
2213 struct D : B { void f(); };
2214 )";
2215 auto Pattern =
2216 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2217 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2218 CXXMethodDecl *Proto =
2219 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2220
2221 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2222 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2223 EXPECT_EQ(To->size_overridden_methods(), 1u);
2224}
2225
2226TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2227 auto Code =
2228 R"(
2229 struct B { virtual void f(); };
2230 void B::f() {}
2231 )";
2232 auto Pattern =
2233 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2234 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2235 CXXMethodDecl *Proto =
2236 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2237 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2238
2239 ASSERT_TRUE(Proto->isVirtual());
2240 ASSERT_TRUE(Def->isVirtual());
2241 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2242 EXPECT_TRUE(To->isVirtual());
2243}
2244
Gabor Marton5254e642018-06-27 13:32:50 +00002245TEST_P(ImportFunctions,
2246 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2247 Decl *ToTU = getToTuDecl(
2248 R"(
2249 void f() {}
2250 void f();
2251 )",
2252 Lang_CXX);
2253 ASSERT_EQ(1u,
2254 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2255 return FD->doesThisDeclarationHaveABody();
2256 }).match(ToTU, functionDecl()));
2257
2258 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2259 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2260
2261 Import(FromD, Lang_CXX);
2262
2263 EXPECT_EQ(1u,
2264 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2265 return FD->doesThisDeclarationHaveABody();
2266 }).match(ToTU, functionDecl()));
2267}
2268
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002269TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2270 auto Code =
2271 R"(
2272 struct B { virtual void f(); };
2273 struct D:B { void f(); };
2274 )";
2275 auto BFP =
2276 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2277 auto DFP =
2278 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2279
2280 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2281 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2282 Import(DF, Lang_CXX);
2283
2284 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2285 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2286 Import(BF, Lang_CXX);
2287
2288 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2289
2290 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2291 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2292}
2293
2294TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2295 auto CodeWithoutDef =
2296 R"(
2297 struct B { virtual void f(); };
2298 struct D:B { void f(); };
2299 )";
2300 auto CodeWithDef =
2301 R"(
2302 struct B { virtual void f(){}; };
2303 struct D:B { void f(){}; };
2304 )";
2305 auto BFP =
2306 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2307 auto DFP =
2308 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2309 auto BFDefP = cxxMethodDecl(
2310 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2311 auto DFDefP = cxxMethodDecl(
2312 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2313 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2314
2315 {
2316 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2317 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2318 Import(FromD, Lang_CXX);
2319 }
2320 {
2321 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2322 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2323 Import(FromB, Lang_CXX);
2324 }
2325
2326 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2327
2328 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2329 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2330 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2331 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2332 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2333}
2334
2335TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2336 auto Code =
2337 R"(
2338 struct B { virtual void f(); };
2339 struct D:B { void f(); };
2340 void B::f(){};
2341 )";
2342
2343 auto BFP =
2344 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2345 auto BFDefP = cxxMethodDecl(
2346 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2347 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2348 unless(isDefinition()));
2349
2350 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2351 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2352 Import(D, Lang_CXX);
2353
2354 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2355 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2356 Import(B, Lang_CXX);
2357
2358 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2359
2360 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2361 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2362
2363 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2364 ToTU, cxxRecordDecl(hasName("B")));
2365 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2366 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2367 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2368
2369 // The definition should be out-of-class.
2370 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2371 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2372 ToBFOutOfClass->getLexicalDeclContext());
2373 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2374 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2375
2376 // Check that the redecl chain is intact.
2377 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2378}
2379
2380TEST_P(ImportFunctions,
2381 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2382 auto CodeTU0 =
2383 R"(
2384 struct B { virtual void f(); };
2385 struct D:B { void f(); };
2386 )";
2387 auto CodeTU1 =
2388 R"(
2389 struct B { virtual void f(); };
2390 struct D:B { void f(); };
2391 void B::f(){}
2392 void D::f(){}
2393 void foo(B &b, D &d) { b.f(); d.f(); }
2394 )";
2395
2396 auto BFP =
2397 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2398 auto BFDefP = cxxMethodDecl(
2399 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2400 auto DFP =
2401 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2402 auto DFDefP = cxxMethodDecl(
2403 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2404 auto FooDef = functionDecl(hasName("foo"));
2405
2406 {
2407 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2408 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2409 Import(D, Lang_CXX);
2410 }
2411
2412 {
2413 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2414 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2415 Import(Foo, Lang_CXX);
2416 }
2417
2418 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2419
2420 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2421 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2422 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2423 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2424
2425 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2426 ToTU, cxxRecordDecl(hasName("B")));
2427 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2428 ToTU, cxxRecordDecl(hasName("D")));
2429 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2430 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2431 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2432 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2433 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2434 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2435
2436 // The definition should be out-of-class.
2437 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2438 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2439 ToBFOutOfClass->getLexicalDeclContext());
2440 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2441 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2442
2443 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2444 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2445 ToDFOutOfClass->getLexicalDeclContext());
2446 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2447 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2448
2449 // Check that the redecl chain is intact.
2450 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2451 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2452}
2453
Gabor Marton458d1452019-02-14 13:07:03 +00002454//FIXME Move these tests to a separate test file.
2455namespace TypeAndValueParameterizedTests {
2456
2457// Type parameters for type-parameterized test fixtures.
2458struct GetFunPattern {
2459 using DeclTy = FunctionDecl;
2460 BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
2461};
2462struct GetVarPattern {
2463 using DeclTy = VarDecl;
2464 BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
2465};
2466
2467// Values for the value-parameterized test fixtures.
2468// FunctionDecl:
2469auto *ExternF = "void f();";
2470auto *StaticF = "static void f();";
2471auto *AnonF = "namespace { void f(); }";
2472// VarDecl:
2473auto *ExternV = "extern int v;";
2474auto *StaticV = "static int v;";
2475auto *AnonV = "namespace { extern int v; }";
2476
2477// First value in tuple: Compile options.
2478// Second value in tuple: Source code to be used in the test.
2479using ImportVisibilityChainParams =
2480 ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
2481// Fixture to test the redecl chain of Decls with the same visibility. Gtest
2482// makes it possible to have either value-parameterized or type-parameterized
2483// fixtures. However, we cannot have both value- and type-parameterized test
2484// fixtures. This is a value-parameterized test fixture in the gtest sense. We
2485// intend to mimic gtest's type-parameters via the PatternFactory template
2486// parameter. We manually instantiate the different tests with the each types.
2487template <typename PatternFactory>
2488class ImportVisibilityChain
2489 : public ASTImporterTestBase, public ImportVisibilityChainParams {
2490protected:
2491 using DeclTy = typename PatternFactory::DeclTy;
2492 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2493 std::string getCode() const { return std::get<1>(GetParam()); }
2494 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2495
2496 // Type-parameterized test.
2497 void TypedTest_ImportChain() {
2498 std::string Code = getCode() + getCode();
2499 auto Pattern = getPattern();
2500
2501 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
2502
2503 auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
2504 auto *FromF1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
2505
2506 auto *ToF0 = Import(FromF0, Lang_CXX);
2507 auto *ToF1 = Import(FromF1, Lang_CXX);
2508
2509 EXPECT_TRUE(ToF0);
2510 ASSERT_TRUE(ToF1);
2511 EXPECT_NE(ToF0, ToF1);
2512 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2513 }
2514};
2515
2516// Manual instantiation of the fixture with each type.
2517using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
2518using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
2519// Value-parameterized test for the first type.
2520TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
2521 TypedTest_ImportChain();
2522}
2523// Value-parameterized test for the second type.
2524TEST_P(ImportVariablesVisibilityChain, ImportChain) {
2525 TypedTest_ImportChain();
2526}
2527
2528// Automatic instantiation of the value-parameterized tests.
2529INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
2530 ::testing::Combine(
2531 DefaultTestValuesForRunOptions,
2532 ::testing::Values(ExternF, StaticF, AnonF)), );
2533INSTANTIATE_TEST_CASE_P(
2534 ParameterizedTests, ImportVariablesVisibilityChain,
2535 ::testing::Combine(
2536 DefaultTestValuesForRunOptions,
2537 // There is no point to instantiate with StaticV, because in C++ we can
2538 // forward declare a variable only with the 'extern' keyword.
2539 // Consequently, each fwd declared variable has external linkage. This
2540 // is different in the C language where any declaration without an
2541 // initializer is a tentative definition, subsequent definitions may be
2542 // provided but they must have the same linkage. See also the test
2543 // ImportVariableChainInC which test for this special C Lang case.
2544 ::testing::Values(ExternV, AnonV)), );
2545
2546// First value in tuple: Compile options.
2547// Second value in tuple: Tuple with informations for the test.
2548// Code for first import (or initial code), code to import, whether the `f`
2549// functions are expected to be linked in a declaration chain.
2550// One value of this tuple is combined with every value of compile options.
2551// The test can have a single tuple as parameter only.
2552using ImportVisibilityParams = ::testing::WithParamInterface<
2553 std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
2554
2555template <typename PatternFactory>
2556class ImportVisibility
2557 : public ASTImporterTestBase,
2558 public ImportVisibilityParams {
2559protected:
2560 using DeclTy = typename PatternFactory::DeclTy;
2561 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2562 std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
2563 std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
2564 bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
2565 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2566
2567 void TypedTest_ImportAfter() {
2568 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
2569 TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2570
2571 auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
2572 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
2573
2574 auto *ToF1 = Import(FromF1, Lang_CXX);
2575
2576 ASSERT_TRUE(ToF0);
2577 ASSERT_TRUE(ToF1);
2578 EXPECT_NE(ToF0, ToF1);
2579
2580 if (shouldBeLinked())
2581 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2582 else
2583 EXPECT_FALSE(ToF1->getPreviousDecl());
2584 }
2585
2586 void TypedTest_ImportAfterImport() {
2587 TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
2588 TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2589 auto *FromF0 =
2590 FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
2591 auto *FromF1 =
2592 FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
2593 auto *ToF0 = Import(FromF0, Lang_CXX);
2594 auto *ToF1 = Import(FromF1, Lang_CXX);
2595 ASSERT_TRUE(ToF0);
2596 ASSERT_TRUE(ToF1);
2597 EXPECT_NE(ToF0, ToF1);
2598 if (shouldBeLinked())
2599 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2600 else
2601 EXPECT_FALSE(ToF1->getPreviousDecl());
2602 }
2603};
2604using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
2605using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
2606
2607// FunctionDecl.
2608TEST_P(ImportFunctionsVisibility, ImportAfter) {
2609 TypedTest_ImportAfter();
2610}
2611TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
2612 TypedTest_ImportAfterImport();
2613}
2614// VarDecl.
2615TEST_P(ImportVariablesVisibility, ImportAfter) {
2616 TypedTest_ImportAfter();
2617}
2618TEST_P(ImportVariablesVisibility, ImportAfterImport) {
2619 TypedTest_ImportAfterImport();
2620}
2621
2622bool ExpectLink = true;
2623bool ExpectNotLink = false;
2624
2625INSTANTIATE_TEST_CASE_P(
2626 ParameterizedTests, ImportFunctionsVisibility,
2627 ::testing::Combine(
2628 DefaultTestValuesForRunOptions,
2629 ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
2630 std::make_tuple(ExternF, StaticF, ExpectNotLink),
2631 std::make_tuple(ExternF, AnonF, ExpectNotLink),
2632 std::make_tuple(StaticF, ExternF, ExpectNotLink),
2633 std::make_tuple(StaticF, StaticF, ExpectNotLink),
2634 std::make_tuple(StaticF, AnonF, ExpectNotLink),
2635 std::make_tuple(AnonF, ExternF, ExpectNotLink),
2636 std::make_tuple(AnonF, StaticF, ExpectNotLink),
2637 std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
2638INSTANTIATE_TEST_CASE_P(
2639 ParameterizedTests, ImportVariablesVisibility,
2640 ::testing::Combine(
2641 DefaultTestValuesForRunOptions,
2642 ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
2643 std::make_tuple(ExternV, StaticV, ExpectNotLink),
2644 std::make_tuple(ExternV, AnonV, ExpectNotLink),
2645 std::make_tuple(StaticV, ExternV, ExpectNotLink),
2646 std::make_tuple(StaticV, StaticV, ExpectNotLink),
2647 std::make_tuple(StaticV, AnonV, ExpectNotLink),
2648 std::make_tuple(AnonV, ExternV, ExpectNotLink),
2649 std::make_tuple(AnonV, StaticV, ExpectNotLink),
2650 std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
2651
2652} // namespace TypeAndValueParameterizedTests
2653
2654TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2655 std::string Code = "static int v; static int v = 0;";
2656 auto Pattern = varDecl(hasName("v"));
2657
2658 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2659
2660 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2661 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2662
2663 auto *To0 = Import(From0, Lang_C);
2664 auto *To1 = Import(From1, Lang_C);
2665
2666 EXPECT_TRUE(To0);
2667 ASSERT_TRUE(To1);
2668 EXPECT_NE(To0, To1);
2669 EXPECT_EQ(To1->getPreviousDecl(), To0);
2670}
2671
2672TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2673 TranslationUnitDecl *FromTu = getTuDecl(
2674 "namespace NS0 { namespace { void f(); } }"
2675 "namespace NS1 { namespace { void f(); } }",
2676 Lang_CXX, "input0.cc");
2677 auto Pattern = functionDecl(hasName("f"));
2678
2679 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2680 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2681
2682 auto *ToF0 = Import(FromF0, Lang_CXX);
2683 auto *ToF1 = Import(FromF1, Lang_CXX);
2684
2685 EXPECT_TRUE(ToF0);
2686 ASSERT_TRUE(ToF1);
2687 EXPECT_NE(ToF0, ToF1);
2688 EXPECT_FALSE(ToF1->getPreviousDecl());
2689}
2690
2691TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2692 {
2693 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2694 Lang_CXX, "input0.cc");
2695 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2696 FromTU, functionDecl(hasName("g0")));
2697
2698 Import(FromD, Lang_CXX);
2699 }
2700 {
2701 Decl *FromTU =
2702 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2703 Lang_CXX, "input1.cc");
2704 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2705 FromTU, functionDecl(hasName("g1")));
2706 Import(FromD, Lang_CXX);
2707 }
2708
2709 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2710 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2711 2u);
2712}
2713
Gabor Marton302f3002019-02-15 12:04:05 +00002714TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2715 Decl *FromTU = getTuDecl(
2716 R"(
2717 void foo() {
2718 (void)[]() { ; };
2719 }
2720 )",
2721 Lang_CXX11);
2722 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2723 FromTU, functionDecl(hasName("foo")));
2724 auto *ToD = Import(FromD, Lang_CXX);
2725 EXPECT_TRUE(ToD);
2726 CXXRecordDecl *LambdaRec =
2727 cast<LambdaExpr>(cast<CStyleCastExpr>(
2728 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2729 ->getSubExpr())
2730 ->getLambdaClass();
2731 EXPECT_TRUE(LambdaRec->getDestructor());
2732}
2733
Gabor Marton5caba302019-03-07 13:38:20 +00002734TEST_P(ImportFunctions,
2735 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2736 Decl *FromTU = getTuDecl(
2737 R"(
2738 struct X {
2739 template <typename T>
2740 void foo(){}
2741 };
2742 void f() {
2743 X x;
2744 x.foo<int>();
2745 }
2746 )",
2747 Lang_CXX);
2748 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2749 FromTU, functionDecl(hasName("f")));
2750 auto *ToD = Import(FromD, Lang_CXX);
2751 EXPECT_TRUE(ToD);
2752 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2753 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2754}
2755
2756TEST_P(ImportFunctions,
2757 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2758 Decl *FromTU = getTuDecl(
2759 R"(
2760 struct X {
2761 template <typename T>
2762 void foo(){}
2763 };
2764 template <typename T>
2765 void f() {
2766 X x;
2767 x.foo<T>();
2768 }
2769 void g() {
2770 f<int>();
2771 }
2772 )",
2773 Lang_CXX);
2774 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2775 FromTU, functionDecl(hasName("g")));
2776 auto *ToD = Import(FromD, Lang_CXX);
2777 EXPECT_TRUE(ToD);
2778 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2779 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2780 ToTU, translationUnitDecl(hasDescendant(
2781 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2782}
2783
Gabor Marton5254e642018-06-27 13:32:50 +00002784struct ImportFriendFunctions : ImportFunctions {};
2785
2786TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2787 auto Pattern = functionDecl(hasName("f"));
2788
2789 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2790 "void f();",
2791 Lang_CXX,
2792 "input0.cc");
2793 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2794
2795 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2796 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2797 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2798 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2799 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2800 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2801 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2802}
2803
2804TEST_P(ImportFriendFunctions,
2805 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2806 auto Pattern = functionDecl(hasName("f"));
2807
2808 Decl *FromTU = getTuDecl("void f();"
2809 "struct X { friend void f(); };",
2810 Lang_CXX, "input0.cc");
2811 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2812
2813 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2814 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2815 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2816 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2817 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2818 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2819 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2820}
2821
2822TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2823 auto Pattern = functionDecl(hasName("f"));
2824
2825 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2826 "void f();",
2827 Lang_CXX,
2828 "input0.cc");
2829 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2830
2831 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2832 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2833 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2834 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2835 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2836 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2837 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2838}
2839
2840TEST_P(ImportFriendFunctions,
2841 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2842 auto Pattern = functionDecl(hasName("f"));
2843
2844 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2845 "void f(){}",
2846 Lang_CXX, "input0.cc");
2847 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2848
2849 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2850 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2851 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2852 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2853 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2854 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2855 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2856}
2857
Gabor Marton26f72a92018-07-12 09:42:05 +00002858// Disabled temporarily, because the new structural equivalence check
2859// (https://reviews.llvm.org/D48628) breaks it.
2860// PreviousDecl is not set because there is no structural match.
2861// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002862TEST_P(ImportFriendFunctions,
2863 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2864 auto Pattern = functionDecl(hasName("f"));
2865
2866 Decl *FromTU = getTuDecl(
2867 R"(
2868 class X;
2869 void f(X *x){}
2870 class X{
2871 friend void f(X *x);
2872 };
2873 )",
2874 Lang_CXX, "input0.cc");
2875 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2876
2877 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2878 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2879 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2880 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2881 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2882 .match(ToTU, friendDecl())
2883 ->getFriendDecl());
2884 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2885 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2886 // The parameters must refer the same type
2887 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2888 (*ImportedD->param_begin())->getOriginalType());
2889}
2890
Gabor Marton26f72a92018-07-12 09:42:05 +00002891// Disabled temporarily, because the new structural equivalence check
2892// (https://reviews.llvm.org/D48628) breaks it.
2893// PreviousDecl is not set because there is no structural match.
2894// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002895TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002896 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002897 auto Pattern = functionDecl(hasName("f"));
2898
2899 Decl *FromTU = getTuDecl(
2900 R"(
2901 class X;
2902 void f(X *x){}
2903 class X{
2904 friend void f(X *x);
2905 };
2906 )",
2907 Lang_CXX, "input0.cc");
2908 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2909
2910 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2911 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2912 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2913 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2914 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2915 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2916
2917 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2918 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2919 // The parameters must refer the same type
2920 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2921 (*ImportedD->param_begin())->getOriginalType());
2922}
2923
2924TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2925 auto Pattern = functionDecl(hasName("f"));
2926
2927 FunctionDecl *ImportedD;
2928 {
2929 Decl *FromTU =
2930 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2931 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2932 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2933 }
2934 FunctionDecl *ImportedD1;
2935 {
2936 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2937 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2938 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2939 }
2940
2941 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2942 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2943 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2944 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2945 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2946}
2947
Balazs Keri89632b82018-08-21 14:32:21 +00002948TEST_P(ImportFriendFunctions, Lookup) {
2949 auto FunctionPattern = functionDecl(hasName("f"));
2950 auto ClassPattern = cxxRecordDecl(hasName("X"));
2951
2952 TranslationUnitDecl *FromTU =
2953 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2954 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2955 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2956 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2957 {
2958 auto FromName = FromD->getDeclName();
2959 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2960 auto LookupRes = Class->noload_lookup(FromName);
2961 ASSERT_EQ(LookupRes.size(), 0u);
2962 LookupRes = FromTU->noload_lookup(FromName);
2963 ASSERT_EQ(LookupRes.size(), 1u);
2964 }
2965
2966 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2967 auto ToName = ToD->getDeclName();
2968
2969 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2970 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2971 auto LookupRes = Class->noload_lookup(ToName);
2972 EXPECT_EQ(LookupRes.size(), 0u);
2973 LookupRes = ToTU->noload_lookup(ToName);
2974 EXPECT_EQ(LookupRes.size(), 1u);
2975
2976 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2977 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2978 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2979 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2980}
2981
2982TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2983 auto FunctionPattern = functionDecl(hasName("f"));
2984 auto ClassPattern = cxxRecordDecl(hasName("X"));
2985
2986 TranslationUnitDecl *FromTU = getTuDecl(
2987 "struct X { friend void f(); };"
2988 // This proto decl makes f available to normal
2989 // lookup, otherwise it is hidden.
2990 // Normal C++ lookup (implemented in
2991 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2992 // returns the found `NamedDecl` only if the set IDNS is matched
2993 "void f();",
2994 Lang_CXX, "input0.cc");
2995 auto *FromFriend =
2996 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2997 auto *FromNormal =
2998 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2999 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3000 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3001 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3002 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3003
3004 auto FromName = FromFriend->getDeclName();
3005 auto *FromClass =
3006 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
3007 auto LookupRes = FromClass->noload_lookup(FromName);
3008 ASSERT_EQ(LookupRes.size(), 0u);
3009 LookupRes = FromTU->noload_lookup(FromName);
3010 ASSERT_EQ(LookupRes.size(), 1u);
3011
3012 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
3013 auto ToName = ToFriend->getDeclName();
3014
3015 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3016 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
3017 LookupRes = ToClass->noload_lookup(ToName);
3018 EXPECT_EQ(LookupRes.size(), 0u);
3019 LookupRes = ToTU->noload_lookup(ToName);
3020 // Test is disabled because this result is 2.
3021 EXPECT_EQ(LookupRes.size(), 1u);
3022
3023 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
3024 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
3025 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
3026 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3027 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3028 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3029 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3030}
3031
3032TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
3033 auto FunctionPattern = functionDecl(hasName("f"));
3034 auto ClassPattern = cxxRecordDecl(hasName("X"));
3035
3036 TranslationUnitDecl *FromTU = getTuDecl(
3037 "void f();"
3038 "struct X { friend void f(); };",
3039 Lang_CXX, "input0.cc");
3040 auto *FromNormal =
3041 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
3042 auto *FromFriend =
3043 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
3044 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3045 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3046 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3047 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3048
3049 auto FromName = FromNormal->getDeclName();
3050 auto *FromClass =
3051 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
3052 auto LookupRes = FromClass->noload_lookup(FromName);
3053 ASSERT_EQ(LookupRes.size(), 0u);
3054 LookupRes = FromTU->noload_lookup(FromName);
3055 ASSERT_EQ(LookupRes.size(), 1u);
3056
3057 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
3058 auto ToName = ToNormal->getDeclName();
3059 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3060
3061 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
3062 LookupRes = ToClass->noload_lookup(ToName);
3063 EXPECT_EQ(LookupRes.size(), 0u);
3064 LookupRes = ToTU->noload_lookup(ToName);
3065 EXPECT_EQ(LookupRes.size(), 1u);
3066
3067 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
3068 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
3069 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
3070 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3071 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3072 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3073 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3074}
3075
3076TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
3077 auto Pattern = functionDecl(hasName("f"));
3078
3079 TranslationUnitDecl *FromNormalTU =
3080 getTuDecl("void f();", Lang_CXX, "input0.cc");
3081 auto *FromNormalF =
3082 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
3083 TranslationUnitDecl *FromFriendTU =
3084 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
3085 auto *FromFriendF =
3086 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
3087 auto FromNormalName = FromNormalF->getDeclName();
3088 auto FromFriendName = FromFriendF->getDeclName();
3089
3090 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3091 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3092 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3093 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3094 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
3095 ASSERT_EQ(LookupRes.size(), 1u);
3096 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
3097 ASSERT_EQ(LookupRes.size(), 1u);
3098
3099 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
3100 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3101 auto ToName = ToNormalF->getDeclName();
3102 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3103 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3104 LookupRes = ToTU->noload_lookup(ToName);
3105 EXPECT_EQ(LookupRes.size(), 1u);
3106 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00003107
Balazs Keri89632b82018-08-21 14:32:21 +00003108 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
3109 LookupRes = ToTU->noload_lookup(ToName);
3110 EXPECT_EQ(LookupRes.size(), 1u);
3111 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3112
3113 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3114 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3115
3116 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3117 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3118}
3119
3120TEST_P(ImportFriendFunctions, ImportFriendList) {
3121 TranslationUnitDecl *FromTU = getTuDecl(
3122 "struct X { friend void f(); };"
3123 "void f();",
3124 Lang_CXX, "input0.cc");
3125 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
3126 FromTU, functionDecl(hasName("f")));
3127
3128 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3129 FromTU, cxxRecordDecl(hasName("X")));
3130 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
3131 auto FromFriends = FromClass->friends();
3132 unsigned int FrN = 0;
3133 for (auto Fr : FromFriends) {
3134 ASSERT_EQ(Fr, FromFriend);
3135 ++FrN;
3136 }
3137 ASSERT_EQ(FrN, 1u);
3138
3139 Import(FromFriendF, Lang_CXX);
3140 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3141 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3142 ToTU, cxxRecordDecl(hasName("X")));
3143 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
3144 auto ToFriends = ToClass->friends();
3145 FrN = 0;
3146 for (auto Fr : ToFriends) {
3147 EXPECT_EQ(Fr, ToFriend);
3148 ++FrN;
3149 }
3150 EXPECT_EQ(FrN, 1u);
3151}
3152
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00003153AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
3154 InnerMatcher) {
3155 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
3156 return InnerMatcher.matches(*Typedef, Finder, Builder);
3157 return false;
3158}
3159
Gabor Marton19f4f392018-06-25 13:04:37 +00003160TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00003161 CodeFiles Samples{{"main.c",
3162 {"void foo();"
3163 "void moo();"
3164 "int main() { foo(); moo(); }",
3165 Lang_C}},
3166
3167 {"foo.c",
3168 {"typedef enum { THING_VALUE } thing_t;"
3169 "void conflict(thing_t type);"
3170 "void foo() { (void)THING_VALUE; }"
3171 "void conflict(thing_t type) {}",
3172 Lang_C}},
3173
3174 {"moo.c",
3175 {"typedef enum { THING_VALUE } thing_t;"
3176 "void conflict(thing_t type);"
3177 "void moo() { conflict(THING_VALUE); }",
3178 Lang_C}}};
3179
3180 auto VerificationMatcher =
3181 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
3182 hasTypedefForAnonDecl(hasName("thing_t")));
3183
3184 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
3185 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
3186
3187 testImportSequence(
3188 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
3189 // Just check that there is only one enum decl in the result AST.
3190 "main.c", enumDecl(), VerificationMatcher);
3191
3192 // For different import order, result should be the same.
3193 testImportSequence(
3194 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
3195 // Check that there is only one enum decl in the result AST.
3196 "main.c", enumDecl(), VerificationMatcher);
3197}
3198
Peter Szecsice7f3182018-05-07 12:08:27 +00003199const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
3200 dependentScopeDeclRefExpr;
3201
Gabor Marton19f4f392018-06-25 13:04:37 +00003202TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003203 MatchVerifier<Decl> Verifier;
3204 testImport("template <typename T> struct S { static T foo; };"
3205 "template <typename T> void declToImport() {"
3206 " (void) S<T>::foo;"
3207 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00003208 "void instantiate() { declToImport<int>(); }"
3209 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00003210 Lang_CXX11, "", Lang_CXX11, Verifier,
3211 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3212 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
3213
3214 testImport("template <typename T> struct S {"
3215 "template<typename S> static void foo(){};"
3216 "};"
3217 "template <typename T> void declToImport() {"
3218 " S<T>::template foo<T>();"
3219 "}"
3220 "void instantiate() { declToImport<int>(); }",
3221 Lang_CXX11, "", Lang_CXX11, Verifier,
3222 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3223 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
3224}
3225
3226const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
3227 dependentNameType;
3228
Gabor Marton19f4f392018-06-25 13:04:37 +00003229TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003230 MatchVerifier<Decl> Verifier;
3231 testImport("template <typename T> struct declToImport {"
3232 " typedef typename T::type dependent_name;"
3233 "};",
3234 Lang_CXX11, "", Lang_CXX11, Verifier,
3235 classTemplateDecl(has(
3236 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
3237}
3238
Gabor Marton19f4f392018-06-25 13:04:37 +00003239TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003240 MatchVerifier<Decl> Verifier;
3241 testImport("struct S { template <typename T> void mem(); };"
3242 "template <typename U> void declToImport() {"
3243 " S s;"
3244 " s.mem<U>();"
3245 "}"
3246 "void instantiate() { declToImport<int>(); }",
3247 Lang_CXX11, "", Lang_CXX11, Verifier,
3248 functionTemplateDecl(has(functionDecl(has(
3249 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3250}
3251
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003252class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00003253public:
3254 static constexpr auto DefaultCode = R"(
3255 struct A { int x; };
3256 void f() {
3257 A a;
3258 A a1(a);
3259 A a2(A{});
3260 a = a1;
3261 a = A{};
3262 a.~A();
3263 })";
3264
3265 template <typename MatcherType>
3266 void testImportOf(
3267 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3268 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3269 }
3270
3271 template <typename MatcherType>
3272 void testNoImportOf(
3273 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3274 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3275 }
3276
3277private:
3278 template <typename MatcherType>
3279 void test(const MatcherType &MethodMatcher,
3280 const char *Code, unsigned int ExpectedCount) {
3281 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3282
3283 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3284 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3285 ToTU, ClassMatcher);
3286
Balazs Keri2f752ba2018-07-16 14:05:18 +00003287 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003288
3289 {
3290 CXXMethodDecl *Method =
3291 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3292 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00003293 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003294 }
3295
Balazs Keri2f752ba2018-07-16 14:05:18 +00003296 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003297
3298 Decl *ImportedClass = nullptr;
3299 {
3300 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3301 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3302 FromTU, ClassMatcher);
3303 ImportedClass = Import(FromClass, Lang_CXX11);
3304 }
3305
3306 EXPECT_EQ(ToClass, ImportedClass);
3307 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3308 ExpectedCount);
3309 }
3310};
3311
3312TEST_P(ImportImplicitMethods, DefaultConstructor) {
3313 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3314}
3315
3316TEST_P(ImportImplicitMethods, CopyConstructor) {
3317 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3318}
3319
3320TEST_P(ImportImplicitMethods, MoveConstructor) {
3321 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3322}
3323
3324TEST_P(ImportImplicitMethods, Destructor) {
3325 testImportOf(cxxDestructorDecl());
3326}
3327
3328TEST_P(ImportImplicitMethods, CopyAssignment) {
3329 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3330}
3331
3332TEST_P(ImportImplicitMethods, MoveAssignment) {
3333 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3334}
3335
3336TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3337 auto Code = R"(
3338 struct A { A() { int x; } };
3339 )";
3340 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3341}
3342
3343TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3344 auto Code = R"(
3345 struct A { A() = default; };
3346 )";
3347 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3348}
3349
3350TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3351 auto Code = R"(
3352 struct A { A() = delete; };
3353 )";
3354 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3355}
3356
3357TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3358 auto Code = R"(
3359 struct A { void f() { } };
3360 )";
3361 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3362}
3363
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003364TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003365 Decl *ToR1;
3366 {
3367 Decl *FromTU = getTuDecl(
3368 "struct A { };", Lang_CXX, "input0.cc");
3369 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3370 FromTU, cxxRecordDecl(hasName("A")));
3371
3372 ToR1 = Import(FromR, Lang_CXX);
3373 }
3374
3375 Decl *ToR2;
3376 {
3377 Decl *FromTU = getTuDecl(
3378 "struct A { };", Lang_CXX, "input1.cc");
3379 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3380 FromTU, cxxRecordDecl(hasName("A")));
3381
3382 ToR2 = Import(FromR, Lang_CXX);
3383 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003384
Balazs Keric7797c42018-07-11 09:37:24 +00003385 EXPECT_EQ(ToR1, ToR2);
3386}
3387
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003388TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003389 Decl *ToR1;
3390 {
3391 Decl *FromTU = getTuDecl(
3392 "struct A { int x; };", Lang_CXX, "input0.cc");
3393 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3394 FromTU, cxxRecordDecl(hasName("A")));
3395 ToR1 = Import(FromR, Lang_CXX);
3396 }
3397 Decl *ToR2;
3398 {
3399 Decl *FromTU = getTuDecl(
3400 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3401 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3402 FromTU, cxxRecordDecl(hasName("A")));
3403 ToR2 = Import(FromR, Lang_CXX);
3404 }
3405 EXPECT_NE(ToR1, ToR2);
3406}
3407
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003408TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003409 Decl *ToF1;
3410 {
3411 Decl *FromTU = getTuDecl(
3412 "struct A { int x; };", Lang_CXX, "input0.cc");
3413 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3414 FromTU, fieldDecl(hasName("x")));
3415 ToF1 = Import(FromF, Lang_CXX);
3416 }
3417 Decl *ToF2;
3418 {
3419 Decl *FromTU = getTuDecl(
3420 "struct A { int x; };", Lang_CXX, "input1.cc");
3421 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3422 FromTU, fieldDecl(hasName("x")));
3423 ToF2 = Import(FromF, Lang_CXX);
3424 }
3425 EXPECT_EQ(ToF1, ToF2);
3426}
3427
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003428TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003429 Decl *ToF1;
3430 {
3431 Decl *FromTU = getTuDecl(
3432 "struct A { int x; };", Lang_CXX, "input0.cc");
3433 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3434 FromTU, fieldDecl(hasName("x")));
3435 ToF1 = Import(FromF, Lang_CXX);
3436 }
3437 Decl *ToF2;
3438 {
3439 Decl *FromTU = getTuDecl(
3440 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3441 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3442 FromTU, fieldDecl(hasName("x")));
3443 ToF2 = Import(FromF, Lang_CXX);
3444 }
3445 EXPECT_NE(ToF1, ToF2);
3446}
3447
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003448TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003449 Decl *ToM1;
3450 {
3451 Decl *FromTU = getTuDecl(
3452 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3453 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3454 FromTU, functionDecl(hasName("x"), isDefinition()));
3455 ToM1 = Import(FromM, Lang_CXX);
3456 }
3457 Decl *ToM2;
3458 {
3459 Decl *FromTU = getTuDecl(
3460 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3461 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3462 FromTU, functionDecl(hasName("x"), isDefinition()));
3463 ToM2 = Import(FromM, Lang_CXX);
3464 }
3465 EXPECT_EQ(ToM1, ToM2);
3466}
3467
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003468TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003469 Decl *ToM1;
3470 {
3471 Decl *FromTU = getTuDecl(
3472 "struct A { void x(); }; void A::x() { }",
3473 Lang_CXX, "input0.cc");
3474 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3475 FromTU, functionDecl(hasName("x"), isDefinition()));
3476 ToM1 = Import(FromM, Lang_CXX);
3477 }
3478 Decl *ToM2;
3479 {
3480 Decl *FromTU = getTuDecl(
3481 "struct A { void x() const; }; void A::x() const { }",
3482 Lang_CXX, "input1.cc");
3483 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3484 FromTU, functionDecl(hasName("x"), isDefinition()));
3485 ToM2 = Import(FromM, Lang_CXX);
3486 }
3487 EXPECT_NE(ToM1, ToM2);
3488}
3489
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003490TEST_P(ASTImporterOptionSpecificTestBase,
3491 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003492 Decl *FromTU = getTuDecl(
3493 R"(
3494 struct A {
3495 struct {
3496 struct A *next;
3497 } entry0;
3498 struct {
3499 struct A *next;
3500 } entry1;
3501 };
3502 )",
3503 Lang_C, "input0.cc");
3504 auto *From =
3505 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3506
3507 Import(From, Lang_C);
3508
3509 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3510 auto *Entry0 =
3511 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3512 auto *Entry1 =
3513 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3514 auto *R0 = getRecordDecl(Entry0);
3515 auto *R1 = getRecordDecl(Entry1);
3516 EXPECT_NE(R0, R1);
3517 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3518 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3519 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3520 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3521}
3522
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003523TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003524 Decl *FromTU = getTuDecl(
3525 R"(
3526 void f(int X, int Y, bool Z) {
3527 (void)[X, Y, Z] { (void)Z; };
3528 }
3529 )",
3530 Lang_CXX11, "input0.cc");
3531 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3532 FromTU, functionDecl(hasName("f")));
3533 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3534 EXPECT_TRUE(ToF);
3535
3536 CXXRecordDecl *FromLambda =
3537 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3538 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3539
3540 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3541 EXPECT_TRUE(ToLambda);
3542
3543 // Check if the fields of the lambda class are imported in correct order.
3544 unsigned FromIndex = 0u;
3545 for (auto *FromField : FromLambda->fields()) {
3546 ASSERT_FALSE(FromField->getDeclName());
3547 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3548 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003549 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3550 EXPECT_TRUE(ToIndex);
3551 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003552 ++FromIndex;
3553 }
3554
3555 EXPECT_EQ(FromIndex, 3u);
3556}
3557
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003558TEST_P(ASTImporterOptionSpecificTestBase,
3559 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003560 std::string ClassTemplate =
3561 R"(
3562 template <typename T>
3563 struct X {
3564 int a{0}; // FieldDecl with InitListExpr
3565 X(char) : a(3) {} // (1)
3566 X(int) {} // (2)
3567 };
3568 )";
3569 Decl *ToTU = getToTuDecl(ClassTemplate +
3570 R"(
3571 void foo() {
3572 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3573 X<char> xc('c');
3574 }
3575 )", Lang_CXX11);
3576 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3577 ToTU, classTemplateSpecializationDecl(hasName("X")));
3578 // FieldDecl without InitlistExpr:
3579 auto *ToField = *ToSpec->field_begin();
3580 ASSERT_TRUE(ToField);
3581 ASSERT_FALSE(ToField->getInClassInitializer());
3582 Decl *FromTU = getTuDecl(ClassTemplate +
3583 R"(
3584 void bar() {
3585 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3586 X<char> xc(1);
3587 }
3588 )", Lang_CXX11);
3589 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3590 FromTU, classTemplateSpecializationDecl(hasName("X")));
3591 // FieldDecl with InitlistExpr:
3592 auto *FromField = *FromSpec->field_begin();
3593 ASSERT_TRUE(FromField);
3594 ASSERT_TRUE(FromField->getInClassInitializer());
3595
3596 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3597 ASSERT_TRUE(ImportedSpec);
3598 EXPECT_EQ(ImportedSpec, ToSpec);
3599 // After the import, the FieldDecl has to be merged, thus it should have the
3600 // InitListExpr.
3601 EXPECT_TRUE(ToField->getInClassInitializer());
3602}
3603
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003604TEST_P(ASTImporterOptionSpecificTestBase,
3605 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003606 std::string ClassTemplate =
3607 R"(
3608 template <typename T>
3609 struct X {
3610 void f() {}
3611 void g() {}
3612 };
3613 )";
3614 Decl *ToTU = getToTuDecl(ClassTemplate +
3615 R"(
3616 void foo() {
3617 X<char> x;
3618 x.f();
3619 }
3620 )", Lang_CXX11);
3621 Decl *FromTU = getTuDecl(ClassTemplate +
3622 R"(
3623 void bar() {
3624 X<char> x;
3625 x.g();
3626 }
3627 )", Lang_CXX11);
3628 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3629 FromTU, classTemplateSpecializationDecl(hasName("X")));
3630 auto FunPattern = functionDecl(hasName("g"),
3631 hasParent(classTemplateSpecializationDecl()));
3632 auto *FromFun =
3633 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3634 auto *ToFun =
3635 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3636 ASSERT_TRUE(FromFun->hasBody());
3637 ASSERT_FALSE(ToFun->hasBody());
3638 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3639 ASSERT_TRUE(ImportedSpec);
3640 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3641 ToTU, classTemplateSpecializationDecl(hasName("X")));
3642 EXPECT_EQ(ImportedSpec, ToSpec);
3643 EXPECT_TRUE(ToFun->hasBody());
3644}
3645
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003646TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003647 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3648 std::string ClassTemplate =
3649 R"(
3650 template <typename T>
3651 struct X {};
3652 )";
3653 Decl *ToTU = getToTuDecl(ClassTemplate +
3654 R"(
3655 template <>
3656 struct X<char> {
3657 int a;
3658 };
3659 void foo() {
3660 X<char> x;
3661 }
3662 )",
3663 Lang_CXX11);
3664 Decl *FromTU = getTuDecl(ClassTemplate +
3665 R"(
3666 template <>
3667 struct X<char> {
3668 int b;
3669 };
3670 void foo() {
3671 X<char> x;
3672 }
3673 )",
3674 Lang_CXX11);
3675 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3676 FromTU, classTemplateSpecializationDecl(hasName("X")));
3677 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3678
3679 // We expect one (ODR) warning during the import.
3680 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3681
3682 // The second specialization is different from the first, thus it violates
3683 // ODR, consequently we expect to keep the first specialization only, which is
3684 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003685 EXPECT_FALSE(ImportedSpec);
3686 EXPECT_EQ(1u,
3687 DeclCounter<ClassTemplateSpecializationDecl>().match(
3688 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003689}
3690
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003691TEST_P(ASTImporterOptionSpecificTestBase,
3692 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003693 std::string ClassTemplate =
3694 R"(
3695 template <typename T>
3696 struct X {
3697 X(char) {}
3698 X(int) {}
3699 };
3700 )";
3701 Decl *ToTU = getToTuDecl(ClassTemplate +
3702 R"(
3703 void foo() {
3704 X<char> x('c');
3705 }
3706 )", Lang_CXX11);
3707 Decl *FromTU = getTuDecl(ClassTemplate +
3708 R"(
3709 void bar() {
3710 X<char> x(1);
3711 }
3712 )", Lang_CXX11);
3713 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3714 FromTU, classTemplateSpecializationDecl(hasName("X")));
3715 // Match the void(int) ctor.
3716 auto CtorPattern =
3717 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3718 hasParent(classTemplateSpecializationDecl()));
3719 auto *FromCtor =
3720 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3721 auto *ToCtor =
3722 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3723 ASSERT_TRUE(FromCtor->hasBody());
3724 ASSERT_FALSE(ToCtor->hasBody());
3725 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3726 ASSERT_TRUE(ImportedSpec);
3727 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3728 ToTU, classTemplateSpecializationDecl(hasName("X")));
3729 EXPECT_EQ(ImportedSpec, ToSpec);
3730 EXPECT_TRUE(ToCtor->hasBody());
3731}
3732
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003733TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003734 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3735 auto Code =
3736 R"(
3737 // primary template
3738 template<class T1, class T2, int I>
3739 class A {};
3740
3741 // partial specialization
3742 template<class T, int I>
3743 class A<T, T*, I> {};
3744 )";
3745 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3746 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3747 auto *FromSpec =
3748 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3749 FromTU, classTemplatePartialSpecializationDecl());
3750 auto *ToSpec =
3751 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3752 ToTU, classTemplatePartialSpecializationDecl());
3753
3754 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3755 EXPECT_EQ(ImportedSpec, ToSpec);
3756 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3757 ToTU, classTemplatePartialSpecializationDecl()));
3758}
3759
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003760TEST_P(ASTImporterOptionSpecificTestBase,
3761 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003762 auto Code =
3763 R"(
3764 // primary template
3765 template<class T1, class T2, int I>
3766 class A {};
3767
3768 // full specialization
3769 template<>
3770 class A<int, int, 1> {};
3771 )";
3772 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3773 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3774 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3775 FromTU, classTemplateSpecializationDecl());
3776 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3777 ToTU, classTemplateSpecializationDecl());
3778
3779 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3780 EXPECT_EQ(ImportedSpec, ToSpec);
3781 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3782 ToTU, classTemplateSpecializationDecl()));
3783}
3784
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003785TEST_P(ASTImporterOptionSpecificTestBase,
3786 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003787 std::string PrimaryTemplate =
3788 R"(
3789 template<class T1, class T2, int I>
3790 class A {};
3791 )";
3792 auto PartialSpec =
3793 R"(
3794 template<class T, int I>
3795 class A<T, T*, I> {};
3796 )";
3797 auto FullSpec =
3798 R"(
3799 template<>
3800 class A<int, int, 1> {};
3801 )";
3802 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3803 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3804 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3805 FromTU, classTemplateSpecializationDecl());
3806
3807 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3808 EXPECT_TRUE(ImportedSpec);
3809 // Check the number of partial specializations.
3810 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3811 ToTU, classTemplatePartialSpecializationDecl()));
3812 // Check the number of full specializations.
3813 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3814 ToTU, classTemplateSpecializationDecl(
3815 unless(classTemplatePartialSpecializationDecl()))));
3816}
3817
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003818TEST_P(ASTImporterOptionSpecificTestBase,
3819 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003820 Decl *TU = getTuDecl(
3821 R"(
3822 const int &init();
3823 void foo() { const int &a{init()}; }
3824 )", Lang_CXX11, "input0.cc");
3825 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3826 ASSERT_TRUE(FromD->getAnyInitializer());
3827 auto *InitExpr = FromD->getAnyInitializer();
3828 ASSERT_TRUE(InitExpr);
3829 ASSERT_TRUE(InitExpr->isGLValue());
3830
3831 auto *ToD = Import(FromD, Lang_CXX11);
3832 EXPECT_TRUE(ToD);
3833 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3834 EXPECT_TRUE(ToInitExpr);
3835 EXPECT_TRUE(ToInitExpr->isGLValue());
3836}
3837
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003838struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003839
3840TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3841 Decl *FromTU = getTuDecl(
3842 R"(
3843 struct A {
3844 static const int a = 1 + 2;
3845 };
3846 const int A::a;
3847 )", Lang_CXX, "input1.cc");
3848
3849 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3850 FromTU, varDecl(hasName("a"))); // Decl with init
3851 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3852 FromTU, varDecl(hasName("a"))); // Decl with definition
3853 ASSERT_NE(FromDWithInit, FromDWithDef);
3854 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3855
3856 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3857 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3858 ASSERT_TRUE(ToD0);
3859 ASSERT_TRUE(ToD1);
3860 EXPECT_NE(ToD0, ToD1);
3861 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3862}
3863
3864TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3865 auto StructA =
3866 R"(
3867 struct A {
3868 static const int a = 1 + 2;
3869 };
3870 )";
3871 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3872 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3873 "input1.cc");
3874
3875 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3876 FromTU, varDecl(hasName("a"))); // Decl with init
3877 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3878 FromTU, varDecl(hasName("a"))); // Decl with definition
3879 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3880 ASSERT_TRUE(FromDWithInit->getInit());
3881 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3882 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3883 ASSERT_FALSE(FromDWithDef->getInit());
3884
3885 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3886 ToTU, varDecl(hasName("a"))); // Decl with init
3887 ASSERT_TRUE(ToD->getInit());
3888 ASSERT_FALSE(ToD->getDefinition());
3889
3890 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3891 EXPECT_TRUE(ImportedD->getAnyInitializer());
3892 EXPECT_TRUE(ImportedD->getDefinition());
3893}
3894
3895TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3896 auto StructA =
3897 R"(
3898 struct A {
3899 static const int a;
3900 };
3901 )";
3902 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3903 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3904 Lang_CXX, "input1.cc");
3905
3906 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3907 FromTU, varDecl(hasName("a")));
3908 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3909 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3910 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3911 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3912 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3913 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3914 ASSERT_TRUE(FromDWithDef->getInit());
3915
3916 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3917 ToTU, varDecl(hasName("a")));
3918 ASSERT_FALSE(ToD->getInit());
3919 ASSERT_FALSE(ToD->getDefinition());
3920
3921 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3922 EXPECT_TRUE(ImportedD->getAnyInitializer());
3923 EXPECT_TRUE(ImportedD->getDefinition());
3924}
3925
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003926struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003927
Gabor Marton54058b52018-12-17 13:53:12 +00003928TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3929 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3930 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3931 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3932 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3933 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3934
3935 Decl *ImportedDef = Import(FromDef, Lang_C);
3936
3937 EXPECT_NE(ImportedDef, ToProto);
3938 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3939 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3940 EXPECT_TRUE(ImportedDef == ToDef);
3941 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3942 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3943 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3944}
3945
3946TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3947 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3948 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3949 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3950 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3951 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3952
3953 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3954
3955 EXPECT_NE(ImportedDef, ToProto);
3956 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3957 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3958 EXPECT_TRUE(ImportedDef == ToDef);
3959 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3960 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3961 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3962}
3963
3964TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3965 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3966 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3967 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3968 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3969 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3970
3971 Decl *ImportedProto = Import(FromProto, Lang_C);
3972 Decl *ImportedDef = Import(FromDef, Lang_C);
3973 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3974
3975 EXPECT_NE(ImportedDef, ImportedProto);
3976 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3977 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3978 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3979 EXPECT_TRUE(ImportedDef == ToDef);
3980 EXPECT_TRUE(ImportedProto == ToProto);
3981 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3982 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3983 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3984}
3985
Gabor Martonfc03fc62019-02-18 11:09:56 +00003986// FIXME put these structs and the tests rely on them into their own separate
3987// test file!
3988struct Function {
3989 using DeclTy = FunctionDecl;
3990 static constexpr auto *Prototype = "void X();";
3991 static constexpr auto *Definition = "void X() {}";
3992 BindableMatcher<Decl> getPattern() {
3993 return functionDecl(hasName("X"), unless(isImplicit()));
3994 }
3995};
Gabor Marton7df342a2018-12-17 12:42:12 +00003996
Gabor Martonfc03fc62019-02-18 11:09:56 +00003997struct Class {
3998 using DeclTy = CXXRecordDecl;
3999 static constexpr auto *Prototype = "class X;";
4000 static constexpr auto *Definition = "class X {};";
4001 BindableMatcher<Decl> getPattern() {
4002 return cxxRecordDecl(hasName("X"), unless(isImplicit()));
4003 }
4004};
Gabor Marton7df342a2018-12-17 12:42:12 +00004005
Gabor Martonfc03fc62019-02-18 11:09:56 +00004006struct Variable {
4007 using DeclTy = VarDecl;
4008 static constexpr auto *Prototype = "extern int X;";
4009 static constexpr auto *Definition = "int X;";
4010 BindableMatcher<Decl> getPattern() {
4011 return varDecl(hasName("X"));
4012 }
4013};
Gabor Marton7df342a2018-12-17 12:42:12 +00004014
Gabor Martonfc03fc62019-02-18 11:09:56 +00004015struct FunctionTemplate {
4016 using DeclTy = FunctionTemplateDecl;
4017 static constexpr auto *Prototype = "template <class T> void X();";
4018 static constexpr auto *Definition =
4019 R"(
4020 template <class T> void X() {};
4021 // Explicit instantiation is a must because of -fdelayed-template-parsing:
4022 template void X<int>();
4023 )";
4024 BindableMatcher<Decl> getPattern() {
4025 return functionTemplateDecl(hasName("X"), unless(isImplicit()));
4026 }
4027};
Gabor Marton7df342a2018-12-17 12:42:12 +00004028
Gabor Martonfc03fc62019-02-18 11:09:56 +00004029struct ClassTemplate {
4030 using DeclTy = ClassTemplateDecl;
4031 static constexpr auto *Prototype = "template <class T> class X;";
4032 static constexpr auto *Definition = "template <class T> class X {};";
4033 BindableMatcher<Decl> getPattern() {
4034 return classTemplateDecl(hasName("X"), unless(isImplicit()));
4035 }
4036};
Gabor Marton7df342a2018-12-17 12:42:12 +00004037
Gabor Martonfc03fc62019-02-18 11:09:56 +00004038struct FunctionTemplateSpec {
4039 using DeclTy = FunctionDecl;
4040 static constexpr auto *Prototype =
4041 R"(
4042 // Proto of the primary template.
4043 template <class T>
4044 void X();
4045 // Proto of the specialization.
4046 template <>
4047 void X<int>();
4048 )";
4049 static constexpr auto *Definition =
4050 R"(
4051 // Proto of the primary template.
4052 template <class T>
4053 void X();
4054 // Specialization and definition.
4055 template <>
4056 void X<int>() {}
4057 )";
4058 BindableMatcher<Decl> getPattern() {
4059 return functionDecl(hasName("X"), isExplicitTemplateSpecialization());
4060 }
4061};
Gabor Marton7df342a2018-12-17 12:42:12 +00004062
Gabor Marton7f8c4002019-03-19 13:34:10 +00004063struct ClassTemplateSpec {
4064 using DeclTy = ClassTemplateSpecializationDecl;
4065 static constexpr auto *Prototype =
4066 R"(
4067 template <class T> class X;
4068 template <> class X<int>;
4069 )";
4070 static constexpr auto *Definition =
4071 R"(
4072 template <class T> class X;
4073 template <> class X<int> {};
4074 )";
4075 BindableMatcher<Decl> getPattern() {
4076 return classTemplateSpecializationDecl(hasName("X"), unless(isImplicit()));
4077 }
4078};
4079
Gabor Martonfc03fc62019-02-18 11:09:56 +00004080template <typename TypeParam>
4081struct RedeclChain : ASTImporterOptionSpecificTestBase {
Gabor Marton7df342a2018-12-17 12:42:12 +00004082
Gabor Martonfc03fc62019-02-18 11:09:56 +00004083 using DeclTy = typename TypeParam::DeclTy;
4084 std::string getPrototype() { return TypeParam::Prototype; }
4085 std::string getDefinition() { return TypeParam::Definition; }
4086 BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); }
Gabor Marton7df342a2018-12-17 12:42:12 +00004087
Gabor Martondd59d272019-03-19 14:04:50 +00004088 void CheckPreviousDecl(Decl *Prev, Decl *Current) {
4089 ASSERT_NE(Prev, Current);
4090 ASSERT_EQ(&Prev->getASTContext(), &Current->getASTContext());
4091 EXPECT_EQ(Prev->getCanonicalDecl(), Current->getCanonicalDecl());
4092
4093 // Templates.
4094 if (auto *PrevT = dyn_cast<TemplateDecl>(Prev)) {
4095 EXPECT_EQ(Current->getPreviousDecl(), Prev);
4096 auto *CurrentT = cast<TemplateDecl>(Current);
4097 ASSERT_TRUE(PrevT->getTemplatedDecl());
4098 ASSERT_TRUE(CurrentT->getTemplatedDecl());
4099 EXPECT_EQ(CurrentT->getTemplatedDecl()->getPreviousDecl(),
4100 PrevT->getTemplatedDecl());
4101 return;
4102 }
4103
4104 // Specializations.
4105 if (auto *PrevF = dyn_cast<FunctionDecl>(Prev)) {
4106 if (PrevF->getTemplatedKind() ==
4107 FunctionDecl::TK_FunctionTemplateSpecialization) {
4108 // There may be a hidden fwd spec decl before a spec decl.
4109 // In that case the previous visible decl can be reached through that
4110 // invisible one.
4111 EXPECT_THAT(Prev, testing::AnyOf(
4112 Current->getPreviousDecl(),
4113 Current->getPreviousDecl()->getPreviousDecl()));
4114 auto *ToTU = Prev->getTranslationUnitDecl();
4115 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4116 ToTU, functionTemplateDecl());
4117 auto *FirstSpecD = *(TemplateD->spec_begin());
4118 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), PrevF->getCanonicalDecl());
4119 return;
4120 }
4121 }
4122
4123 // The rest: Classes, Functions, etc.
4124 EXPECT_EQ(Current->getPreviousDecl(), Prev);
4125 }
4126
Gabor Martonfc03fc62019-02-18 11:09:56 +00004127 void
4128 TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() {
4129 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX);
4130 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4131 ASSERT_FALSE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004132
Gabor Martonfc03fc62019-02-18 11:09:56 +00004133 Decl *ImportedD = Import(FromD, Lang_CXX);
4134 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004135
Gabor Martonfc03fc62019-02-18 11:09:56 +00004136 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4137 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4138 EXPECT_TRUE(ImportedD == ToD);
4139 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
Simon Pilgrim85f61252019-04-30 10:57:02 +00004140 if (auto *ToT = dyn_cast<TemplateDecl>(ToD)) {
Gabor Martonfc03fc62019-02-18 11:09:56 +00004141 EXPECT_TRUE(ToT->getTemplatedDecl());
Simon Pilgrim85f61252019-04-30 10:57:02 +00004142 }
Gabor Martonfc03fc62019-02-18 11:09:56 +00004143 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004144
Gabor Martonfc03fc62019-02-18 11:09:56 +00004145 void TypedTest_DefinitionShouldBeImportedAsADefinition() {
4146 Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
4147 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4148 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004149
Gabor Martonfc03fc62019-02-18 11:09:56 +00004150 Decl *ImportedD = Import(FromD, Lang_CXX);
4151 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004152
Gabor Martonfc03fc62019-02-18 11:09:56 +00004153 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4154 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4155 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
Simon Pilgrim85f61252019-04-30 10:57:02 +00004156 if (auto *ToT = dyn_cast<TemplateDecl>(ToD)) {
Gabor Martonfc03fc62019-02-18 11:09:56 +00004157 EXPECT_TRUE(ToT->getTemplatedDecl());
Simon Pilgrim85f61252019-04-30 10:57:02 +00004158 }
Gabor Martonfc03fc62019-02-18 11:09:56 +00004159 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004160
Gabor Martonfc03fc62019-02-18 11:09:56 +00004161 void TypedTest_ImportPrototypeAfterImportedPrototype() {
4162 Decl *FromTU = getTuDecl(
4163 getPrototype() + getPrototype(), Lang_CXX);
4164 auto *From0 =
4165 FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4166 auto *From1 = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4167 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4168 ASSERT_FALSE(From1->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004169
Gabor Martonfc03fc62019-02-18 11:09:56 +00004170 Decl *Imported0 = Import(From0, Lang_CXX);
4171 Decl *Imported1 = Import(From1, Lang_CXX);
4172 Decl *ToTU = Imported0->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004173
Gabor Martonfc03fc62019-02-18 11:09:56 +00004174 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4175 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4176 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4177 EXPECT_TRUE(Imported0 == To0);
4178 EXPECT_TRUE(Imported1 == To1);
4179 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4180 EXPECT_FALSE(To1->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004181
4182 CheckPreviousDecl(To0, To1);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004183 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004184
Gabor Martonfc03fc62019-02-18 11:09:56 +00004185 void TypedTest_ImportDefinitionAfterImportedPrototype() {
4186 Decl *FromTU = getTuDecl(
4187 getPrototype() + getDefinition(), Lang_CXX);
4188 auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4189 auto *FromDef = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4190 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4191 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004192
Gabor Martonfc03fc62019-02-18 11:09:56 +00004193 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4194 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4195 Decl *ToTU = ImportedProto->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004196
Gabor Martonfc03fc62019-02-18 11:09:56 +00004197 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4198 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4199 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4200 EXPECT_TRUE(ImportedProto == ToProto);
4201 EXPECT_TRUE(ImportedDef == ToDef);
4202 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4203 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004204
4205 CheckPreviousDecl(ToProto, ToDef);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004206 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004207
Gabor Martonfc03fc62019-02-18 11:09:56 +00004208 void TypedTest_ImportPrototypeAfterImportedDefinition() {
4209 Decl *FromTU = getTuDecl(
4210 getDefinition() + getPrototype(), Lang_CXX);
4211 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4212 auto *FromProto = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4213 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4214 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004215
Gabor Martonfc03fc62019-02-18 11:09:56 +00004216 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4217 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4218 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4219
4220 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4221 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4222 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4223 EXPECT_TRUE(ImportedDef == ToDef);
4224 EXPECT_TRUE(ImportedProto == ToProto);
4225 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4226 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004227
4228 CheckPreviousDecl(ToDef, ToProto);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004229 }
4230
4231 void TypedTest_ImportPrototypes() {
4232 Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4233 Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4234 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4235 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4236 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4237 ASSERT_FALSE(From1->isThisDeclarationADefinition());
4238
4239 Decl *Imported0 = Import(From0, Lang_CXX);
4240 Decl *Imported1 = Import(From1, Lang_CXX);
4241 Decl *ToTU = Imported0->getTranslationUnitDecl();
4242
4243 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4244 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4245 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4246 EXPECT_TRUE(Imported0 == To0);
4247 EXPECT_TRUE(Imported1 == To1);
4248 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4249 EXPECT_FALSE(To1->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004250
4251 CheckPreviousDecl(To0, To1);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004252 }
4253
4254 void TypedTest_ImportDefinitions() {
4255 Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4256 Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4257 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4258 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4259 ASSERT_TRUE(From0->isThisDeclarationADefinition());
4260 ASSERT_TRUE(From1->isThisDeclarationADefinition());
4261
4262 Decl *Imported0 = Import(From0, Lang_CXX);
4263 Decl *Imported1 = Import(From1, Lang_CXX);
4264 Decl *ToTU = Imported0->getTranslationUnitDecl();
4265
4266 EXPECT_EQ(Imported0, Imported1);
4267 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4268 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4269 EXPECT_TRUE(Imported0 == To0);
4270 EXPECT_TRUE(To0->isThisDeclarationADefinition());
Simon Pilgrim85f61252019-04-30 10:57:02 +00004271 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0)) {
Gabor Martonfc03fc62019-02-18 11:09:56 +00004272 EXPECT_TRUE(ToT0->getTemplatedDecl());
Simon Pilgrim85f61252019-04-30 10:57:02 +00004273 }
Gabor Martonfc03fc62019-02-18 11:09:56 +00004274 }
4275
4276 void TypedTest_ImportDefinitionThenPrototype() {
4277 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4278 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4279 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4280 auto *FromProto =
4281 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4282 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4283 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4284
4285 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4286 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4287 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4288
4289 EXPECT_NE(ImportedDef, ImportedProto);
4290 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4291 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4292 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4293 EXPECT_TRUE(ImportedDef == ToDef);
4294 EXPECT_TRUE(ImportedProto == ToProto);
4295 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4296 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004297
4298 CheckPreviousDecl(ToDef, ToProto);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004299 }
4300
4301 void TypedTest_ImportPrototypeThenDefinition() {
4302 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4303 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4304 auto *FromProto =
4305 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4306 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4307 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4308 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4309
4310 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4311 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4312 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4313
4314 EXPECT_NE(ImportedDef, ImportedProto);
4315 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4316 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4317 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4318 EXPECT_TRUE(ImportedDef == ToDef);
4319 EXPECT_TRUE(ImportedProto == ToProto);
4320 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4321 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004322
4323 CheckPreviousDecl(ToProto, ToDef);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004324 }
4325
4326 void TypedTest_WholeRedeclChainIsImportedAtOnce() {
4327 Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
4328 auto *FromD = // Definition
4329 LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4330 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
4331
4332 Decl *ImportedD = Import(FromD, Lang_CXX);
4333 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4334
4335 // The whole redecl chain is imported at once.
4336 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4337 EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition());
4338 }
4339
4340 void TypedTest_ImportPrototypeThenProtoAndDefinition() {
4341 {
4342 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4343 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4344 Import(FromD, Lang_CXX);
4345 }
4346 {
4347 Decl *FromTU =
4348 getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc");
4349 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4350 Import(FromD, Lang_CXX);
4351 }
4352
4353 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4354
4355 ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u);
4356 DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4357 EXPECT_FALSE(ProtoD->isThisDeclarationADefinition());
4358
4359 DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4360 EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition());
4361
4362 EXPECT_TRUE(DefinitionD->getPreviousDecl());
4363 EXPECT_FALSE(
4364 DefinitionD->getPreviousDecl()->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004365
4366 CheckPreviousDecl(ProtoD, DefinitionD->getPreviousDecl());
Gabor Martonfc03fc62019-02-18 11:09:56 +00004367 }
4368};
4369
4370#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \
4371 NamePrefix, TestCase) \
4372 using BaseTemplate##TypeParam = BaseTemplate<TypeParam>; \
4373 TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \
4374 TypedTest_##TestCase(); \
4375 }
4376
4377ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4378 RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004379 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004380ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4381 RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004382 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004383ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4384 RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004385 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004386ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004387 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004388 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004389ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4390 RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004391 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004392ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4393 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004394 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004395ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4396 RedeclChain, ClassTemplateSpec, ,
4397 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004398
4399ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004400 RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004401ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004402 RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004403ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004404 RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004405ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004406 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004407 DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004408ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004409 RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004410ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4411 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004412 DefinitionShouldBeImportedAsADefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004413ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4414 RedeclChain, ClassTemplateSpec, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004415
4416ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004417 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004418ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004419 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004420ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004421 ImportPrototypeAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004422ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004423 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004424ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004425 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004426ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004427 ImportPrototypeAfterImportedPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004428ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4429 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004430
4431ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004432 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004433ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004434 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004435ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004436 ImportDefinitionAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004437ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004438 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004439ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004440 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004441ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004442 ImportDefinitionAfterImportedPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004443ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4444 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004445
4446ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004447 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004448ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004449 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004450ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004451 ImportPrototypeAfterImportedDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004452ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004453 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004454ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004455 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004456ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004457 ImportPrototypeAfterImportedDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004458ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4459 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004460
4461ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004462 ImportPrototypes)
Gabor Marton038100a2019-02-20 16:57:41 +00004463ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004464ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004465 ImportPrototypes)
Gabor Marton16d98c22019-03-07 13:01:51 +00004466ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4467 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004468ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004469 ImportPrototypes)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004470ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4471 ImportPrototypes)
Gabor Martondd59d272019-03-19 14:04:50 +00004472ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4473 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004474
4475ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004476 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004477ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004478 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004479ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004480 ImportDefinitions)
Gabor Marton16d98c22019-03-07 13:01:51 +00004481ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4482 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004483ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004484 ImportDefinitions)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004485ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4486 ImportDefinitions)
Gabor Martondd59d272019-03-19 14:04:50 +00004487ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4488 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004489
4490ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004491 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004492ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004493 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004494ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004495 ImportDefinitionThenPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004496ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004497 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004498ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004499 ImportDefinitionThenPrototype)
Gabor Martondd59d272019-03-19 14:04:50 +00004500ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004501 ImportDefinitionThenPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004502ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4503 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004504
4505ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004506 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004507ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004508 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004509ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004510 ImportPrototypeThenDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004511ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004512 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004513ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004514 ImportPrototypeThenDefinition)
Gabor Martondd59d272019-03-19 14:04:50 +00004515ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004516 ImportPrototypeThenDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004517ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4518 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004519
4520ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004521 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004522ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004523 WholeRedeclChainIsImportedAtOnce)
Gabor Marton16d98c22019-03-07 13:01:51 +00004524ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004525 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004526ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004527 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004528
4529ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004530 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004531ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004532 ImportPrototypeThenProtoAndDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004533ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004534 ImportPrototypeThenProtoAndDefinition)
Gabor Martondd59d272019-03-19 14:04:50 +00004535ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004536 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004537
4538INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction,
4539 DefaultTestValuesForRunOptions, );
4540INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass,
4541 DefaultTestValuesForRunOptions, );
4542INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable,
4543 DefaultTestValuesForRunOptions, );
4544INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
4545 DefaultTestValuesForRunOptions, );
4546INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
4547 DefaultTestValuesForRunOptions, );
4548INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
4549 DefaultTestValuesForRunOptions, );
Gabor Marton7f8c4002019-03-19 13:34:10 +00004550INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplateSpec,
4551 DefaultTestValuesForRunOptions, );
Gabor Martonfc03fc62019-02-18 11:09:56 +00004552
4553
Gabor Marton7df342a2018-12-17 12:42:12 +00004554
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004555struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00004556
4557TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4558 Decl *FromTU = getTuDecl(
4559 R"(
4560 class A {
4561 template <int I> class F {};
4562 class X {
4563 template <int I> friend class F;
4564 };
4565 };
4566 )",
4567 Lang_CXX, "input0.cc");
4568
4569 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4570 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4571 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4572 FromTU, cxxRecordDecl(hasName("F")));
4573
4574 ASSERT_TRUE(FromClass);
4575 ASSERT_TRUE(FromFriendClass);
4576 ASSERT_NE(FromClass, FromFriendClass);
4577 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4578 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4579 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4580 FromClass->getDescribedClassTemplate());
4581
4582 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
4583 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
4584
4585 EXPECT_TRUE(ToClass);
4586 EXPECT_TRUE(ToFriendClass);
4587 EXPECT_NE(ToClass, ToFriendClass);
4588 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4589 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4590 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4591 ToClass->getDescribedClassTemplate());
4592}
4593
4594TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4595 Decl *FromTu = getTuDecl(
4596 R"(
4597 class declToImport {
4598 friend class declToImport;
4599 };
4600 )",
4601 Lang_CXX, "input.cc");
4602
4603 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4604 FromTu, cxxRecordDecl(hasName("declToImport")));
4605 auto *ToD = Import(FromD, Lang_CXX);
4606 auto Pattern = cxxRecordDecl(has(friendDecl()));
4607 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4608 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4609}
4610
4611TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4612 Decl *FromTu = getTuDecl(
4613 R"(
4614 template<class A> class declToImport {
4615 template<class A1> friend class declToImport;
4616 };
4617 )",
4618 Lang_CXX, "input.cc");
4619
4620 auto *FromD =
4621 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
4622 auto *ToD = Import(FromD, Lang_CXX);
4623
4624 auto Pattern = classTemplateDecl(
4625 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4626 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4627 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4628
4629 auto *Class =
4630 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
4631 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4632 EXPECT_NE(Friend->getFriendDecl(), Class);
4633 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
4634}
4635
4636TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4637 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
4638
4639 ClassTemplateSpecializationDecl *Imported1;
4640 {
4641 Decl *FromTU = getTuDecl("template<class T> class X;"
4642 "struct Y { friend class X<int>; };",
4643 Lang_CXX, "input0.cc");
4644 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4645 FromTU, Pattern);
4646
4647 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4648 }
4649 ClassTemplateSpecializationDecl *Imported2;
4650 {
4651 Decl *FromTU = getTuDecl("template<class T> class X;"
4652 "template<> class X<int>{};"
4653 "struct Z { friend class X<int>; };",
4654 Lang_CXX, "input1.cc");
4655 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4656 FromTU, Pattern);
4657
4658 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4659 }
4660
4661 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4662 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4663 2u);
4664 ASSERT_TRUE(Imported2->getPreviousDecl());
4665 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4666}
4667
4668TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4669 Decl *FromTU0 = getTuDecl(
4670 R"(
4671 class X {
4672 class Y;
4673 };
4674 class X::Y {
4675 template <typename T>
4676 friend class F; // The decl context of F is the global namespace.
4677 };
4678 )",
4679 Lang_CXX, "input0.cc");
4680 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4681 FromTU0, classTemplateDecl(hasName("F")));
4682 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4683 Decl *FromTU1 = getTuDecl(
4684 R"(
4685 template <typename T>
4686 class F {};
4687 )",
4688 Lang_CXX, "input1.cc");
4689 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4690 FromTU1, classTemplateDecl(hasName("F")));
4691 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4692 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4693 Imported1->getTemplatedDecl()->getTypeForDecl());
4694}
4695
4696TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4697 Decl *From, *To;
4698 std::tie(From, To) =
4699 getImportedDecl("class declToImport {};", Lang_CXX,
4700 "class Y { friend class declToImport; };", Lang_CXX);
4701 auto *Imported = cast<CXXRecordDecl>(To);
4702
4703 EXPECT_TRUE(Imported->getPreviousDecl());
4704}
4705
4706TEST_P(ImportFriendClasses,
4707 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4708 Decl *ToTU = getToTuDecl(
4709 R"(
4710 class X {
4711 class Y;
4712 };
4713 class X::Y {
4714 template <typename T>
4715 friend class F; // The decl context of F is the global namespace.
4716 };
4717 )",
4718 Lang_CXX);
4719 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4720 ToTU, classTemplateDecl(hasName("F")));
4721 Decl *FromTU = getTuDecl(
4722 R"(
4723 template <typename T>
4724 class F {};
4725 )",
4726 Lang_CXX, "input0.cc");
4727 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4728 FromTU, classTemplateDecl(hasName("F")));
4729 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4730 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4731 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4732 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4733 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4734}
4735
4736TEST_P(ImportFriendClasses,
4737 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4738 Decl *FromTU0 = getTuDecl(
4739 R"(
4740 class X {
4741 class Y;
4742 };
4743 class X::Y {
4744 template <typename T>
4745 friend class F; // The decl context of F is the global namespace.
4746 };
4747 )",
4748 Lang_CXX, "input0.cc");
4749 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4750 FromTU0, classTemplateDecl(hasName("F")));
4751 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4752 Decl *FromTU1 = getTuDecl(
4753 R"(
4754 template <typename T>
4755 class F {};
4756 )",
4757 Lang_CXX, "input1.cc");
4758 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4759 FromTU1, classTemplateDecl(hasName("F")));
4760 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4761 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4762 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4763 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4764 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4765}
4766
4767TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4768 Decl *FromTU0 = getTuDecl(
4769 R"(
4770 class X {
4771 class Y;
4772 };
4773 class X::Y {
4774 friend class F; // The decl context of F is the global namespace.
4775 };
4776 )",
4777 Lang_CXX, "input0.cc");
4778 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4779 QualType FT = Friend->getFriendType()->getType();
4780 FT = FromTU0->getASTContext().getCanonicalType(FT);
4781 auto *Fwd = cast<TagType>(FT)->getDecl();
4782 auto *ImportedFwd = Import(Fwd, Lang_CXX);
4783 Decl *FromTU1 = getTuDecl(
4784 R"(
4785 class F {};
4786 )",
4787 Lang_CXX, "input1.cc");
4788 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4789 FromTU1, cxxRecordDecl(hasName("F")));
4790 auto *ImportedDef = Import(Definition, Lang_CXX);
4791 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4792 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4793}
4794
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004795TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00004796 auto *Code = R"(
4797 template <class T>
4798 struct X {
4799 friend void foo(){}
4800 };
4801 )";
4802 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4803 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4804 ToTU, functionDecl(hasName("foo")));
4805
4806 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4807 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4808 FromTU, functionDecl(hasName("foo")));
4809 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4810 EXPECT_EQ(ImportedFoo, ToFoo);
4811}
4812
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004813struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00004814
4815TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4816 Decl *TU = getTuDecl(
4817 R"(
4818 namespace NS {
4819
4820 template <typename T>
4821 struct S {};
4822 template struct S<int>;
4823
4824 inline namespace INS {
4825 template <typename T>
4826 struct S {};
4827 template struct S<int>;
4828 }
4829
4830 }
4831 )", Lang_CXX11, "input0.cc");
4832 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4833 TU, namespaceDecl());
4834 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4835 TU, classTemplateSpecializationDecl());
4836 ASSERT_TRUE(NS->containsDecl(Spec));
4837
4838 NS->removeDecl(Spec);
4839 EXPECT_FALSE(NS->containsDecl(Spec));
4840}
4841
Gabor Marton7df342a2018-12-17 12:42:12 +00004842TEST_P(DeclContextTest,
4843 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4844 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4845 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4846 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4847
4848 // Investigate the list.
4849 auto *DC = A0->getDeclContext();
4850 ASSERT_TRUE(DC->containsDecl(A0));
4851 ASSERT_TRUE(DC->containsDecl(A1));
4852
4853 // Investigate the lookup table.
4854 auto *Map = DC->getLookupPtr();
4855 ASSERT_TRUE(Map);
4856 auto I = Map->find(A0->getDeclName());
4857 ASSERT_NE(I, Map->end());
4858 StoredDeclsList &L = I->second;
4859 // The lookup table contains the most recent decl of A.
4860 ASSERT_NE(L.getAsDecl(), A0);
4861 ASSERT_EQ(L.getAsDecl(), A1);
4862
4863 ASSERT_TRUE(L.getAsDecl());
4864 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4865 // The point here is to have a Vec with only one element, which is not the
4866 // one we are going to delete from the DC later.
4867 L.setHasExternalDecls();
4868 ASSERT_TRUE(L.getAsVector());
4869 ASSERT_EQ(1u, L.getAsVector()->size());
4870
4871 // This asserts in the old implementation.
4872 DC->removeDecl(A0);
4873 EXPECT_FALSE(DC->containsDecl(A0));
4874}
4875
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004876struct ImportFunctionTemplateSpecializations
4877 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004878
4879TEST_P(ImportFunctionTemplateSpecializations,
4880 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4881
4882 Decl *FromTU = getTuDecl(
4883 R"(
4884 template<class T>
4885 int f() { return 0; }
4886 void foo() { f<int>(); }
4887 )",
4888 Lang_CXX, "input0.cc");
4889
4890 // Check that the function template instantiation is NOT the child of the TU.
4891 auto Pattern = translationUnitDecl(
4892 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4893 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4894
4895 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4896 FromTU, functionDecl(hasName("foo")));
4897 ASSERT_TRUE(Import(Foo, Lang_CXX));
4898
4899 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4900 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4901}
4902
4903TEST_P(ImportFunctionTemplateSpecializations,
4904 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4905
4906 Decl *FromTU = getTuDecl(
4907 R"(
4908 template<class T>
4909 int f() { return 0; }
4910 template int f<int>();
4911 )",
4912 Lang_CXX, "input0.cc");
4913
4914 // Check that the function template instantiation is NOT the child of the TU.
4915 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4916 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4917 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4918
4919 ASSERT_TRUE(
4920 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4921
4922 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4923 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4924}
4925
4926TEST_P(ImportFunctionTemplateSpecializations,
4927 TUshouldContainFunctionTemplateSpecialization) {
4928
4929 Decl *FromTU = getTuDecl(
4930 R"(
4931 template<class T>
4932 int f() { return 0; }
4933 template <> int f<int>() { return 4; }
4934 )",
4935 Lang_CXX, "input0.cc");
4936
4937 // Check that the function template specialization is the child of the TU.
4938 auto Specialization =
4939 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4940 auto Pattern = translationUnitDecl(has(Specialization));
4941 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4942
4943 ASSERT_TRUE(
4944 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4945
4946 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4947 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4948}
4949
4950TEST_P(ImportFunctionTemplateSpecializations,
4951 FunctionTemplateSpecializationRedeclChain) {
4952
4953 Decl *FromTU = getTuDecl(
4954 R"(
4955 template<class T>
4956 int f() { return 0; }
4957 template <> int f<int>() { return 4; }
4958 )",
4959 Lang_CXX, "input0.cc");
4960
4961 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4962 hasParent(translationUnitDecl()));
4963 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4964 {
4965 auto *TU = FromTU;
4966 auto *SpecD = FromSpecD;
4967 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4968 TU, functionTemplateDecl());
4969 auto *FirstSpecD = *(TemplateD->spec_begin());
4970 ASSERT_EQ(SpecD, FirstSpecD);
4971 ASSERT_TRUE(SpecD->getPreviousDecl());
4972 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4973 ->doesThisDeclarationHaveABody());
4974 }
4975
4976 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4977
4978 {
4979 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4980 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4981 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4982 TU, functionTemplateDecl());
4983 auto *FirstSpecD = *(TemplateD->spec_begin());
4984 EXPECT_EQ(SpecD, FirstSpecD);
4985 ASSERT_TRUE(SpecD->getPreviousDecl());
4986 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4987 ->doesThisDeclarationHaveABody());
4988 }
4989}
4990
4991TEST_P(ImportFunctionTemplateSpecializations,
4992 MatchNumberOfFunctionTemplateSpecializations) {
4993
4994 Decl *FromTU = getTuDecl(
4995 R"(
4996 template <typename T> constexpr int f() { return 0; }
4997 template <> constexpr int f<int>() { return 4; }
4998 void foo() {
4999 static_assert(f<char>() == 0, "");
5000 static_assert(f<int>() == 4, "");
5001 }
5002 )",
5003 Lang_CXX11, "input0.cc");
5004 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
5005 FromTU, functionDecl(hasName("foo")));
5006
5007 Import(FromD, Lang_CXX11);
5008 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5009 EXPECT_EQ(
5010 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
5011 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
5012}
5013
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005014TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00005015 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
5016 {
5017 Decl *FromTU = getTuDecl(
5018 R"(
5019 template <typename T>
5020 struct B;
5021 )",
5022 Lang_CXX, "input0.cc");
5023 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
5024 FromTU, classTemplateDecl(hasName("B")));
5025
5026 Import(FromD, Lang_CXX);
5027 }
5028
5029 {
5030 Decl *FromTU = getTuDecl(
5031 R"(
5032 template <typename T>
5033 struct B {
5034 void f();
5035 B* b;
5036 };
5037 )",
5038 Lang_CXX, "input1.cc");
5039 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
5040 FromTU, functionDecl(hasName("f")));
5041 Import(FromD, Lang_CXX);
5042 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
5043 FromTU, classTemplateDecl(hasName("B")));
5044 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
5045 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
5046
5047 // We expect no (ODR) warning during the import.
5048 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5049 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5050 }
5051}
5052
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005053TEST_P(ASTImporterOptionSpecificTestBase,
5054 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00005055 // We already have an incomplete underlying type in the "To" context.
5056 auto Code =
5057 R"(
5058 template <typename T>
5059 struct S {
5060 void foo();
5061 };
5062 using U = S<int>;
5063 )";
5064 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
5065 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
5066 typedefNameDecl(hasName("U")));
5067 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
5068
5069 // The "From" context has the same typedef, but the underlying type is
5070 // complete this time.
5071 Decl *FromTU = getTuDecl(std::string(Code) +
5072 R"(
5073 void foo(U* u) {
5074 u->foo();
5075 }
5076 )", Lang_CXX11);
5077 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
5078 typedefNameDecl(hasName("U")));
5079 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
5080
5081 // The imported type should be complete.
5082 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
5083 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
5084}
5085
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005086struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00005087
5088TEST_P(ASTImporterLookupTableTest, OneDecl) {
5089 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
5090 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
5091 ASTImporterLookupTable LT(*ToTU);
5092 auto Res = LT.lookup(ToTU, D->getDeclName());
5093 ASSERT_EQ(Res.size(), 1u);
5094 EXPECT_EQ(*Res.begin(), D);
5095}
5096
5097static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
5098 for (Decl *D : DC->decls()) {
5099 if (auto *ND = dyn_cast<NamedDecl>(D))
5100 if (ND->getDeclName() == Name)
5101 return ND;
5102 }
5103 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00005104}
Gabor Marton54058b52018-12-17 13:53:12 +00005105
5106TEST_P(ASTImporterLookupTableTest,
5107 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
5108 auto *Code = R"(
5109 template <class T>
5110 struct X {
5111 friend void foo(){}
5112 };
5113 )";
5114 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
5115 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
5116 ToTU, classTemplateDecl(hasName("X")));
5117 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
5118 ToTU, functionDecl(hasName("foo")));
5119 DeclContext *FooDC = Foo->getDeclContext();
5120 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5121 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
5122 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5123 DeclarationName FooName = Foo->getDeclName();
5124
5125 // Cannot find in the LookupTable of its DC (TUDecl)
5126 SmallVector<NamedDecl *, 2> FoundDecls;
5127 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5128 EXPECT_EQ(FoundDecls.size(), 0u);
5129
5130 // Cannot find in the LookupTable of its LexicalDC (X)
5131 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5132 EXPECT_EQ(FoundDecls.size(), 0u);
5133
5134 // Can't find in the list of Decls of the DC.
5135 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5136
5137 // Can't find in the list of Decls of the LexicalDC
5138 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
5139
5140 // ASTImporter specific lookup finds it.
5141 ASTImporterLookupTable LT(*ToTU);
5142 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5143 ASSERT_EQ(Res.size(), 1u);
5144 EXPECT_EQ(*Res.begin(), Foo);
5145}
5146
5147TEST_P(ASTImporterLookupTableTest,
5148 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
5149 TranslationUnitDecl *ToTU =
5150 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
5151 auto *Foo =
5152 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
5153 auto *A =
5154 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5155 DeclContext *FooDC = Foo->getDeclContext();
5156 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5157 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
5158 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5159 DeclarationName FooName = Foo->getDeclName();
5160
5161 // Cannot find in the LookupTable of its DC (TUDecl).
5162 SmallVector<NamedDecl *, 2> FoundDecls;
5163 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5164 EXPECT_EQ(FoundDecls.size(), 0u);
5165
5166 // Cannot find in the LookupTable of its LexicalDC (A).
5167 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5168 EXPECT_EQ(FoundDecls.size(), 0u);
5169
5170 // Can't find in the list of Decls of the DC.
5171 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5172
5173 // Can find in the list of Decls of the LexicalDC.
5174 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
5175
5176 // ASTImporter specific lookup finds it.
5177 ASTImporterLookupTable LT(*ToTU);
5178 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5179 ASSERT_EQ(Res.size(), 1u);
5180 EXPECT_EQ(*Res.begin(), Foo);
5181}
5182
5183TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
5184 TranslationUnitDecl *ToTU =
5185 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
5186 DeclarationName VName = FirstDeclMatcher<VarDecl>()
5187 .match(ToTU, varDecl(hasName("V")))
5188 ->getDeclName();
5189 auto *A =
5190 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5191 auto *B =
5192 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
5193
5194 ASTImporterLookupTable LT(*ToTU);
5195
5196 auto Res = LT.lookup(cast<DeclContext>(A), VName);
5197 ASSERT_EQ(Res.size(), 1u);
5198 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5199 ToTU, fieldDecl(hasName("V"),
5200 hasParent(recordDecl(hasName("A"))))));
5201 Res = LT.lookup(cast<DeclContext>(B), VName);
5202 ASSERT_EQ(Res.size(), 1u);
5203 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5204 ToTU, fieldDecl(hasName("V"),
5205 hasParent(recordDecl(hasName("B"))))));
5206 Res = LT.lookup(ToTU, VName);
5207 ASSERT_EQ(Res.size(), 1u);
5208 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
5209 ToTU, varDecl(hasName("V"),
5210 hasParent(translationUnitDecl()))));
5211}
5212
5213TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5214 TranslationUnitDecl *ToTU = getToTuDecl(
5215 R"(
5216 void foo();
5217 void foo(int);
5218 void foo(int, int);
5219 )",
5220 Lang_CXX);
5221
5222 ASTImporterLookupTable LT(*ToTU);
5223 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5224 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5225 DeclarationName Name = F0->getDeclName();
5226 auto Res = LT.lookup(ToTU, Name);
5227 EXPECT_EQ(Res.size(), 3u);
5228 EXPECT_EQ(Res.count(F0), 1u);
5229 EXPECT_EQ(Res.count(F2), 1u);
5230}
5231
Gabor Martona9cab312019-02-08 09:19:34 +00005232TEST_P(ASTImporterLookupTableTest,
5233 DifferentOperatorsShouldHaveDifferentResultSet) {
5234 TranslationUnitDecl *ToTU = getToTuDecl(
5235 R"(
5236 struct X{};
5237 void operator+(X, X);
5238 void operator-(X, X);
5239 )",
5240 Lang_CXX);
5241
5242 ASTImporterLookupTable LT(*ToTU);
5243 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5244 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5245 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5246 ToTU, functionDecl(hasOverloadedOperatorName("-")));
5247 DeclarationName NamePlus = FPlus->getDeclName();
5248 auto ResPlus = LT.lookup(ToTU, NamePlus);
5249 EXPECT_EQ(ResPlus.size(), 1u);
5250 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5251 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5252 DeclarationName NameMinus = FMinus->getDeclName();
5253 auto ResMinus = LT.lookup(ToTU, NameMinus);
5254 EXPECT_EQ(ResMinus.size(), 1u);
5255 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5256 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5257 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5258}
5259
5260TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5261 TranslationUnitDecl *ToTU = getToTuDecl(
5262 R"(
5263 struct X {};
5264 void operator+(X, X);
5265 )",
5266 Lang_CXX);
5267 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5268 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5269
5270 Decl *FromTU = getTuDecl(
5271 R"(
5272 struct X {};
5273 void operator+(X, X);
5274 )",
5275 Lang_CXX);
5276 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5277 FromTU, functionDecl(hasOverloadedOperatorName("+")));
5278
5279 // FromPlus have a different TU, thus its DeclarationName is different too.
5280 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5281
5282 ASTImporterLookupTable LT(*ToTU);
5283 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
5284 ASSERT_EQ(Res.size(), 1u);
5285 EXPECT_EQ(*Res.begin(), ToPlus);
5286
5287 // FromPlus have a different TU, thus its DeclarationName is different too.
5288 Res = LT.lookup(ToTU, FromPlus->getDeclName());
5289 ASSERT_EQ(Res.size(), 0u);
5290}
5291
Gabor Marton54058b52018-12-17 13:53:12 +00005292static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
5293 QualType Ty = FD->getFriendType()->getType();
5294 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
5295 return cast<RecordType>(NamedTy)->getDecl();
5296}
5297
5298TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
5299 TranslationUnitDecl *ToTU = getToTuDecl(
5300 R"(
5301 class Y { friend class F; };
5302 )",
5303 Lang_CXX);
5304
5305 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5306 // So we must dig up the underlying CXXRecordDecl.
5307 ASTImporterLookupTable LT(*ToTU);
5308 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5309 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5310 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5311 ToTU, cxxRecordDecl(hasName("Y")));
5312
5313 DeclarationName Name = RD->getDeclName();
5314 auto Res = LT.lookup(ToTU, Name);
5315 EXPECT_EQ(Res.size(), 1u);
5316 EXPECT_EQ(*Res.begin(), RD);
5317
5318 Res = LT.lookup(Y, Name);
5319 EXPECT_EQ(Res.size(), 0u);
5320}
5321
5322TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5323 TranslationUnitDecl *ToTU = getToTuDecl(
5324 R"(
5325 class Y { template <class T> friend class F; };
5326 )",
5327 Lang_CXX);
5328
5329 ASTImporterLookupTable LT(*ToTU);
5330 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5331 ToTU, classTemplateDecl(hasName("F")));
5332 DeclarationName Name = F->getDeclName();
5333 auto Res = LT.lookup(ToTU, Name);
5334 EXPECT_EQ(Res.size(), 2u);
5335 EXPECT_EQ(Res.count(F), 1u);
5336 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5337}
5338
5339TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5340 TranslationUnitDecl *ToTU = getToTuDecl(
5341 R"(
5342 template <typename T>
5343 class F;
5344
5345 template <typename T>
5346 class Y {
5347 friend class F<T>;
5348 };
5349 )",
5350 Lang_CXX);
5351
5352 ASTImporterLookupTable LT(*ToTU);
5353 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5354 ToTU, classTemplateDecl(hasName("F")));
5355 DeclarationName Name = F->getDeclName();
5356 auto Res = LT.lookup(ToTU, Name);
5357 EXPECT_EQ(Res.size(), 2u);
5358 EXPECT_EQ(Res.count(F), 1u);
5359 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5360}
5361
5362TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
5363 TranslationUnitDecl *ToTU = getToTuDecl(
5364 R"(
5365 template <typename T>
5366 class F;
5367
5368 class Y {
5369 friend class F<int>;
5370 };
5371 )",
5372 Lang_CXX);
5373
5374 ASTImporterLookupTable LT(*ToTU);
5375 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5376 ToTU, classTemplateDecl(hasName("F")));
5377 DeclarationName Name = F->getDeclName();
5378 auto Res = LT.lookup(ToTU, Name);
5379 ASSERT_EQ(Res.size(), 3u);
5380 EXPECT_EQ(Res.count(F), 1u);
5381 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5382 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
5383}
5384
5385TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
5386 TranslationUnitDecl *ToTU = getToTuDecl(
5387 R"(
5388 class Y { friend void F(); };
5389 )",
5390 Lang_CXX);
5391
5392 ASTImporterLookupTable LT(*ToTU);
5393 auto *F =
5394 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
5395 DeclarationName Name = F->getDeclName();
5396 auto Res = LT.lookup(ToTU, Name);
5397 EXPECT_EQ(Res.size(), 1u);
5398 EXPECT_EQ(*Res.begin(), F);
5399}
5400
5401TEST_P(ASTImporterLookupTableTest,
5402 LookupFindsDeclsInClassTemplateSpecialization) {
5403 TranslationUnitDecl *ToTU = getToTuDecl(
5404 R"(
5405 template <typename T>
5406 struct X {
5407 int F;
5408 };
5409 void foo() {
5410 X<char> xc;
5411 }
5412 )",
5413 Lang_CXX);
5414
5415 ASTImporterLookupTable LT(*ToTU);
5416
5417 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
5418 ToTU, classTemplateDecl(hasName("X")));
5419 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
5420 ToTU,
5421 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
5422
5423 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5424 ToTU, classTemplateSpecializationDecl(hasName("X")));
5425 FieldDecl *FieldInSpec = *Spec->field_begin();
5426 ASSERT_TRUE(FieldInSpec);
5427
5428 DeclarationName Name = FieldInSpec->getDeclName();
5429 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
5430
5431 SmallVector<NamedDecl *, 2> FoundDecls;
5432 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
5433 EXPECT_EQ(FoundDecls.size(), 1u);
5434 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
5435
5436 auto Res = LT.lookup(TemplateDC, Name);
5437 ASSERT_EQ(Res.size(), 1u);
5438 EXPECT_EQ(*Res.begin(), FieldInTemplate);
5439
5440 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
5441 FoundDecls);
5442 EXPECT_EQ(FoundDecls.size(), 1u);
5443 EXPECT_EQ(FoundDecls[0], FieldInSpec);
5444
5445 Res = LT.lookup(cast<DeclContext>(Spec), Name);
5446 ASSERT_EQ(Res.size(), 1u);
5447 EXPECT_EQ(*Res.begin(), FieldInSpec);
5448}
5449
5450TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
5451 TranslationUnitDecl *ToTU = getToTuDecl(
5452 R"(
5453 class Y { template <class T> friend void F(); };
5454 )",
5455 Lang_CXX);
5456
5457 ASTImporterLookupTable LT(*ToTU);
5458 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
5459 ToTU, functionTemplateDecl(hasName("F")));
5460 DeclarationName Name = F->getDeclName();
5461 auto Res = LT.lookup(ToTU, Name);
5462 EXPECT_EQ(Res.size(), 2u);
5463 EXPECT_EQ(Res.count(F), 1u);
5464 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5465}
5466
5467TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
5468 TranslationUnitDecl *ToTU = getToTuDecl(
5469 R"(
5470 struct X;
5471 struct A {
5472 friend struct X;
5473 };
5474 struct B {
5475 friend struct X;
5476 };
5477 )",
5478 Lang_CXX);
5479
5480 ASTImporterLookupTable LT(*ToTU);
5481 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
5482 ToTU, cxxRecordDecl(hasName("X")));
5483 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5484 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5485 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
5486 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
5487 ASSERT_EQ(RD0, RD1);
5488 ASSERT_EQ(RD1, X);
5489
5490 DeclarationName Name = X->getDeclName();
5491 auto Res = LT.lookup(ToTU, Name);
5492 EXPECT_EQ(Res.size(), 1u);
5493 EXPECT_EQ(*Res.begin(), X);
5494}
5495
5496TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
5497 TranslationUnitDecl *ToTU = getToTuDecl(
5498 R"(
5499 enum E {
5500 A,
5501 B
5502 };
5503 )",
5504 Lang_C);
5505
5506 ASTImporterLookupTable LT(*ToTU);
5507 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
5508 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
5509 ToTU, enumConstantDecl(hasName("A")));
5510
5511 DeclarationName Name = A->getDeclName();
5512 // Redecl context is the TU.
5513 ASSERT_EQ(E->getRedeclContext(), ToTU);
5514
5515 SmallVector<NamedDecl *, 2> FoundDecls;
5516 // Normal lookup finds in the DC.
5517 E->localUncachedLookup(Name, FoundDecls);
5518 EXPECT_EQ(FoundDecls.size(), 1u);
5519
5520 // Normal lookup finds in the Redecl context.
5521 ToTU->localUncachedLookup(Name, FoundDecls);
5522 EXPECT_EQ(FoundDecls.size(), 1u);
5523
5524 // Import specific lookup finds in the DC.
5525 auto Res = LT.lookup(E, Name);
5526 ASSERT_EQ(Res.size(), 1u);
5527 EXPECT_EQ(*Res.begin(), A);
5528
5529 // Import specific lookup finds in the Redecl context.
5530 Res = LT.lookup(ToTU, Name);
5531 ASSERT_EQ(Res.size(), 1u);
5532 EXPECT_EQ(*Res.begin(), A);
5533}
5534
5535TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
5536 TranslationUnitDecl *ToTU = getToTuDecl(
5537 R"(
5538 namespace N {
5539 int A;
5540 }
5541 namespace N {
5542 }
5543 )",
5544 Lang_CXX);
5545 auto *N1 =
5546 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
5547 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
5548 DeclarationName Name = A->getDeclName();
5549
5550 ASTImporterLookupTable LT(*ToTU);
5551 auto Res = LT.lookup(N1, Name);
5552 ASSERT_EQ(Res.size(), 1u);
5553 EXPECT_EQ(*Res.begin(), A);
5554}
5555
Gabor Marton19f4f392018-06-25 13:04:37 +00005556INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5557 ::testing::Values(ArgVector()), );
5558
Gabor Marton5254e642018-06-27 13:32:50 +00005559INSTANTIATE_TEST_CASE_P(
5560 ParameterizedTests, CanonicalRedeclChain,
5561 ::testing::Values(ArgVector()),);
5562
Gabor Marton0e04ebd2019-02-11 10:27:58 +00005563// FIXME This test is disabled currently, upcoming patches will make it
5564// possible to enable.
5565TEST_P(ASTImporterOptionSpecificTestBase,
5566 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
5567 Decl *FromTU = getTuDecl(
5568 R"(
5569 namespace NS {
5570 struct X;
5571 struct Y {
5572 static const int I = 3;
5573 };
5574 }
5575 namespace NS {
5576 struct X { // <--- To be imported
5577 void method(int i = Y::I) {}
5578 int f;
5579 };
5580 }
5581 )",
5582 Lang_CXX);
5583 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5584 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5585 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
5586 FromTU,
5587 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
5588 ASSERT_NE(FromFwd, FromDef);
5589 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
5590 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
5591 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
5592
5593 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
5594 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
5595 EXPECT_NE(ToFwd, ToDef);
5596 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
5597 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
5598 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
5599 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5600 // We expect no (ODR) warning during the import.
5601 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5602}
5603
Gabor Martone331e632019-02-18 13:09:27 +00005604struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
5605
5606TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
5607 Decl *ToTU = getToTuDecl(
5608 R"(
5609 class X {
5610 template <typename T> friend void foo();
5611 };
5612 )",
5613 Lang_CXX);
5614 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
5615 ToTU, functionTemplateDecl(hasName("foo")));
5616
5617 Decl *FromTU = getTuDecl(
5618 R"(
5619 template <typename T> void foo();
5620 )",
5621 Lang_CXX);
5622 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
5623 FromTU, functionTemplateDecl(hasName("foo")));
5624 auto *Imported = Import(FromFoo, Lang_CXX);
5625
Gabor Marton16d98c22019-03-07 13:01:51 +00005626 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00005627}
5628
Gabor Marton54058b52018-12-17 13:53:12 +00005629INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5630 DefaultTestValuesForRunOptions, );
5631
Gabor Marton19f4f392018-06-25 13:04:37 +00005632INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5633 DefaultTestValuesForRunOptions, );
5634
5635INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5636 DefaultTestValuesForRunOptions, );
5637
5638INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5639 DefaultTestValuesForRunOptions, );
5640
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005641INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005642 DefaultTestValuesForRunOptions, );
5643
Raphael Isemanne9bc35f2019-04-29 21:02:35 +00005644INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
5645 DefaultTestValuesForRunOptions, );
5646
Gabor Marton19f4f392018-06-25 13:04:37 +00005647INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5648 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005649
Gabor Martone331e632019-02-18 13:09:27 +00005650INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5651 DefaultTestValuesForRunOptions, );
5652
Gabor Marton54058b52018-12-17 13:53:12 +00005653INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005654 DefaultTestValuesForRunOptions, );
5655
Gabor Marton54058b52018-12-17 13:53:12 +00005656INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005657 DefaultTestValuesForRunOptions, );
5658
Gabor Marton7df342a2018-12-17 12:42:12 +00005659INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5660 DefaultTestValuesForRunOptions, );
5661
Gabor Marton5254e642018-06-27 13:32:50 +00005662INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5663 ImportFunctionTemplateSpecializations,
5664 DefaultTestValuesForRunOptions, );
5665
Gabor Martonac3a5d62018-09-17 12:04:52 +00005666INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5667 DefaultTestValuesForRunOptions, );
5668
5669INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5670 DefaultTestValuesForRunOptions, );
5671
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005672} // end namespace ast_matchers
5673} // end namespace clang