blob: 07a7c3aea81ea3b49598c6a5cc770d76a571f2b1 [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());
4140 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
4141 EXPECT_TRUE(ToT->getTemplatedDecl());
4142 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004143
Gabor Martonfc03fc62019-02-18 11:09:56 +00004144 void TypedTest_DefinitionShouldBeImportedAsADefinition() {
4145 Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
4146 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4147 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004148
Gabor Martonfc03fc62019-02-18 11:09:56 +00004149 Decl *ImportedD = Import(FromD, Lang_CXX);
4150 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004151
Gabor Martonfc03fc62019-02-18 11:09:56 +00004152 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4153 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4154 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
4155 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
4156 EXPECT_TRUE(ToT->getTemplatedDecl());
4157 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004158
Gabor Martonfc03fc62019-02-18 11:09:56 +00004159 void TypedTest_ImportPrototypeAfterImportedPrototype() {
4160 Decl *FromTU = getTuDecl(
4161 getPrototype() + getPrototype(), Lang_CXX);
4162 auto *From0 =
4163 FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4164 auto *From1 = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4165 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4166 ASSERT_FALSE(From1->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004167
Gabor Martonfc03fc62019-02-18 11:09:56 +00004168 Decl *Imported0 = Import(From0, Lang_CXX);
4169 Decl *Imported1 = Import(From1, Lang_CXX);
4170 Decl *ToTU = Imported0->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004171
Gabor Martonfc03fc62019-02-18 11:09:56 +00004172 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4173 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4174 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4175 EXPECT_TRUE(Imported0 == To0);
4176 EXPECT_TRUE(Imported1 == To1);
4177 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4178 EXPECT_FALSE(To1->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004179
4180 CheckPreviousDecl(To0, To1);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004181 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004182
Gabor Martonfc03fc62019-02-18 11:09:56 +00004183 void TypedTest_ImportDefinitionAfterImportedPrototype() {
4184 Decl *FromTU = getTuDecl(
4185 getPrototype() + getDefinition(), Lang_CXX);
4186 auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4187 auto *FromDef = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4188 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4189 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004190
Gabor Martonfc03fc62019-02-18 11:09:56 +00004191 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4192 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4193 Decl *ToTU = ImportedProto->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004194
Gabor Martonfc03fc62019-02-18 11:09:56 +00004195 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4196 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4197 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4198 EXPECT_TRUE(ImportedProto == ToProto);
4199 EXPECT_TRUE(ImportedDef == ToDef);
4200 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4201 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004202
4203 CheckPreviousDecl(ToProto, ToDef);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004204 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004205
Gabor Martonfc03fc62019-02-18 11:09:56 +00004206 void TypedTest_ImportPrototypeAfterImportedDefinition() {
4207 Decl *FromTU = getTuDecl(
4208 getDefinition() + getPrototype(), Lang_CXX);
4209 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4210 auto *FromProto = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4211 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4212 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004213
Gabor Martonfc03fc62019-02-18 11:09:56 +00004214 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4215 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4216 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4217
4218 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4219 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4220 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4221 EXPECT_TRUE(ImportedDef == ToDef);
4222 EXPECT_TRUE(ImportedProto == ToProto);
4223 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4224 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004225
4226 CheckPreviousDecl(ToDef, ToProto);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004227 }
4228
4229 void TypedTest_ImportPrototypes() {
4230 Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4231 Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4232 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4233 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4234 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4235 ASSERT_FALSE(From1->isThisDeclarationADefinition());
4236
4237 Decl *Imported0 = Import(From0, Lang_CXX);
4238 Decl *Imported1 = Import(From1, Lang_CXX);
4239 Decl *ToTU = Imported0->getTranslationUnitDecl();
4240
4241 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4242 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4243 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4244 EXPECT_TRUE(Imported0 == To0);
4245 EXPECT_TRUE(Imported1 == To1);
4246 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4247 EXPECT_FALSE(To1->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004248
4249 CheckPreviousDecl(To0, To1);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004250 }
4251
4252 void TypedTest_ImportDefinitions() {
4253 Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4254 Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4255 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4256 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4257 ASSERT_TRUE(From0->isThisDeclarationADefinition());
4258 ASSERT_TRUE(From1->isThisDeclarationADefinition());
4259
4260 Decl *Imported0 = Import(From0, Lang_CXX);
4261 Decl *Imported1 = Import(From1, Lang_CXX);
4262 Decl *ToTU = Imported0->getTranslationUnitDecl();
4263
4264 EXPECT_EQ(Imported0, Imported1);
4265 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4266 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4267 EXPECT_TRUE(Imported0 == To0);
4268 EXPECT_TRUE(To0->isThisDeclarationADefinition());
4269 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0))
4270 EXPECT_TRUE(ToT0->getTemplatedDecl());
4271 }
4272
4273 void TypedTest_ImportDefinitionThenPrototype() {
4274 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4275 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4276 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4277 auto *FromProto =
4278 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4279 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4280 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4281
4282 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4283 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4284 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4285
4286 EXPECT_NE(ImportedDef, ImportedProto);
4287 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4288 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4289 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4290 EXPECT_TRUE(ImportedDef == ToDef);
4291 EXPECT_TRUE(ImportedProto == ToProto);
4292 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4293 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004294
4295 CheckPreviousDecl(ToDef, ToProto);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004296 }
4297
4298 void TypedTest_ImportPrototypeThenDefinition() {
4299 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4300 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4301 auto *FromProto =
4302 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4303 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4304 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4305 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4306
4307 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4308 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4309 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4310
4311 EXPECT_NE(ImportedDef, ImportedProto);
4312 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4313 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4314 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4315 EXPECT_TRUE(ImportedDef == ToDef);
4316 EXPECT_TRUE(ImportedProto == ToProto);
4317 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4318 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004319
4320 CheckPreviousDecl(ToProto, ToDef);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004321 }
4322
4323 void TypedTest_WholeRedeclChainIsImportedAtOnce() {
4324 Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
4325 auto *FromD = // Definition
4326 LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4327 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
4328
4329 Decl *ImportedD = Import(FromD, Lang_CXX);
4330 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4331
4332 // The whole redecl chain is imported at once.
4333 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4334 EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition());
4335 }
4336
4337 void TypedTest_ImportPrototypeThenProtoAndDefinition() {
4338 {
4339 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4340 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4341 Import(FromD, Lang_CXX);
4342 }
4343 {
4344 Decl *FromTU =
4345 getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc");
4346 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4347 Import(FromD, Lang_CXX);
4348 }
4349
4350 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4351
4352 ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u);
4353 DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4354 EXPECT_FALSE(ProtoD->isThisDeclarationADefinition());
4355
4356 DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4357 EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition());
4358
4359 EXPECT_TRUE(DefinitionD->getPreviousDecl());
4360 EXPECT_FALSE(
4361 DefinitionD->getPreviousDecl()->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004362
4363 CheckPreviousDecl(ProtoD, DefinitionD->getPreviousDecl());
Gabor Martonfc03fc62019-02-18 11:09:56 +00004364 }
4365};
4366
4367#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \
4368 NamePrefix, TestCase) \
4369 using BaseTemplate##TypeParam = BaseTemplate<TypeParam>; \
4370 TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \
4371 TypedTest_##TestCase(); \
4372 }
4373
4374ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4375 RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004376 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004377ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4378 RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004379 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004380ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4381 RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004382 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004383ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004384 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004385 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004386ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4387 RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004388 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004389ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4390 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004391 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004392ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4393 RedeclChain, ClassTemplateSpec, ,
4394 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004395
4396ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004397 RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004398ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004399 RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004400ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004401 RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004402ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004403 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004404 DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004405ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004406 RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004407ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4408 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004409 DefinitionShouldBeImportedAsADefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004410ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4411 RedeclChain, ClassTemplateSpec, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004412
4413ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004414 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004415ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004416 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004417ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004418 ImportPrototypeAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004419ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004420 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004421ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004422 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004423ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004424 ImportPrototypeAfterImportedPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004425ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4426 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004427
4428ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004429 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004430ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004431 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004432ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004433 ImportDefinitionAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004434ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004435 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004436ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004437 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004438ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004439 ImportDefinitionAfterImportedPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004440ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4441 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004442
4443ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004444 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004445ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004446 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004447ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004448 ImportPrototypeAfterImportedDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004449ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004450 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004451ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004452 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004453ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004454 ImportPrototypeAfterImportedDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004455ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4456 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004457
4458ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004459 ImportPrototypes)
Gabor Marton038100a2019-02-20 16:57:41 +00004460ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004461ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004462 ImportPrototypes)
Gabor Marton16d98c22019-03-07 13:01:51 +00004463ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4464 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004465ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004466 ImportPrototypes)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004467ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4468 ImportPrototypes)
Gabor Martondd59d272019-03-19 14:04:50 +00004469ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4470 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004471
4472ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004473 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004474ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004475 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004476ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004477 ImportDefinitions)
Gabor Marton16d98c22019-03-07 13:01:51 +00004478ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4479 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004480ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004481 ImportDefinitions)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004482ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4483 ImportDefinitions)
Gabor Martondd59d272019-03-19 14:04:50 +00004484ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4485 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004486
4487ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004488 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004489ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004490 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004491ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004492 ImportDefinitionThenPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004493ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004494 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004495ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004496 ImportDefinitionThenPrototype)
Gabor Martondd59d272019-03-19 14:04:50 +00004497ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004498 ImportDefinitionThenPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004499ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4500 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004501
4502ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004503 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004504ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004505 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004506ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004507 ImportPrototypeThenDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004508ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004509 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004510ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004511 ImportPrototypeThenDefinition)
Gabor Martondd59d272019-03-19 14:04:50 +00004512ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004513 ImportPrototypeThenDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004514ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4515 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004516
4517ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004518 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004519ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004520 WholeRedeclChainIsImportedAtOnce)
Gabor Marton16d98c22019-03-07 13:01:51 +00004521ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004522 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004523ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004524 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004525
4526ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004527 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004528ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004529 ImportPrototypeThenProtoAndDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004530ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004531 ImportPrototypeThenProtoAndDefinition)
Gabor Martondd59d272019-03-19 14:04:50 +00004532ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004533 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004534
4535INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction,
4536 DefaultTestValuesForRunOptions, );
4537INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass,
4538 DefaultTestValuesForRunOptions, );
4539INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable,
4540 DefaultTestValuesForRunOptions, );
4541INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
4542 DefaultTestValuesForRunOptions, );
4543INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
4544 DefaultTestValuesForRunOptions, );
4545INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
4546 DefaultTestValuesForRunOptions, );
Gabor Marton7f8c4002019-03-19 13:34:10 +00004547INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplateSpec,
4548 DefaultTestValuesForRunOptions, );
Gabor Martonfc03fc62019-02-18 11:09:56 +00004549
4550
Gabor Marton7df342a2018-12-17 12:42:12 +00004551
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004552struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00004553
4554TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4555 Decl *FromTU = getTuDecl(
4556 R"(
4557 class A {
4558 template <int I> class F {};
4559 class X {
4560 template <int I> friend class F;
4561 };
4562 };
4563 )",
4564 Lang_CXX, "input0.cc");
4565
4566 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4567 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4568 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4569 FromTU, cxxRecordDecl(hasName("F")));
4570
4571 ASSERT_TRUE(FromClass);
4572 ASSERT_TRUE(FromFriendClass);
4573 ASSERT_NE(FromClass, FromFriendClass);
4574 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4575 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4576 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4577 FromClass->getDescribedClassTemplate());
4578
4579 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
4580 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
4581
4582 EXPECT_TRUE(ToClass);
4583 EXPECT_TRUE(ToFriendClass);
4584 EXPECT_NE(ToClass, ToFriendClass);
4585 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4586 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4587 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4588 ToClass->getDescribedClassTemplate());
4589}
4590
4591TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4592 Decl *FromTu = getTuDecl(
4593 R"(
4594 class declToImport {
4595 friend class declToImport;
4596 };
4597 )",
4598 Lang_CXX, "input.cc");
4599
4600 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4601 FromTu, cxxRecordDecl(hasName("declToImport")));
4602 auto *ToD = Import(FromD, Lang_CXX);
4603 auto Pattern = cxxRecordDecl(has(friendDecl()));
4604 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4605 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4606}
4607
4608TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4609 Decl *FromTu = getTuDecl(
4610 R"(
4611 template<class A> class declToImport {
4612 template<class A1> friend class declToImport;
4613 };
4614 )",
4615 Lang_CXX, "input.cc");
4616
4617 auto *FromD =
4618 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
4619 auto *ToD = Import(FromD, Lang_CXX);
4620
4621 auto Pattern = classTemplateDecl(
4622 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4623 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4624 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4625
4626 auto *Class =
4627 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
4628 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4629 EXPECT_NE(Friend->getFriendDecl(), Class);
4630 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
4631}
4632
4633TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4634 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
4635
4636 ClassTemplateSpecializationDecl *Imported1;
4637 {
4638 Decl *FromTU = getTuDecl("template<class T> class X;"
4639 "struct Y { friend class X<int>; };",
4640 Lang_CXX, "input0.cc");
4641 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4642 FromTU, Pattern);
4643
4644 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4645 }
4646 ClassTemplateSpecializationDecl *Imported2;
4647 {
4648 Decl *FromTU = getTuDecl("template<class T> class X;"
4649 "template<> class X<int>{};"
4650 "struct Z { friend class X<int>; };",
4651 Lang_CXX, "input1.cc");
4652 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4653 FromTU, Pattern);
4654
4655 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4656 }
4657
4658 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4659 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4660 2u);
4661 ASSERT_TRUE(Imported2->getPreviousDecl());
4662 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4663}
4664
4665TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4666 Decl *FromTU0 = getTuDecl(
4667 R"(
4668 class X {
4669 class Y;
4670 };
4671 class X::Y {
4672 template <typename T>
4673 friend class F; // The decl context of F is the global namespace.
4674 };
4675 )",
4676 Lang_CXX, "input0.cc");
4677 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4678 FromTU0, classTemplateDecl(hasName("F")));
4679 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4680 Decl *FromTU1 = getTuDecl(
4681 R"(
4682 template <typename T>
4683 class F {};
4684 )",
4685 Lang_CXX, "input1.cc");
4686 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4687 FromTU1, classTemplateDecl(hasName("F")));
4688 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4689 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4690 Imported1->getTemplatedDecl()->getTypeForDecl());
4691}
4692
4693TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4694 Decl *From, *To;
4695 std::tie(From, To) =
4696 getImportedDecl("class declToImport {};", Lang_CXX,
4697 "class Y { friend class declToImport; };", Lang_CXX);
4698 auto *Imported = cast<CXXRecordDecl>(To);
4699
4700 EXPECT_TRUE(Imported->getPreviousDecl());
4701}
4702
4703TEST_P(ImportFriendClasses,
4704 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4705 Decl *ToTU = getToTuDecl(
4706 R"(
4707 class X {
4708 class Y;
4709 };
4710 class X::Y {
4711 template <typename T>
4712 friend class F; // The decl context of F is the global namespace.
4713 };
4714 )",
4715 Lang_CXX);
4716 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4717 ToTU, classTemplateDecl(hasName("F")));
4718 Decl *FromTU = getTuDecl(
4719 R"(
4720 template <typename T>
4721 class F {};
4722 )",
4723 Lang_CXX, "input0.cc");
4724 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4725 FromTU, classTemplateDecl(hasName("F")));
4726 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4727 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4728 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4729 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4730 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4731}
4732
4733TEST_P(ImportFriendClasses,
4734 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4735 Decl *FromTU0 = getTuDecl(
4736 R"(
4737 class X {
4738 class Y;
4739 };
4740 class X::Y {
4741 template <typename T>
4742 friend class F; // The decl context of F is the global namespace.
4743 };
4744 )",
4745 Lang_CXX, "input0.cc");
4746 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4747 FromTU0, classTemplateDecl(hasName("F")));
4748 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4749 Decl *FromTU1 = getTuDecl(
4750 R"(
4751 template <typename T>
4752 class F {};
4753 )",
4754 Lang_CXX, "input1.cc");
4755 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4756 FromTU1, classTemplateDecl(hasName("F")));
4757 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4758 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4759 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4760 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4761 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4762}
4763
4764TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4765 Decl *FromTU0 = getTuDecl(
4766 R"(
4767 class X {
4768 class Y;
4769 };
4770 class X::Y {
4771 friend class F; // The decl context of F is the global namespace.
4772 };
4773 )",
4774 Lang_CXX, "input0.cc");
4775 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4776 QualType FT = Friend->getFriendType()->getType();
4777 FT = FromTU0->getASTContext().getCanonicalType(FT);
4778 auto *Fwd = cast<TagType>(FT)->getDecl();
4779 auto *ImportedFwd = Import(Fwd, Lang_CXX);
4780 Decl *FromTU1 = getTuDecl(
4781 R"(
4782 class F {};
4783 )",
4784 Lang_CXX, "input1.cc");
4785 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4786 FromTU1, cxxRecordDecl(hasName("F")));
4787 auto *ImportedDef = Import(Definition, Lang_CXX);
4788 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4789 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4790}
4791
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004792TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00004793 auto *Code = R"(
4794 template <class T>
4795 struct X {
4796 friend void foo(){}
4797 };
4798 )";
4799 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4800 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4801 ToTU, functionDecl(hasName("foo")));
4802
4803 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4804 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4805 FromTU, functionDecl(hasName("foo")));
4806 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4807 EXPECT_EQ(ImportedFoo, ToFoo);
4808}
4809
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004810struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00004811
4812TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4813 Decl *TU = getTuDecl(
4814 R"(
4815 namespace NS {
4816
4817 template <typename T>
4818 struct S {};
4819 template struct S<int>;
4820
4821 inline namespace INS {
4822 template <typename T>
4823 struct S {};
4824 template struct S<int>;
4825 }
4826
4827 }
4828 )", Lang_CXX11, "input0.cc");
4829 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4830 TU, namespaceDecl());
4831 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4832 TU, classTemplateSpecializationDecl());
4833 ASSERT_TRUE(NS->containsDecl(Spec));
4834
4835 NS->removeDecl(Spec);
4836 EXPECT_FALSE(NS->containsDecl(Spec));
4837}
4838
Gabor Marton7df342a2018-12-17 12:42:12 +00004839TEST_P(DeclContextTest,
4840 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4841 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4842 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4843 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4844
4845 // Investigate the list.
4846 auto *DC = A0->getDeclContext();
4847 ASSERT_TRUE(DC->containsDecl(A0));
4848 ASSERT_TRUE(DC->containsDecl(A1));
4849
4850 // Investigate the lookup table.
4851 auto *Map = DC->getLookupPtr();
4852 ASSERT_TRUE(Map);
4853 auto I = Map->find(A0->getDeclName());
4854 ASSERT_NE(I, Map->end());
4855 StoredDeclsList &L = I->second;
4856 // The lookup table contains the most recent decl of A.
4857 ASSERT_NE(L.getAsDecl(), A0);
4858 ASSERT_EQ(L.getAsDecl(), A1);
4859
4860 ASSERT_TRUE(L.getAsDecl());
4861 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4862 // The point here is to have a Vec with only one element, which is not the
4863 // one we are going to delete from the DC later.
4864 L.setHasExternalDecls();
4865 ASSERT_TRUE(L.getAsVector());
4866 ASSERT_EQ(1u, L.getAsVector()->size());
4867
4868 // This asserts in the old implementation.
4869 DC->removeDecl(A0);
4870 EXPECT_FALSE(DC->containsDecl(A0));
4871}
4872
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004873struct ImportFunctionTemplateSpecializations
4874 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004875
4876TEST_P(ImportFunctionTemplateSpecializations,
4877 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4878
4879 Decl *FromTU = getTuDecl(
4880 R"(
4881 template<class T>
4882 int f() { return 0; }
4883 void foo() { f<int>(); }
4884 )",
4885 Lang_CXX, "input0.cc");
4886
4887 // Check that the function template instantiation is NOT the child of the TU.
4888 auto Pattern = translationUnitDecl(
4889 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4890 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4891
4892 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4893 FromTU, functionDecl(hasName("foo")));
4894 ASSERT_TRUE(Import(Foo, Lang_CXX));
4895
4896 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4897 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4898}
4899
4900TEST_P(ImportFunctionTemplateSpecializations,
4901 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4902
4903 Decl *FromTU = getTuDecl(
4904 R"(
4905 template<class T>
4906 int f() { return 0; }
4907 template int f<int>();
4908 )",
4909 Lang_CXX, "input0.cc");
4910
4911 // Check that the function template instantiation is NOT the child of the TU.
4912 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4913 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4914 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4915
4916 ASSERT_TRUE(
4917 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4918
4919 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4920 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4921}
4922
4923TEST_P(ImportFunctionTemplateSpecializations,
4924 TUshouldContainFunctionTemplateSpecialization) {
4925
4926 Decl *FromTU = getTuDecl(
4927 R"(
4928 template<class T>
4929 int f() { return 0; }
4930 template <> int f<int>() { return 4; }
4931 )",
4932 Lang_CXX, "input0.cc");
4933
4934 // Check that the function template specialization is the child of the TU.
4935 auto Specialization =
4936 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4937 auto Pattern = translationUnitDecl(has(Specialization));
4938 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4939
4940 ASSERT_TRUE(
4941 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4942
4943 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4944 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4945}
4946
4947TEST_P(ImportFunctionTemplateSpecializations,
4948 FunctionTemplateSpecializationRedeclChain) {
4949
4950 Decl *FromTU = getTuDecl(
4951 R"(
4952 template<class T>
4953 int f() { return 0; }
4954 template <> int f<int>() { return 4; }
4955 )",
4956 Lang_CXX, "input0.cc");
4957
4958 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4959 hasParent(translationUnitDecl()));
4960 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4961 {
4962 auto *TU = FromTU;
4963 auto *SpecD = FromSpecD;
4964 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4965 TU, functionTemplateDecl());
4966 auto *FirstSpecD = *(TemplateD->spec_begin());
4967 ASSERT_EQ(SpecD, FirstSpecD);
4968 ASSERT_TRUE(SpecD->getPreviousDecl());
4969 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4970 ->doesThisDeclarationHaveABody());
4971 }
4972
4973 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4974
4975 {
4976 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4977 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4978 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4979 TU, functionTemplateDecl());
4980 auto *FirstSpecD = *(TemplateD->spec_begin());
4981 EXPECT_EQ(SpecD, FirstSpecD);
4982 ASSERT_TRUE(SpecD->getPreviousDecl());
4983 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4984 ->doesThisDeclarationHaveABody());
4985 }
4986}
4987
4988TEST_P(ImportFunctionTemplateSpecializations,
4989 MatchNumberOfFunctionTemplateSpecializations) {
4990
4991 Decl *FromTU = getTuDecl(
4992 R"(
4993 template <typename T> constexpr int f() { return 0; }
4994 template <> constexpr int f<int>() { return 4; }
4995 void foo() {
4996 static_assert(f<char>() == 0, "");
4997 static_assert(f<int>() == 4, "");
4998 }
4999 )",
5000 Lang_CXX11, "input0.cc");
5001 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
5002 FromTU, functionDecl(hasName("foo")));
5003
5004 Import(FromD, Lang_CXX11);
5005 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5006 EXPECT_EQ(
5007 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
5008 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
5009}
5010
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005011TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00005012 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
5013 {
5014 Decl *FromTU = getTuDecl(
5015 R"(
5016 template <typename T>
5017 struct B;
5018 )",
5019 Lang_CXX, "input0.cc");
5020 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
5021 FromTU, classTemplateDecl(hasName("B")));
5022
5023 Import(FromD, Lang_CXX);
5024 }
5025
5026 {
5027 Decl *FromTU = getTuDecl(
5028 R"(
5029 template <typename T>
5030 struct B {
5031 void f();
5032 B* b;
5033 };
5034 )",
5035 Lang_CXX, "input1.cc");
5036 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
5037 FromTU, functionDecl(hasName("f")));
5038 Import(FromD, Lang_CXX);
5039 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
5040 FromTU, classTemplateDecl(hasName("B")));
5041 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
5042 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
5043
5044 // We expect no (ODR) warning during the import.
5045 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5046 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5047 }
5048}
5049
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005050TEST_P(ASTImporterOptionSpecificTestBase,
5051 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00005052 // We already have an incomplete underlying type in the "To" context.
5053 auto Code =
5054 R"(
5055 template <typename T>
5056 struct S {
5057 void foo();
5058 };
5059 using U = S<int>;
5060 )";
5061 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
5062 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
5063 typedefNameDecl(hasName("U")));
5064 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
5065
5066 // The "From" context has the same typedef, but the underlying type is
5067 // complete this time.
5068 Decl *FromTU = getTuDecl(std::string(Code) +
5069 R"(
5070 void foo(U* u) {
5071 u->foo();
5072 }
5073 )", Lang_CXX11);
5074 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
5075 typedefNameDecl(hasName("U")));
5076 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
5077
5078 // The imported type should be complete.
5079 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
5080 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
5081}
5082
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005083struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00005084
5085TEST_P(ASTImporterLookupTableTest, OneDecl) {
5086 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
5087 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
5088 ASTImporterLookupTable LT(*ToTU);
5089 auto Res = LT.lookup(ToTU, D->getDeclName());
5090 ASSERT_EQ(Res.size(), 1u);
5091 EXPECT_EQ(*Res.begin(), D);
5092}
5093
5094static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
5095 for (Decl *D : DC->decls()) {
5096 if (auto *ND = dyn_cast<NamedDecl>(D))
5097 if (ND->getDeclName() == Name)
5098 return ND;
5099 }
5100 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00005101}
Gabor Marton54058b52018-12-17 13:53:12 +00005102
5103TEST_P(ASTImporterLookupTableTest,
5104 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
5105 auto *Code = R"(
5106 template <class T>
5107 struct X {
5108 friend void foo(){}
5109 };
5110 )";
5111 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
5112 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
5113 ToTU, classTemplateDecl(hasName("X")));
5114 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
5115 ToTU, functionDecl(hasName("foo")));
5116 DeclContext *FooDC = Foo->getDeclContext();
5117 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5118 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
5119 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5120 DeclarationName FooName = Foo->getDeclName();
5121
5122 // Cannot find in the LookupTable of its DC (TUDecl)
5123 SmallVector<NamedDecl *, 2> FoundDecls;
5124 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5125 EXPECT_EQ(FoundDecls.size(), 0u);
5126
5127 // Cannot find in the LookupTable of its LexicalDC (X)
5128 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5129 EXPECT_EQ(FoundDecls.size(), 0u);
5130
5131 // Can't find in the list of Decls of the DC.
5132 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5133
5134 // Can't find in the list of Decls of the LexicalDC
5135 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
5136
5137 // ASTImporter specific lookup finds it.
5138 ASTImporterLookupTable LT(*ToTU);
5139 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5140 ASSERT_EQ(Res.size(), 1u);
5141 EXPECT_EQ(*Res.begin(), Foo);
5142}
5143
5144TEST_P(ASTImporterLookupTableTest,
5145 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
5146 TranslationUnitDecl *ToTU =
5147 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
5148 auto *Foo =
5149 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
5150 auto *A =
5151 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5152 DeclContext *FooDC = Foo->getDeclContext();
5153 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5154 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
5155 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5156 DeclarationName FooName = Foo->getDeclName();
5157
5158 // Cannot find in the LookupTable of its DC (TUDecl).
5159 SmallVector<NamedDecl *, 2> FoundDecls;
5160 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5161 EXPECT_EQ(FoundDecls.size(), 0u);
5162
5163 // Cannot find in the LookupTable of its LexicalDC (A).
5164 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5165 EXPECT_EQ(FoundDecls.size(), 0u);
5166
5167 // Can't find in the list of Decls of the DC.
5168 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5169
5170 // Can find in the list of Decls of the LexicalDC.
5171 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
5172
5173 // ASTImporter specific lookup finds it.
5174 ASTImporterLookupTable LT(*ToTU);
5175 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5176 ASSERT_EQ(Res.size(), 1u);
5177 EXPECT_EQ(*Res.begin(), Foo);
5178}
5179
5180TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
5181 TranslationUnitDecl *ToTU =
5182 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
5183 DeclarationName VName = FirstDeclMatcher<VarDecl>()
5184 .match(ToTU, varDecl(hasName("V")))
5185 ->getDeclName();
5186 auto *A =
5187 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5188 auto *B =
5189 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
5190
5191 ASTImporterLookupTable LT(*ToTU);
5192
5193 auto Res = LT.lookup(cast<DeclContext>(A), VName);
5194 ASSERT_EQ(Res.size(), 1u);
5195 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5196 ToTU, fieldDecl(hasName("V"),
5197 hasParent(recordDecl(hasName("A"))))));
5198 Res = LT.lookup(cast<DeclContext>(B), VName);
5199 ASSERT_EQ(Res.size(), 1u);
5200 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5201 ToTU, fieldDecl(hasName("V"),
5202 hasParent(recordDecl(hasName("B"))))));
5203 Res = LT.lookup(ToTU, VName);
5204 ASSERT_EQ(Res.size(), 1u);
5205 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
5206 ToTU, varDecl(hasName("V"),
5207 hasParent(translationUnitDecl()))));
5208}
5209
5210TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5211 TranslationUnitDecl *ToTU = getToTuDecl(
5212 R"(
5213 void foo();
5214 void foo(int);
5215 void foo(int, int);
5216 )",
5217 Lang_CXX);
5218
5219 ASTImporterLookupTable LT(*ToTU);
5220 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5221 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5222 DeclarationName Name = F0->getDeclName();
5223 auto Res = LT.lookup(ToTU, Name);
5224 EXPECT_EQ(Res.size(), 3u);
5225 EXPECT_EQ(Res.count(F0), 1u);
5226 EXPECT_EQ(Res.count(F2), 1u);
5227}
5228
Gabor Martona9cab312019-02-08 09:19:34 +00005229TEST_P(ASTImporterLookupTableTest,
5230 DifferentOperatorsShouldHaveDifferentResultSet) {
5231 TranslationUnitDecl *ToTU = getToTuDecl(
5232 R"(
5233 struct X{};
5234 void operator+(X, X);
5235 void operator-(X, X);
5236 )",
5237 Lang_CXX);
5238
5239 ASTImporterLookupTable LT(*ToTU);
5240 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5241 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5242 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5243 ToTU, functionDecl(hasOverloadedOperatorName("-")));
5244 DeclarationName NamePlus = FPlus->getDeclName();
5245 auto ResPlus = LT.lookup(ToTU, NamePlus);
5246 EXPECT_EQ(ResPlus.size(), 1u);
5247 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5248 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5249 DeclarationName NameMinus = FMinus->getDeclName();
5250 auto ResMinus = LT.lookup(ToTU, NameMinus);
5251 EXPECT_EQ(ResMinus.size(), 1u);
5252 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5253 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5254 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5255}
5256
5257TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5258 TranslationUnitDecl *ToTU = getToTuDecl(
5259 R"(
5260 struct X {};
5261 void operator+(X, X);
5262 )",
5263 Lang_CXX);
5264 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5265 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5266
5267 Decl *FromTU = getTuDecl(
5268 R"(
5269 struct X {};
5270 void operator+(X, X);
5271 )",
5272 Lang_CXX);
5273 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5274 FromTU, functionDecl(hasOverloadedOperatorName("+")));
5275
5276 // FromPlus have a different TU, thus its DeclarationName is different too.
5277 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5278
5279 ASTImporterLookupTable LT(*ToTU);
5280 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
5281 ASSERT_EQ(Res.size(), 1u);
5282 EXPECT_EQ(*Res.begin(), ToPlus);
5283
5284 // FromPlus have a different TU, thus its DeclarationName is different too.
5285 Res = LT.lookup(ToTU, FromPlus->getDeclName());
5286 ASSERT_EQ(Res.size(), 0u);
5287}
5288
Gabor Marton54058b52018-12-17 13:53:12 +00005289static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
5290 QualType Ty = FD->getFriendType()->getType();
5291 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
5292 return cast<RecordType>(NamedTy)->getDecl();
5293}
5294
5295TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
5296 TranslationUnitDecl *ToTU = getToTuDecl(
5297 R"(
5298 class Y { friend class F; };
5299 )",
5300 Lang_CXX);
5301
5302 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5303 // So we must dig up the underlying CXXRecordDecl.
5304 ASTImporterLookupTable LT(*ToTU);
5305 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5306 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5307 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5308 ToTU, cxxRecordDecl(hasName("Y")));
5309
5310 DeclarationName Name = RD->getDeclName();
5311 auto Res = LT.lookup(ToTU, Name);
5312 EXPECT_EQ(Res.size(), 1u);
5313 EXPECT_EQ(*Res.begin(), RD);
5314
5315 Res = LT.lookup(Y, Name);
5316 EXPECT_EQ(Res.size(), 0u);
5317}
5318
5319TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5320 TranslationUnitDecl *ToTU = getToTuDecl(
5321 R"(
5322 class Y { template <class T> friend class F; };
5323 )",
5324 Lang_CXX);
5325
5326 ASTImporterLookupTable LT(*ToTU);
5327 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5328 ToTU, classTemplateDecl(hasName("F")));
5329 DeclarationName Name = F->getDeclName();
5330 auto Res = LT.lookup(ToTU, Name);
5331 EXPECT_EQ(Res.size(), 2u);
5332 EXPECT_EQ(Res.count(F), 1u);
5333 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5334}
5335
5336TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5337 TranslationUnitDecl *ToTU = getToTuDecl(
5338 R"(
5339 template <typename T>
5340 class F;
5341
5342 template <typename T>
5343 class Y {
5344 friend class F<T>;
5345 };
5346 )",
5347 Lang_CXX);
5348
5349 ASTImporterLookupTable LT(*ToTU);
5350 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5351 ToTU, classTemplateDecl(hasName("F")));
5352 DeclarationName Name = F->getDeclName();
5353 auto Res = LT.lookup(ToTU, Name);
5354 EXPECT_EQ(Res.size(), 2u);
5355 EXPECT_EQ(Res.count(F), 1u);
5356 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5357}
5358
5359TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
5360 TranslationUnitDecl *ToTU = getToTuDecl(
5361 R"(
5362 template <typename T>
5363 class F;
5364
5365 class Y {
5366 friend class F<int>;
5367 };
5368 )",
5369 Lang_CXX);
5370
5371 ASTImporterLookupTable LT(*ToTU);
5372 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5373 ToTU, classTemplateDecl(hasName("F")));
5374 DeclarationName Name = F->getDeclName();
5375 auto Res = LT.lookup(ToTU, Name);
5376 ASSERT_EQ(Res.size(), 3u);
5377 EXPECT_EQ(Res.count(F), 1u);
5378 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5379 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
5380}
5381
5382TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
5383 TranslationUnitDecl *ToTU = getToTuDecl(
5384 R"(
5385 class Y { friend void F(); };
5386 )",
5387 Lang_CXX);
5388
5389 ASTImporterLookupTable LT(*ToTU);
5390 auto *F =
5391 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
5392 DeclarationName Name = F->getDeclName();
5393 auto Res = LT.lookup(ToTU, Name);
5394 EXPECT_EQ(Res.size(), 1u);
5395 EXPECT_EQ(*Res.begin(), F);
5396}
5397
5398TEST_P(ASTImporterLookupTableTest,
5399 LookupFindsDeclsInClassTemplateSpecialization) {
5400 TranslationUnitDecl *ToTU = getToTuDecl(
5401 R"(
5402 template <typename T>
5403 struct X {
5404 int F;
5405 };
5406 void foo() {
5407 X<char> xc;
5408 }
5409 )",
5410 Lang_CXX);
5411
5412 ASTImporterLookupTable LT(*ToTU);
5413
5414 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
5415 ToTU, classTemplateDecl(hasName("X")));
5416 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
5417 ToTU,
5418 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
5419
5420 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5421 ToTU, classTemplateSpecializationDecl(hasName("X")));
5422 FieldDecl *FieldInSpec = *Spec->field_begin();
5423 ASSERT_TRUE(FieldInSpec);
5424
5425 DeclarationName Name = FieldInSpec->getDeclName();
5426 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
5427
5428 SmallVector<NamedDecl *, 2> FoundDecls;
5429 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
5430 EXPECT_EQ(FoundDecls.size(), 1u);
5431 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
5432
5433 auto Res = LT.lookup(TemplateDC, Name);
5434 ASSERT_EQ(Res.size(), 1u);
5435 EXPECT_EQ(*Res.begin(), FieldInTemplate);
5436
5437 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
5438 FoundDecls);
5439 EXPECT_EQ(FoundDecls.size(), 1u);
5440 EXPECT_EQ(FoundDecls[0], FieldInSpec);
5441
5442 Res = LT.lookup(cast<DeclContext>(Spec), Name);
5443 ASSERT_EQ(Res.size(), 1u);
5444 EXPECT_EQ(*Res.begin(), FieldInSpec);
5445}
5446
5447TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
5448 TranslationUnitDecl *ToTU = getToTuDecl(
5449 R"(
5450 class Y { template <class T> friend void F(); };
5451 )",
5452 Lang_CXX);
5453
5454 ASTImporterLookupTable LT(*ToTU);
5455 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
5456 ToTU, functionTemplateDecl(hasName("F")));
5457 DeclarationName Name = F->getDeclName();
5458 auto Res = LT.lookup(ToTU, Name);
5459 EXPECT_EQ(Res.size(), 2u);
5460 EXPECT_EQ(Res.count(F), 1u);
5461 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5462}
5463
5464TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
5465 TranslationUnitDecl *ToTU = getToTuDecl(
5466 R"(
5467 struct X;
5468 struct A {
5469 friend struct X;
5470 };
5471 struct B {
5472 friend struct X;
5473 };
5474 )",
5475 Lang_CXX);
5476
5477 ASTImporterLookupTable LT(*ToTU);
5478 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
5479 ToTU, cxxRecordDecl(hasName("X")));
5480 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5481 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5482 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
5483 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
5484 ASSERT_EQ(RD0, RD1);
5485 ASSERT_EQ(RD1, X);
5486
5487 DeclarationName Name = X->getDeclName();
5488 auto Res = LT.lookup(ToTU, Name);
5489 EXPECT_EQ(Res.size(), 1u);
5490 EXPECT_EQ(*Res.begin(), X);
5491}
5492
5493TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
5494 TranslationUnitDecl *ToTU = getToTuDecl(
5495 R"(
5496 enum E {
5497 A,
5498 B
5499 };
5500 )",
5501 Lang_C);
5502
5503 ASTImporterLookupTable LT(*ToTU);
5504 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
5505 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
5506 ToTU, enumConstantDecl(hasName("A")));
5507
5508 DeclarationName Name = A->getDeclName();
5509 // Redecl context is the TU.
5510 ASSERT_EQ(E->getRedeclContext(), ToTU);
5511
5512 SmallVector<NamedDecl *, 2> FoundDecls;
5513 // Normal lookup finds in the DC.
5514 E->localUncachedLookup(Name, FoundDecls);
5515 EXPECT_EQ(FoundDecls.size(), 1u);
5516
5517 // Normal lookup finds in the Redecl context.
5518 ToTU->localUncachedLookup(Name, FoundDecls);
5519 EXPECT_EQ(FoundDecls.size(), 1u);
5520
5521 // Import specific lookup finds in the DC.
5522 auto Res = LT.lookup(E, Name);
5523 ASSERT_EQ(Res.size(), 1u);
5524 EXPECT_EQ(*Res.begin(), A);
5525
5526 // Import specific lookup finds in the Redecl context.
5527 Res = LT.lookup(ToTU, Name);
5528 ASSERT_EQ(Res.size(), 1u);
5529 EXPECT_EQ(*Res.begin(), A);
5530}
5531
5532TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
5533 TranslationUnitDecl *ToTU = getToTuDecl(
5534 R"(
5535 namespace N {
5536 int A;
5537 }
5538 namespace N {
5539 }
5540 )",
5541 Lang_CXX);
5542 auto *N1 =
5543 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
5544 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
5545 DeclarationName Name = A->getDeclName();
5546
5547 ASTImporterLookupTable LT(*ToTU);
5548 auto Res = LT.lookup(N1, Name);
5549 ASSERT_EQ(Res.size(), 1u);
5550 EXPECT_EQ(*Res.begin(), A);
5551}
5552
Gabor Marton19f4f392018-06-25 13:04:37 +00005553INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5554 ::testing::Values(ArgVector()), );
5555
Gabor Marton5254e642018-06-27 13:32:50 +00005556INSTANTIATE_TEST_CASE_P(
5557 ParameterizedTests, CanonicalRedeclChain,
5558 ::testing::Values(ArgVector()),);
5559
Gabor Marton0e04ebd2019-02-11 10:27:58 +00005560// FIXME This test is disabled currently, upcoming patches will make it
5561// possible to enable.
5562TEST_P(ASTImporterOptionSpecificTestBase,
5563 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
5564 Decl *FromTU = getTuDecl(
5565 R"(
5566 namespace NS {
5567 struct X;
5568 struct Y {
5569 static const int I = 3;
5570 };
5571 }
5572 namespace NS {
5573 struct X { // <--- To be imported
5574 void method(int i = Y::I) {}
5575 int f;
5576 };
5577 }
5578 )",
5579 Lang_CXX);
5580 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5581 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5582 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
5583 FromTU,
5584 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
5585 ASSERT_NE(FromFwd, FromDef);
5586 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
5587 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
5588 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
5589
5590 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
5591 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
5592 EXPECT_NE(ToFwd, ToDef);
5593 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
5594 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
5595 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
5596 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5597 // We expect no (ODR) warning during the import.
5598 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5599}
5600
Gabor Martone331e632019-02-18 13:09:27 +00005601struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
5602
5603TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
5604 Decl *ToTU = getToTuDecl(
5605 R"(
5606 class X {
5607 template <typename T> friend void foo();
5608 };
5609 )",
5610 Lang_CXX);
5611 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
5612 ToTU, functionTemplateDecl(hasName("foo")));
5613
5614 Decl *FromTU = getTuDecl(
5615 R"(
5616 template <typename T> void foo();
5617 )",
5618 Lang_CXX);
5619 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
5620 FromTU, functionTemplateDecl(hasName("foo")));
5621 auto *Imported = Import(FromFoo, Lang_CXX);
5622
Gabor Marton16d98c22019-03-07 13:01:51 +00005623 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00005624}
5625
Gabor Marton54058b52018-12-17 13:53:12 +00005626INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5627 DefaultTestValuesForRunOptions, );
5628
Gabor Marton19f4f392018-06-25 13:04:37 +00005629INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5630 DefaultTestValuesForRunOptions, );
5631
5632INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5633 DefaultTestValuesForRunOptions, );
5634
5635INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5636 DefaultTestValuesForRunOptions, );
5637
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005638INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005639 DefaultTestValuesForRunOptions, );
5640
Raphael Isemanne9bc35f2019-04-29 21:02:35 +00005641INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
5642 DefaultTestValuesForRunOptions, );
5643
Gabor Marton19f4f392018-06-25 13:04:37 +00005644INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5645 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005646
Gabor Martone331e632019-02-18 13:09:27 +00005647INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5648 DefaultTestValuesForRunOptions, );
5649
Gabor Marton54058b52018-12-17 13:53:12 +00005650INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005651 DefaultTestValuesForRunOptions, );
5652
Gabor Marton54058b52018-12-17 13:53:12 +00005653INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005654 DefaultTestValuesForRunOptions, );
5655
Gabor Marton7df342a2018-12-17 12:42:12 +00005656INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5657 DefaultTestValuesForRunOptions, );
5658
Gabor Marton5254e642018-06-27 13:32:50 +00005659INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5660 ImportFunctionTemplateSpecializations,
5661 DefaultTestValuesForRunOptions, );
5662
Gabor Martonac3a5d62018-09-17 12:04:52 +00005663INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5664 DefaultTestValuesForRunOptions, );
5665
5666INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5667 DefaultTestValuesForRunOptions, );
5668
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005669} // end namespace ast_matchers
5670} // end namespace clang