blob: d6bd13498567f7061fb19066f0910a20d42f605c [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 *>(
Peter Szecsidedda6f2018-03-30 22:03:29 +000047 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
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>
92 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
93 NodeType Node) {
94 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
Gabor Marton19f4f392018-06-25 13:04:37 +0000103 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000104
Gabor Marton19f4f392018-06-25 13:04:37 +0000105 // This should dump source locations and assert if some source locations
106 // were not imported.
107 SmallString<1024> ImportChecker;
108 llvm::raw_svector_ostream ToNothing(ImportChecker);
109 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000110
Gabor Marton19f4f392018-06-25 13:04:37 +0000111 // This traverses the AST to catch certain bugs like poorly or not
112 // implemented subtrees.
113 Imported->dump(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000114
Gabor Marton19f4f392018-06-25 13:04:37 +0000115 return Imported;
116 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000117
Gabor Marton19f4f392018-06-25 13:04:37 +0000118 template <typename NodeType>
119 testing::AssertionResult
120 testImport(const std::string &FromCode, const ArgVector &FromArgs,
121 const std::string &ToCode, const ArgVector &ToArgs,
122 MatchVerifier<NodeType> &Verifier,
123 const BindableMatcher<NodeType> &SearchMatcher,
124 const BindableMatcher<NodeType> &VerificationMatcher) {
125 const char *const InputFileName = "input.cc";
126 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000127
Gabor Marton19f4f392018-06-25 13:04:37 +0000128 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
129 FromCode, FromArgs, InputFileName),
130 ToAST = tooling::buildASTFromCodeWithArgs(
131 ToCode, ToArgs, OutputFileName);
132
133 ASTContext &FromCtx = FromAST->getASTContext(),
134 &ToCtx = ToAST->getASTContext();
135
136 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
137 FromAST->getFileManager(), false);
138
139 auto FoundNodes = match(SearchMatcher, FromCtx);
140 if (FoundNodes.size() != 1)
141 return testing::AssertionFailure()
142 << "Multiple potential nodes were found!";
143
144 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
145 if (!ToImport)
146 return testing::AssertionFailure() << "Node type mismatch!";
147
148 // Sanity check: the node being imported should match in the same way as
149 // the result node.
150 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
151 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
152
153 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
154 if (!Imported)
155 return testing::AssertionFailure() << "Import failed, nullptr returned!";
156
Bill Wendling8003edc2018-11-09 00:41:36 +0000157
Gabor Marton19f4f392018-06-25 13:04:37 +0000158 return Verifier.match(Imported, WrapperMatcher);
159 }
160
161 template <typename NodeType>
162 testing::AssertionResult
163 testImport(const std::string &FromCode, const ArgVector &FromArgs,
164 const std::string &ToCode, const ArgVector &ToArgs,
165 MatchVerifier<NodeType> &Verifier,
166 const BindableMatcher<NodeType> &VerificationMatcher) {
167 return testImport(
168 FromCode, FromArgs, ToCode, ToArgs, Verifier,
169 translationUnitDecl(
170 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
171 VerificationMatcher);
172 }
173
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000174protected:
175 ArgVector getExtraArgs() const override { return GetParam(); }
176
Gabor Marton19f4f392018-06-25 13:04:37 +0000177public:
178
179 /// Test how AST node named "declToImport" located in the translation unit
180 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
181 /// The verification is done by running AMatcher over the imported node.
182 template <typename NodeType, typename MatcherType>
183 void testImport(const std::string &FromCode, Language FromLang,
184 const std::string &ToCode, Language ToLang,
185 MatchVerifier<NodeType> &Verifier,
186 const MatcherType &AMatcher) {
187 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
188 ToArgs = getArgVectorForLanguage(ToLang);
189 EXPECT_TRUE(
190 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
191 }
192
193 struct ImportAction {
194 StringRef FromFilename;
195 StringRef ToFilename;
196 // FIXME: Generalize this to support other node kinds.
197 BindableMatcher<Decl> ImportPredicate;
198
199 ImportAction(StringRef FromFilename, StringRef ToFilename,
200 DeclarationMatcher ImportPredicate)
201 : FromFilename(FromFilename), ToFilename(ToFilename),
202 ImportPredicate(ImportPredicate) {}
203
204 ImportAction(StringRef FromFilename, StringRef ToFilename,
205 const std::string &DeclName)
206 : FromFilename(FromFilename), ToFilename(ToFilename),
207 ImportPredicate(namedDecl(hasName(DeclName))) {}
208 };
209
210 using SingleASTUnit = std::unique_ptr<ASTUnit>;
211 using AllASTUnits = StringMap<SingleASTUnit>;
212
213 struct CodeEntry {
214 std::string CodeSample;
215 Language Lang;
216 };
217
218 using CodeFiles = StringMap<CodeEntry>;
219
220 /// Builds an ASTUnit for one potential compile options set.
221 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
222 ArgVector Args = getArgVectorForLanguage(CE.Lang);
223 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
224 EXPECT_TRUE(AST.get());
225 return AST;
226 }
227
228 /// Test an arbitrary sequence of imports for a set of given in-memory files.
229 /// The verification is done by running VerificationMatcher against a
230 /// specified AST node inside of one of given files.
231 /// \param CodeSamples Map whose key is the file name and the value is the
232 /// file content.
233 /// \param ImportActions Sequence of imports. Each import in sequence
234 /// specifies "from file" and "to file" and a matcher that is used for
235 /// searching a declaration for import in "from file".
236 /// \param FileForFinalCheck Name of virtual file for which the final check is
237 /// applied.
238 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
239 /// FileForFinalCheck for which the verification will be done.
240 /// \param VerificationMatcher Matcher that will be used for verification
241 /// after all imports in sequence are done.
242 void testImportSequence(const CodeFiles &CodeSamples,
243 const std::vector<ImportAction> &ImportActions,
244 StringRef FileForFinalCheck,
245 BindableMatcher<Decl> FinalSelectPredicate,
246 BindableMatcher<Decl> VerificationMatcher) {
247 AllASTUnits AllASTs;
248 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
249 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
250
251 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
252 if (!AllASTs.count(Filename)) {
253 auto Found = CodeSamples.find(Filename);
254 assert(Found != CodeSamples.end() && "Wrong file for import!");
255 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
256 }
257 };
258
259 for (const ImportAction &Action : ImportActions) {
260 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
261 GenASTsIfNeeded(FromFile);
262 GenASTsIfNeeded(ToFile);
263
264 ASTUnit *From = AllASTs[FromFile].get();
265 ASTUnit *To = AllASTs[ToFile].get();
266
267 // Create a new importer if needed.
268 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
269 if (!ImporterRef)
270 ImporterRef.reset(new ASTImporter(
271 To->getASTContext(), To->getFileManager(), From->getASTContext(),
272 From->getFileManager(), false));
273
274 // Find the declaration and import it.
275 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
276 From->getASTContext());
277 EXPECT_TRUE(FoundDecl.size() == 1);
278 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
279 auto Imported = importNode(From, To, *ImporterRef, ToImport);
280 EXPECT_TRUE(Imported);
281 }
282
283 // Find the declaration and import it.
284 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
285 AllASTs[FileForFinalCheck]->getASTContext());
286 EXPECT_TRUE(FoundDecl.size() == 1);
287 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
288 MatchVerifier<Decl> Verifier;
289 EXPECT_TRUE(
290 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
291 }
292};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000293
Gabor Martonf086fa82018-07-17 12:06:36 +0000294template <typename T> RecordDecl *getRecordDecl(T *D) {
295 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
296 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000297}
Gabor Martonf086fa82018-07-17 12:06:36 +0000298
Peter Szecsidedda6f2018-03-30 22:03:29 +0000299// This class provides generic methods to write tests which can check internal
Balazs Keri21f938c2018-07-02 14:14:07 +0000300// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000301// this fixture makes it possible to import from several "From" contexts.
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000302class ASTImporterTestBase : public CompilerOptionSpecificTest {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000303
304 const char *const InputFileName = "input.cc";
305 const char *const OutputFileName = "output.cc";
306
307 // Buffer for the To context, must live in the test scope.
308 std::string ToCode;
309
Gabor Marton26f72a92018-07-12 09:42:05 +0000310 // Represents a "From" translation unit and holds an importer object which we
311 // use to import from this translation unit.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000312 struct TU {
313 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000314 std::string Code;
315 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000316 std::unique_ptr<ASTUnit> Unit;
317 TranslationUnitDecl *TUDecl = nullptr;
Gabor Marton26f72a92018-07-12 09:42:05 +0000318 std::unique_ptr<ASTImporter> Importer;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000319 TU(StringRef Code, StringRef FileName, ArgVector Args)
320 : Code(Code), FileName(FileName),
321 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
322 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000323 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
324 Unit->enableSourceFileDiagnostics();
325 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000326
Gabor Marton54058b52018-12-17 13:53:12 +0000327 void lazyInitImporter(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST) {
Gabor Marton26f72a92018-07-12 09:42:05 +0000328 assert(ToAST);
329 if (!Importer) {
Gabor Marton54058b52018-12-17 13:53:12 +0000330 Importer.reset(
331 new ASTImporter(ToAST->getASTContext(), ToAST->getFileManager(),
332 Unit->getASTContext(), Unit->getFileManager(),
333 false, &LookupTable));
Gabor Marton26f72a92018-07-12 09:42:05 +0000334 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000335 assert(&ToAST->getASTContext() == &Importer->getToContext());
336 createVirtualFileIfNeeded(ToAST, FileName, Code);
337 }
338
Gabor Marton54058b52018-12-17 13:53:12 +0000339 Decl *import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
340 Decl *FromDecl) {
341 lazyInitImporter(LookupTable, ToAST);
Gabor Marton26f72a92018-07-12 09:42:05 +0000342 return Importer->Import(FromDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000343 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000344
Gabor Marton54058b52018-12-17 13:53:12 +0000345 QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
346 QualType FromType) {
347 lazyInitImporter(LookupTable, ToAST);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000348 return Importer->Import(FromType);
Gabor Marton26f72a92018-07-12 09:42:05 +0000349 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000350 };
351
352 // We may have several From contexts and related translation units. In each
353 // AST, the buffers for the source are handled via references and are set
354 // during the creation of the AST. These references must point to a valid
355 // buffer until the AST is alive. Thus, we must use a list in order to avoid
356 // moving of the stored objects because that would mean breaking the
357 // references in the AST. By using a vector a move could happen when the
358 // vector is expanding, with the list we won't have these issues.
359 std::list<TU> FromTUs;
360
Gabor Marton54058b52018-12-17 13:53:12 +0000361 // Initialize the lookup table if not initialized already.
362 void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
363 assert(ToTU);
364 if (!LookupTablePtr)
365 LookupTablePtr = llvm::make_unique<ASTImporterLookupTable>(*ToTU);
366 }
367
368 void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000369 if (ToAST)
370 return;
371 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton54058b52018-12-17 13:53:12 +0000372 // Source code must be a valid live buffer through the tests lifetime.
373 ToCode = ToSrcCode;
Gabor Marton6e1510c2018-07-12 11:50:21 +0000374 // Build the AST from an empty file.
Gabor Marton54058b52018-12-17 13:53:12 +0000375 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000376 ToAST->enableSourceFileDiagnostics();
Gabor Marton54058b52018-12-17 13:53:12 +0000377 lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
Gabor Marton6e1510c2018-07-12 11:50:21 +0000378 }
379
380 TU *findFromTU(Decl *From) {
381 // Create a virtual file in the To Ctx which corresponds to the file from
382 // which we want to import the `From` Decl. Without this source locations
383 // will be invalid in the ToCtx.
384 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
385 return E.TUDecl == From->getTranslationUnitDecl();
386 });
387 assert(It != FromTUs.end());
388 return &*It;
389 }
390
Gabor Marton54058b52018-12-17 13:53:12 +0000391protected:
392
393 std::unique_ptr<ASTImporterLookupTable> LookupTablePtr;
394
Peter Szecsidedda6f2018-03-30 22:03:29 +0000395public:
396 // We may have several From context but only one To context.
397 std::unique_ptr<ASTUnit> ToAST;
398
Peter Szecsidedda6f2018-03-30 22:03:29 +0000399 // Creates an AST both for the From and To source code and imports the Decl
400 // of the identifier into the To context.
401 // Must not be called more than once within the same test.
402 std::tuple<Decl *, Decl *>
403 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
404 Language ToLang, StringRef Identifier = DeclToImportID) {
405 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
406 ToArgs = getArgVectorForLanguage(ToLang);
407
408 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
409 TU &FromTU = FromTUs.back();
410
Peter Szecsidedda6f2018-03-30 22:03:29 +0000411 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000412 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000413
Gabor Marton26f72a92018-07-12 09:42:05 +0000414 ASTContext &FromCtx = FromTU.Unit->getASTContext();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000415
Peter Szecsidedda6f2018-03-30 22:03:29 +0000416 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
417 assert(ImportedII && "Declaration with the given identifier "
418 "should be specified in test!");
419 DeclarationName ImportDeclName(ImportedII);
Gabor Marton54058b52018-12-17 13:53:12 +0000420 SmallVector<NamedDecl *, 1> FoundDecls;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000421 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
422 FoundDecls);
423
424 assert(FoundDecls.size() == 1);
425
Gabor Marton54058b52018-12-17 13:53:12 +0000426 Decl *Imported =
427 FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
Gabor Marton26f72a92018-07-12 09:42:05 +0000428
Peter Szecsidedda6f2018-03-30 22:03:29 +0000429 assert(Imported);
430 return std::make_tuple(*FoundDecls.begin(), Imported);
431 }
432
Gabor Marton9581c332018-05-23 13:53:36 +0000433 // Creates a TU decl for the given source code which can be used as a From
434 // context. May be called several times in a given test (with different file
435 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000436 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
437 StringRef FileName = "input.cc") {
438 assert(
439 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
440 return E.FileName == FileName;
441 }) == FromTUs.end());
442
443 ArgVector Args = getArgVectorForLanguage(Lang);
444 FromTUs.emplace_back(SrcCode, FileName, Args);
445 TU &Tu = FromTUs.back();
446
447 return Tu.TUDecl;
448 }
449
Gabor Marton9581c332018-05-23 13:53:36 +0000450 // Creates the To context with the given source code and returns the TU decl.
451 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
452 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton9581c332018-05-23 13:53:36 +0000453 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000454 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Gabor Marton9581c332018-05-23 13:53:36 +0000455 return ToAST->getASTContext().getTranslationUnitDecl();
456 }
457
Peter Szecsidedda6f2018-03-30 22:03:29 +0000458 // Import the given Decl into the ToCtx.
459 // May be called several times in a given test.
460 // The different instances of the param From may have different ASTContext.
461 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000462 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000463 TU *FromTU = findFromTU(From);
Gabor Marton54058b52018-12-17 13:53:12 +0000464 assert(LookupTablePtr);
465 return FromTU->import(*LookupTablePtr, ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000466 }
467
Gabor Marton458d1452019-02-14 13:07:03 +0000468 template <class DeclT> DeclT *Import(DeclT *From, Language Lang) {
469 return cast_or_null<DeclT>(Import(cast<Decl>(From), Lang));
470 }
471
Gabor Marton6e1510c2018-07-12 11:50:21 +0000472 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000473 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000474 TU *FromTU = findFromTU(TUDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000475 assert(LookupTablePtr);
476 return FromTU->import(*LookupTablePtr, ToAST.get(), FromType);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000477 }
478
Peter Szecsidedda6f2018-03-30 22:03:29 +0000479 ~ASTImporterTestBase() {
480 if (!::testing::Test::HasFailure()) return;
481
482 for (auto &Tu : FromTUs) {
483 assert(Tu.Unit);
484 llvm::errs() << "FromAST:\n";
485 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
486 llvm::errs() << "\n";
487 }
488 if (ToAST) {
489 llvm::errs() << "ToAST:\n";
490 ToAST->getASTContext().getTranslationUnitDecl()->dump();
491 }
492 }
493};
494
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000495class ASTImporterOptionSpecificTestBase
496 : public ASTImporterTestBase,
497 public ::testing::WithParamInterface<ArgVector> {
498protected:
499 ArgVector getExtraArgs() const override { return GetParam(); }
500};
501
Gabor Marton19f4f392018-06-25 13:04:37 +0000502struct ImportExpr : TestImportBase {};
503struct ImportType : TestImportBase {};
504struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000505
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000506struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +0000507
508TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
509 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
510 auto Pattern = functionDecl(hasName("f"));
511 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
512
513 auto Redecls = getCanonicalForwardRedeclChain(D0);
514 ASSERT_EQ(Redecls.size(), 1u);
515 EXPECT_EQ(D0, Redecls[0]);
516}
517
518TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
519 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
520 auto Pattern = functionDecl(hasName("f"));
521 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
522 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
523 FunctionDecl *D1 = D2->getPreviousDecl();
524
525 auto Redecls = getCanonicalForwardRedeclChain(D0);
526 ASSERT_EQ(Redecls.size(), 3u);
527 EXPECT_EQ(D0, Redecls[0]);
528 EXPECT_EQ(D1, Redecls[1]);
529 EXPECT_EQ(D2, Redecls[2]);
530}
531
532TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
533 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
534 auto Pattern = functionDecl(hasName("f"));
535 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
536 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
537 FunctionDecl *D1 = D2->getPreviousDecl();
538
539 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
540 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
541 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
542
543 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
544 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
545}
546
Gabor Marton19f4f392018-06-25 13:04:37 +0000547TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000548 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000549 testImport(
550 "void declToImport() { (void)\"foo\"; }",
551 Lang_CXX, "", Lang_CXX, Verifier,
552 functionDecl(hasDescendant(
553 stringLiteral(hasType(asString("const char [4]"))))));
554 testImport(
555 "void declToImport() { (void)L\"foo\"; }",
556 Lang_CXX, "", Lang_CXX, Verifier,
557 functionDecl(hasDescendant(
558 stringLiteral(hasType(asString("const wchar_t [4]"))))));
559 testImport(
560 "void declToImport() { (void) \"foo\" \"bar\"; }",
561 Lang_CXX, "", Lang_CXX, Verifier,
562 functionDecl(hasDescendant(
563 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000564}
565
Tom Roeder521f0042019-02-26 19:26:41 +0000566TEST_P(ImportExpr, ImportChooseExpr) {
567 MatchVerifier<Decl> Verifier;
568
569 // This case tests C code that is not condition-dependent and has a true
570 // condition.
571 testImport(
572 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
573 Lang_C, "", Lang_C, Verifier,
574 functionDecl(hasDescendant(chooseExpr())));
575}
576
Gabor Marton19f4f392018-06-25 13:04:37 +0000577TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000578 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000579 testImport(
580 "void declToImport() { (void)__null; }",
581 Lang_CXX, "", Lang_CXX, Verifier,
582 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000583}
584
Gabor Marton19f4f392018-06-25 13:04:37 +0000585TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000586 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000587 testImport(
588 "void declToImport() { (void)nullptr; }",
589 Lang_CXX11, "", Lang_CXX11, Verifier,
590 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000591}
592
593
Gabor Marton19f4f392018-06-25 13:04:37 +0000594TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000595 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000596 testImport(
597 "void declToImport() { (void)1.0; }",
598 Lang_C, "", Lang_C, Verifier,
599 functionDecl(hasDescendant(
600 floatLiteral(equals(1.0), hasType(asString("double"))))));
601 testImport(
602 "void declToImport() { (void)1.0e-5f; }",
603 Lang_C, "", Lang_C, Verifier,
604 functionDecl(hasDescendant(
605 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000606}
607
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000608TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
609 MatchVerifier<Decl> Verifier;
610 testImport(
611 "void declToImport() { (void)1.0i; }",
612 Lang_CXX14, "", Lang_CXX14, Verifier,
613 functionDecl(hasDescendant(imaginaryLiteral())));
614}
615
Gabor Marton19f4f392018-06-25 13:04:37 +0000616TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000617 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000618 testImport(
619 "void declToImport() {"
620 " struct s { int x; long y; unsigned z; }; "
621 " (void)(struct s){ 42, 0L, 1U }; }",
622 Lang_CXX, "", Lang_CXX, Verifier,
623 functionDecl(hasDescendant(
624 compoundLiteralExpr(
625 hasType(asString("struct s")),
626 has(initListExpr(
627 hasType(asString("struct s")),
628 has(integerLiteral(
629 equals(42), hasType(asString("int")))),
630 has(integerLiteral(
631 equals(0), hasType(asString("long")))),
632 has(integerLiteral(
633 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000634}
635
Gabor Marton19f4f392018-06-25 13:04:37 +0000636TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000637 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000638 testImport(
639 "class declToImport { void f() { (void)this; } };",
640 Lang_CXX, "", Lang_CXX, Verifier,
641 cxxRecordDecl(
642 hasMethod(
643 hasDescendant(
644 cxxThisExpr(
645 hasType(
646 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000647}
648
Gabor Marton19f4f392018-06-25 13:04:37 +0000649TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000650 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000651 testImport(
652 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
653 Lang_C, "", Lang_C, Verifier,
654 functionDecl(hasDescendant(
655 atomicExpr(
656 has(ignoringParenImpCasts(
657 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
658 hasType(asString("int *"))))),
659 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000660}
661
Gabor Marton19f4f392018-06-25 13:04:37 +0000662TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000663 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000664 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000665 "void declToImport() { loop: goto loop; (void)&&loop; }",
666 Lang_C, "", Lang_C, Verifier,
667 functionDecl(
668 hasDescendant(
669 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
670 hasDescendant(
671 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000672}
673
674AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
675 internal::Matcher<NamedDecl>, InnerMatcher) {
676 const NamedDecl *Template = Node.getTemplatedDecl();
677 return Template && InnerMatcher.matches(*Template, Finder, Builder);
678}
679
Gabor Marton19f4f392018-06-25 13:04:37 +0000680TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000681 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000682 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000683 "template<typename T> class dummy { void f() { dummy X(*this); } };"
684 "typedef dummy<int> declToImport;"
685 "template class dummy<int>;",
686 Lang_CXX, "", Lang_CXX, Verifier,
687 typedefDecl(hasType(templateSpecializationType(
688 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
689 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
690 hasName("f"),
691 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
692 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
693 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000694 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000695}
696
Gabor Marton19f4f392018-06-25 13:04:37 +0000697TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000698 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000699 testImport(
700 "void declToImport() { int b; switch (b) { case 1: break; } }",
701 Lang_C, "", Lang_C, Verifier,
702 functionDecl(hasDescendant(
703 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000704}
705
Gabor Marton19f4f392018-06-25 13:04:37 +0000706TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000707 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000708 testImport(
709 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
710 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000711 functionDecl(hasDescendant(
712 varDecl(
713 hasName("C"),
714 hasType(asString("int")),
715 hasInitializer(
716 stmtExpr(
717 hasAnySubstatement(declStmt(hasSingleDecl(
718 varDecl(
719 hasName("X"),
720 hasType(asString("int")),
721 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000722 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000723 hasDescendant(
724 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000725}
726
Gabor Marton19f4f392018-06-25 13:04:37 +0000727TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000728 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000729 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000730 "void declToImport() { (void)(true ? 1 : -5); }",
731 Lang_CXX, "", Lang_CXX, Verifier,
732 functionDecl(hasDescendant(
733 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000734 hasCondition(cxxBoolLiteral(equals(true))),
735 hasTrueExpression(integerLiteral(equals(1))),
736 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000737 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
738 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000739}
740
Gabor Marton19f4f392018-06-25 13:04:37 +0000741TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000742 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000743 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000744 "void declToImport() { (void)(1 ?: -5); }",
745 Lang_CXX, "", Lang_CXX, Verifier,
746 functionDecl(hasDescendant(
747 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000748 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000749 implicitCastExpr(
750 hasSourceExpression(opaqueValueExpr(
751 hasSourceExpression(integerLiteral(equals(1))))),
752 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000753 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000754 opaqueValueExpr(
755 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000756 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000757 unaryOperator(
758 hasOperatorName("-"),
759 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000760}
761
Gabor Marton19f4f392018-06-25 13:04:37 +0000762TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000763 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000764 testImport(
765 "void declToImport() {"
766 " struct point { double x; double y; };"
767 " struct point ptarray[10] = "
768 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
769 Lang_C, "", Lang_C, Verifier,
770 functionDecl(hasDescendant(
771 initListExpr(
772 has(designatedInitExpr(
773 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000774 hasDescendant(floatLiteral(equals(1.0))),
775 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000776 has(designatedInitExpr(
777 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000778 hasDescendant(floatLiteral(equals(2.0))),
779 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000780 has(designatedInitExpr(
781 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000782 hasDescendant(floatLiteral(equals(1.0))),
783 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000784}
785
Gabor Marton19f4f392018-06-25 13:04:37 +0000786TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000787 MatchVerifier<Decl> Verifier;
788 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000789 testImport(
790 "void declToImport() { (void)__func__; }",
791 Lang_CXX, "", Lang_CXX, Verifier,
792 functionDecl(hasDescendant(
793 predefinedExpr(
794 hasType(
795 asString("const char [13]")),
796 has(stringLiteral(hasType(
797 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000798}
799
Gabor Marton19f4f392018-06-25 13:04:37 +0000800TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000801 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000802 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000803 "void declToImport() {"
804 " struct point { double x; double y; };"
805 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
806 " [0].x = 1.0 }; }",
807 Lang_CXX, "", Lang_CXX, Verifier,
808 functionDecl(hasDescendant(
809 initListExpr(
810 has(
811 cxxConstructExpr(
812 requiresZeroInitialization())),
813 has(
814 initListExpr(
815 hasType(asString("struct point")),
816 has(floatLiteral(equals(1.0))),
817 has(implicitValueInitExpr(
818 hasType(asString("double")))))),
819 has(
820 initListExpr(
821 hasType(asString("struct point")),
822 has(floatLiteral(equals(2.0))),
823 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000824}
825
826
Aleksei Sidorina693b372016-09-28 10:16:56 +0000827const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
828
Gabor Marton19f4f392018-06-25 13:04:37 +0000829TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000830 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000831 testImport(
832 "void declToImport(__builtin_va_list list, ...) {"
833 " (void)__builtin_va_arg(list, int); }",
834 Lang_CXX, "", Lang_CXX, Verifier,
835 functionDecl(hasDescendant(
836 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000837}
838
Gabor Marton19f4f392018-06-25 13:04:37 +0000839TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000840 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000841 testImport(
842 "struct C {};"
843 "void declToImport() { C c = C(); }",
844 Lang_CXX, "", Lang_CXX, Verifier,
845 functionDecl(hasDescendant(
846 exprWithCleanups(has(cxxConstructExpr(
847 has(materializeTemporaryExpr(has(implicitCastExpr(
848 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000849}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000850
Gabor Marton19f4f392018-06-25 13:04:37 +0000851TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000852 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000853 testImport(
854 "void declToImport() { typedef _Atomic(int) a_int; }",
855 Lang_CXX11, "", Lang_CXX11, Verifier,
856 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000857}
858
Gabor Marton19f4f392018-06-25 13:04:37 +0000859TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000860 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000861 testImport(
862 "template <typename T> void declToImport() { };",
863 Lang_CXX, "", Lang_CXX, Verifier,
864 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000865}
866
Gabor Marton19f4f392018-06-25 13:04:37 +0000867TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000868 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000869 testImport(
870 "template <typename T> struct C { T t; };"
871 "template <typename T> void declToImport() {"
872 " C<T> d;"
873 " (void)d.t;"
874 "}"
875 "void instantiate() { declToImport<int>(); }",
876 Lang_CXX, "", Lang_CXX, Verifier,
877 functionTemplateDecl(hasDescendant(
878 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
879 testImport(
880 "template <typename T> struct C { T t; };"
881 "template <typename T> void declToImport() {"
882 " C<T> d;"
883 " (void)(&d)->t;"
884 "}"
885 "void instantiate() { declToImport<int>(); }",
886 Lang_CXX, "", Lang_CXX, Verifier,
887 functionTemplateDecl(hasDescendant(
888 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000889}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000890
Gabor Marton19f4f392018-06-25 13:04:37 +0000891TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000892 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000893 testImport(
894 "template <int K>"
895 "struct dummy { static const int i = K; };"
896 "template <int K> using dummy2 = dummy<K>;"
897 "int declToImport() { return dummy2<3>::i; }",
898 Lang_CXX11, "", Lang_CXX11, Verifier,
899 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000900 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000901 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
902}
903
904const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
905 varTemplateSpecializationDecl;
906
Gabor Marton19f4f392018-06-25 13:04:37 +0000907TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000908 MatchVerifier<Decl> Verifier;
909 testImport(
910 "template <typename T>"
911 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000912 "void declToImport() { (void)pi<int>; }",
913 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000914 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000915 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000916 unless(hasAncestor(translationUnitDecl(has(varDecl(
917 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000918}
919
Gabor Marton19f4f392018-06-25 13:04:37 +0000920TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000921 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000922 testImport(
923 "template <typename... Args>"
924 "struct dummy {"
925 " dummy(Args... args) {}"
926 " static const int i = 4;"
927 "};"
928 "int declToImport() { return dummy<int>::i; }",
929 Lang_CXX11, "", Lang_CXX11, Verifier,
930 functionDecl(hasDescendant(
931 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000932}
933
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000934const internal::VariadicDynCastAllOfMatcher<Type,
935 DependentTemplateSpecializationType>
936 dependentTemplateSpecializationType;
937
Gabor Marton19f4f392018-06-25 13:04:37 +0000938TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000939 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000940 testImport(
941 "template<typename T>"
942 "struct A;"
943 "template<typename T>"
944 "struct declToImport {"
945 " typename A<T>::template B<T> a;"
946 "};",
947 Lang_CXX, "", Lang_CXX, Verifier,
948 classTemplateDecl(has(cxxRecordDecl(has(
949 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000950}
951
952const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
953 sizeOfPackExpr;
954
Gabor Marton19f4f392018-06-25 13:04:37 +0000955TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000956 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000957 testImport(
958 "template <typename... Ts>"
959 "void declToImport() {"
960 " const int i = sizeof...(Ts);"
961 "};"
962 "void g() { declToImport<int>(); }",
963 Lang_CXX11, "", Lang_CXX11, Verifier,
964 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000965 testImport(
966 "template <typename... Ts>"
967 "using X = int[sizeof...(Ts)];"
968 "template <typename... Us>"
969 "struct Y {"
970 " X<Us..., int, double, int, Us...> f;"
971 "};"
972 "Y<float, int> declToImport;",
973 Lang_CXX11, "", Lang_CXX11, Verifier,
974 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
975 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
976}
977
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000978/// \brief Matches __builtin_types_compatible_p:
979/// GNU extension to check equivalent types
980/// Given
981/// \code
982/// __builtin_types_compatible_p(int, int)
983/// \endcode
984// will generate TypeTraitExpr <...> 'int'
985const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
986
Gabor Marton19f4f392018-06-25 13:04:37 +0000987TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000988 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000989 testImport(
990 "void declToImport() { "
991 " (void)__builtin_types_compatible_p(int, int);"
992 "}",
993 Lang_C, "", Lang_C, Verifier,
994 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000995}
996
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000997const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
998
Gabor Marton19f4f392018-06-25 13:04:37 +0000999TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001000 MatchVerifier<Decl> Verifier;
1001 testImport(
1002 "namespace std { class type_info {}; }"
1003 "void declToImport() {"
1004 " int x;"
1005 " auto a = typeid(int); auto b = typeid(x);"
1006 "}",
1007 Lang_CXX11, "", Lang_CXX11, Verifier,
1008 functionDecl(
1009 hasDescendant(varDecl(
1010 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
1011 hasDescendant(varDecl(
1012 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
1013}
1014
Gabor Marton19f4f392018-06-25 13:04:37 +00001015TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001016 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001017 testImport(
1018 "template<typename T> struct declToImport {"
1019 " void m() { (void)__is_pod(T); }"
1020 "};"
1021 "void f() { declToImport<int>().m(); }",
1022 Lang_CXX11, "", Lang_CXX11, Verifier,
1023 classTemplateDecl(has(cxxRecordDecl(has(
1024 functionDecl(hasDescendant(
1025 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001026}
Gabor Horvath7a91c082017-11-14 11:30:38 +00001027
Gabor Marton6e1510c2018-07-12 11:50:21 +00001028TEST_P(ImportDecl, ImportRecordDeclInFunc) {
1029 MatchVerifier<Decl> Verifier;
1030 testImport("int declToImport() { "
1031 " struct data_t {int a;int b;};"
1032 " struct data_t d;"
1033 " return 0;"
1034 "}",
1035 Lang_C, "", Lang_C, Verifier,
1036 functionDecl(hasBody(compoundStmt(
1037 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
1038}
1039
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001040TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001041 Decl *FromTU = getTuDecl("int declToImport() { "
1042 " struct data_t {int a;int b;};"
1043 " struct data_t d;"
1044 " return 0;"
1045 "}",
1046 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +00001047 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +00001048 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
1049 ASSERT_TRUE(FromVar);
1050 auto ToType =
1051 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
1052 EXPECT_FALSE(ToType.isNull());
1053}
1054
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001055TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001056 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +00001057 Decl *FromTU = getTuDecl(
1058 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1059 Lang_C, "input.c");
1060 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1061 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001062 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001063 auto *To = Import(From, Lang_C);
1064 EXPECT_EQ(To, nullptr);
1065}
1066
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001067TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001068 Decl *FromTU = getTuDecl(
1069 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1070 "int declToImport(){ return NONAME_SIZEOF(int); }",
1071 Lang_C, "input.c");
1072 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1073 FromTU, functionDecl(hasName("declToImport")));
1074 ASSERT_TRUE(From);
1075 auto *To = Import(From, Lang_C);
1076 ASSERT_TRUE(To);
1077 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1078 To, functionDecl(hasName("declToImport"),
1079 hasDescendant(unaryExprOrTypeTraitExpr()))));
1080}
1081
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001082TEST_P(ASTImporterOptionSpecificTestBase,
1083 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001084 // This construct is not supported by ASTImporter.
1085 Decl *FromTU = getTuDecl(
1086 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1087 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1088 Lang_C, "input.c");
1089 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1090 FromTU, functionDecl(hasName("declToImport")));
1091 ASSERT_TRUE(From);
1092 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001093 EXPECT_EQ(To, nullptr);
1094}
1095
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001096const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1097 cxxPseudoDestructorExpr;
1098
Gabor Marton19f4f392018-06-25 13:04:37 +00001099TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001100 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001101 testImport(
1102 "typedef int T;"
1103 "void declToImport(int *p) {"
1104 " T t;"
1105 " p->T::~T();"
1106 "}",
1107 Lang_CXX, "", Lang_CXX, Verifier,
1108 functionDecl(hasDescendant(
1109 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001110}
1111
Gabor Marton19f4f392018-06-25 13:04:37 +00001112TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001113 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001114 testImport(
1115 "namespace foo { int bar; }"
1116 "void declToImport() { using foo::bar; }",
1117 Lang_CXX, "", Lang_CXX, Verifier,
1118 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001119}
1120
1121/// \brief Matches shadow declarations introduced into a scope by a
1122/// (resolved) using declaration.
1123///
1124/// Given
1125/// \code
1126/// namespace n { int f; }
1127/// namespace declToImport { using n::f; }
1128/// \endcode
1129/// usingShadowDecl()
1130/// matches \code f \endcode
1131const internal::VariadicDynCastAllOfMatcher<Decl,
1132 UsingShadowDecl> usingShadowDecl;
1133
Gabor Marton19f4f392018-06-25 13:04:37 +00001134TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001135 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001136 testImport(
1137 "namespace foo { int bar; }"
1138 "namespace declToImport { using foo::bar; }",
1139 Lang_CXX, "", Lang_CXX, Verifier,
1140 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001141}
1142
Gabor Marton19f4f392018-06-25 13:04:37 +00001143TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001144 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001145 testImport(
1146 "template<typename T> int foo();"
1147 "template <typename T> void declToImport() {"
1148 " (void)::foo<T>;"
1149 " (void)::template foo<T>;"
1150 "}"
1151 "void instantiate() { declToImport<int>(); }",
1152 Lang_CXX, "", Lang_CXX, Verifier,
1153 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001154}
1155
Gabor Marton19f4f392018-06-25 13:04:37 +00001156TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001157 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001158 testImport(
1159 "template <typename T> struct C { T t; };"
1160 "template <typename T> void declToImport() {"
1161 " C<T> d;"
1162 " d.t = T();"
1163 "}"
1164 "void instantiate() { declToImport<int>(); }",
1165 Lang_CXX, "", Lang_CXX, Verifier,
1166 functionTemplateDecl(hasDescendant(
1167 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1168 testImport(
1169 "template <typename T> struct C { T t; };"
1170 "template <typename T> void declToImport() {"
1171 " C<T> d;"
1172 " (&d)->t = T();"
1173 "}"
1174 "void instantiate() { declToImport<int>(); }",
1175 Lang_CXX, "", Lang_CXX, Verifier,
1176 functionTemplateDecl(hasDescendant(
1177 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001178}
1179
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001180/// Check that function "declToImport()" (which is the templated function
1181/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1182/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001183TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001184 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001185 testImport(
1186 "template <typename T> void declToImport() { T a = 1; }"
1187 "void instantiate() { declToImport<int>(); }",
1188 Lang_CXX, "", Lang_CXX, Verifier,
1189 functionTemplateDecl(hasAncestor(translationUnitDecl(
1190 unless(has(functionDecl(hasName("declToImport"))))))));
1191 testImport(
1192 "template <typename T> struct declToImport { T t; };"
1193 "void instantiate() { declToImport<int>(); }",
1194 Lang_CXX, "", Lang_CXX, Verifier,
1195 classTemplateDecl(hasAncestor(translationUnitDecl(
1196 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001197}
1198
Gabor Marton19f4f392018-06-25 13:04:37 +00001199TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001200 MatchVerifier<Decl> Verifier;
1201 auto Code =
1202 R"s(
1203 struct declToImport {
1204 template <typename T0> struct X;
1205 template <typename T0> struct X<T0 *> {};
1206 };
1207 )s";
1208 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1209 recordDecl(has(classTemplateDecl()),
1210 has(classTemplateSpecializationDecl())));
1211}
1212
Gabor Marton19f4f392018-06-25 13:04:37 +00001213TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001214 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001215 testImport(
1216 "class declToImport {"
1217 " void f() { *this = declToImport(); }"
1218 "};",
1219 Lang_CXX, "", Lang_CXX, Verifier,
1220 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1221 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001222}
1223
Gabor Marton19f4f392018-06-25 13:04:37 +00001224TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001225 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001226 testImport(
1227 "template<typename T, int Size> class declToImport {"
1228 " T data[Size];"
1229 "};",
1230 Lang_CXX, "", Lang_CXX, Verifier,
1231 classTemplateDecl(has(cxxRecordDecl(
1232 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001233}
1234
Balazs Keri5f4fd8b2019-03-14 14:20:23 +00001235TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1236 Decl *FromTU = getTuDecl(
1237 "class A { public: static int X; }; void f() { (void)A::X; }", Lang_CXX);
1238 auto From = FirstDeclMatcher<FunctionDecl>().match(
1239 FromTU, functionDecl(hasName("f")));
1240 ASSERT_TRUE(From);
1241 ASSERT_TRUE(
1242 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1243 ->getSubExpr()
1244 ->getBeginLoc()
1245 .isValid());
1246 FunctionDecl *To = Import(From, Lang_CXX);
1247 ASSERT_TRUE(To);
1248 ASSERT_TRUE(
1249 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1250 ->getSubExpr()
1251 ->getBeginLoc()
1252 .isValid());
1253}
1254
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001255TEST_P(ASTImporterOptionSpecificTestBase,
1256 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001257 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1258 auto From =
1259 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1260 ASSERT_TRUE(From);
1261 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1262 ASSERT_TRUE(To);
1263 Decl *ToTemplated = To->getTemplatedDecl();
1264 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1265 EXPECT_TRUE(ToTemplated1);
1266 EXPECT_EQ(ToTemplated1, ToTemplated);
1267}
1268
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001269TEST_P(ASTImporterOptionSpecificTestBase,
1270 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001271 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1272 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1273 FromTU, functionTemplateDecl());
1274 ASSERT_TRUE(From);
1275 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1276 ASSERT_TRUE(To);
1277 Decl *ToTemplated = To->getTemplatedDecl();
1278 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1279 EXPECT_TRUE(ToTemplated1);
1280 EXPECT_EQ(ToTemplated1, ToTemplated);
1281}
1282
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001283TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001284 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1285 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1286 auto FromFT =
1287 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1288 ASSERT_TRUE(FromFT);
1289
1290 auto ToTemplated =
1291 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1292 EXPECT_TRUE(ToTemplated);
1293 auto ToTU = ToTemplated->getTranslationUnitDecl();
1294 auto ToFT =
1295 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1296 EXPECT_TRUE(ToFT);
1297}
1298
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001299TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001300 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001301 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1302 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1303 FromTU, functionTemplateDecl());
1304 ASSERT_TRUE(FromFT);
1305
1306 auto ToTemplated =
1307 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1308 EXPECT_TRUE(ToTemplated);
1309 auto ToTU = ToTemplated->getTranslationUnitDecl();
1310 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1311 ToTU, functionTemplateDecl());
1312 EXPECT_TRUE(ToFT);
1313}
1314
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001315TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001316 auto Code =
1317 R"(
1318 namespace x {
1319 template<class X> struct S1{};
1320 template<class X> struct S2{};
1321 template<class X> struct S3{};
1322 }
1323 )";
1324 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1325 auto FromNs =
1326 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1327 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1328 ASSERT_TRUE(ToNs);
1329 auto From =
1330 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1331 classTemplateDecl(
1332 hasName("S2")));
1333 auto To =
1334 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1335 classTemplateDecl(
1336 hasName("S2")));
1337 ASSERT_TRUE(From);
1338 ASSERT_TRUE(To);
1339 auto ToTemplated = To->getTemplatedDecl();
1340 auto ToTemplated1 =
1341 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1342 EXPECT_TRUE(ToTemplated1);
1343 ASSERT_EQ(ToTemplated1, ToTemplated);
1344}
1345
Tom Roeder521f0042019-02-26 19:26:41 +00001346TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1347 // This tests the import of isConditionTrue directly to make sure the importer
1348 // gets it right.
1349 Decl *From, *To;
1350 std::tie(From, To) = getImportedDecl(
1351 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1352 Lang_C, "", Lang_C);
1353
1354 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1355 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1356
1357 const ChooseExpr *FromChooseExpr =
1358 selectFirst<ChooseExpr>("choose", FromResults);
1359 ASSERT_TRUE(FromChooseExpr);
1360
1361 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1362 ASSERT_TRUE(ToChooseExpr);
1363
1364 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1365 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1366 ToChooseExpr->isConditionDependent());
1367}
1368
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001369TEST_P(ASTImporterOptionSpecificTestBase,
1370 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001371 Decl *From, *To;
1372 std::tie(From, To) = getImportedDecl(
1373 R"(
1374 template <typename T> struct X {};
1375
1376 void declToImport(int y, X<int> &x) {}
1377
1378 template <> struct X<int> {
1379 void g() {
1380 X<int> x;
1381 declToImport(0, x);
1382 }
1383 };
1384 )",
1385 Lang_CXX, "", Lang_CXX);
1386
1387 MatchVerifier<Decl> Verifier;
1388 auto Matcher = functionDecl(hasName("declToImport"),
1389 parameterCountIs(2),
1390 hasParameter(0, hasName("y")),
1391 hasParameter(1, hasName("x")),
1392 hasParameter(1, hasType(asString("X<int> &"))));
1393 ASSERT_TRUE(Verifier.match(From, Matcher));
1394 EXPECT_TRUE(Verifier.match(To, Matcher));
1395}
1396
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001397TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001398 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1399 Decl *From, *To;
1400 std::tie(From, To) =
1401 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1402 "void instantiate() { declToImport<int>(); }",
1403 Lang_CXX, "", Lang_CXX);
1404
1405 auto Check = [](Decl *D) -> bool {
1406 auto TU = D->getTranslationUnitDecl();
1407 for (auto Child : TU->decls()) {
1408 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1409 if (FD->getNameAsString() == "declToImport") {
1410 GTEST_NONFATAL_FAILURE_(
1411 "TU should not contain any FunctionDecl with name declToImport");
1412 return false;
1413 }
1414 }
1415 }
1416 return true;
1417 };
1418
1419 ASSERT_TRUE(Check(From));
1420 EXPECT_TRUE(Check(To));
1421}
1422
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001423TEST_P(ASTImporterOptionSpecificTestBase,
1424 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001425 Decl *From, *To;
1426 std::tie(From, To) =
1427 getImportedDecl("template <typename T> struct declToImport { T t; };"
1428 "void instantiate() { declToImport<int>(); }",
1429 Lang_CXX, "", Lang_CXX);
1430
1431 auto Check = [](Decl *D) -> bool {
1432 auto TU = D->getTranslationUnitDecl();
1433 for (auto Child : TU->decls()) {
1434 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1435 if (RD->getNameAsString() == "declToImport") {
1436 GTEST_NONFATAL_FAILURE_(
1437 "TU should not contain any CXXRecordDecl with name declToImport");
1438 return false;
1439 }
1440 }
1441 }
1442 return true;
1443 };
1444
1445 ASSERT_TRUE(Check(From));
1446 EXPECT_TRUE(Check(To));
1447}
1448
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001449TEST_P(ASTImporterOptionSpecificTestBase,
1450 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001451 Decl *From, *To;
1452 std::tie(From, To) =
1453 getImportedDecl(
1454 "template <typename T> struct X {};"
1455 "template <typename T> using declToImport = X<T>;"
1456 "void instantiate() { declToImport<int> a; }",
1457 Lang_CXX11, "", Lang_CXX11);
1458
1459 auto Check = [](Decl *D) -> bool {
1460 auto TU = D->getTranslationUnitDecl();
1461 for (auto Child : TU->decls()) {
1462 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1463 if (AD->getNameAsString() == "declToImport") {
1464 GTEST_NONFATAL_FAILURE_(
1465 "TU should not contain any TypeAliasDecl with name declToImport");
1466 return false;
1467 }
1468 }
1469 }
1470 return true;
1471 };
1472
1473 ASSERT_TRUE(Check(From));
1474 EXPECT_TRUE(Check(To));
1475}
1476
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001477TEST_P(ASTImporterOptionSpecificTestBase,
1478 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001479
1480 Decl *From, *To;
1481 std::tie(From, To) = getImportedDecl(
1482 R"(
1483 template<class T>
1484 class Base {};
1485 class declToImport : public Base<declToImport> {};
1486 )",
1487 Lang_CXX, "", Lang_CXX);
1488
1489 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1490 auto Pattern =
1491 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1492 ASSERT_TRUE(
1493 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1494 EXPECT_TRUE(
1495 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1496
1497 // Check that the ClassTemplateSpecializationDecl is the child of the
1498 // ClassTemplateDecl.
1499 Pattern = translationUnitDecl(has(classTemplateDecl(
1500 hasName("Base"), has(classTemplateSpecializationDecl()))));
1501 ASSERT_TRUE(
1502 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1503 EXPECT_TRUE(
1504 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1505}
1506
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001507AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1508 size_t Index = 0;
1509 for (FieldDecl *Field : Node.fields()) {
1510 if (Index == Order.size())
1511 return false;
1512 if (Field->getName() != Order[Index])
1513 return false;
1514 ++Index;
1515 }
1516 return Index == Order.size();
1517}
1518
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001519TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001520 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1521 Decl *From, *To;
1522 std::tie(From, To) = getImportedDecl(
1523 R"(
1524 namespace NS {
1525 template<class T>
1526 class X {};
1527 template class X<int>;
1528 }
1529 )",
1530 Lang_CXX, "", Lang_CXX, "NS");
1531
1532 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1533 // ClassTemplateDecl.
1534 auto Pattern = namespaceDecl(has(classTemplateDecl(
1535 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1536 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1537 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1538
1539 // Check that the ClassTemplateSpecializationDecl is the child of the
1540 // NamespaceDecl.
1541 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1542 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1543 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1544}
1545
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001546TEST_P(ASTImporterOptionSpecificTestBase,
1547 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001548 Decl *From, *To;
1549 std::tie(From, To) =
1550 getImportedDecl(
1551 "struct declToImport { int a; int b; };",
1552 Lang_CXX11, "", Lang_CXX11);
1553
1554 MatchVerifier<Decl> Verifier;
1555 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1556 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1557}
1558
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001559TEST_P(ASTImporterOptionSpecificTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001560 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001561 Decl *From, *To;
1562 std::tie(From, To) = getImportedDecl(
1563 // The original recursive algorithm of ASTImporter first imports 'c' then
1564 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1565 R"s(
1566 struct declToImport {
1567 int a = c + b;
1568 int b = 1;
1569 int c = 2;
1570 };
1571 )s",
1572 Lang_CXX11, "", Lang_CXX11);
1573
1574 MatchVerifier<Decl> Verifier;
1575 ASSERT_TRUE(
1576 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1577 EXPECT_TRUE(
1578 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1579}
1580
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001581TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001582 Decl *From, *To;
1583 std::tie(From, To) = getImportedDecl(
1584 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001585 struct declToImport {
1586 };
1587 )",
1588 Lang_CXX, "", Lang_CXX);
1589
1590 MatchVerifier<Decl> Verifier;
1591 // Match the implicit Decl.
1592 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1593 ASSERT_TRUE(Verifier.match(From, Matcher));
1594 EXPECT_TRUE(Verifier.match(To, Matcher));
1595}
1596
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001597TEST_P(ASTImporterOptionSpecificTestBase,
1598 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001599 Decl *From, *To;
1600 std::tie(From, To) = getImportedDecl(
1601 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001602 template <typename U>
1603 struct declToImport {
1604 };
1605 )",
1606 Lang_CXX, "", Lang_CXX);
1607
1608 MatchVerifier<Decl> Verifier;
1609 // Match the implicit Decl.
1610 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1611 ASSERT_TRUE(Verifier.match(From, Matcher));
1612 EXPECT_TRUE(Verifier.match(To, Matcher));
1613}
1614
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001615TEST_P(ASTImporterOptionSpecificTestBase,
1616 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001617 Decl *From, *To;
1618 std::tie(From, To) = getImportedDecl(
1619 R"(
1620 template<class T>
1621 class Base {};
1622 class declToImport : public Base<declToImport> {};
1623 )",
1624 Lang_CXX, "", Lang_CXX);
1625
1626 auto hasImplicitClass = has(cxxRecordDecl());
1627 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1628 hasName("Base"),
1629 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1630 ASSERT_TRUE(
1631 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1632 EXPECT_TRUE(
1633 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1634}
1635
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001636TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001637 Decl *From, *To;
1638 std::tie(From, To) =
1639 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1640
1641 MatchVerifier<Decl> Verifier;
1642 auto Matcher = functionDecl();
1643 ASSERT_TRUE(Verifier.match(From, Matcher));
1644 EXPECT_TRUE(Verifier.match(To, Matcher));
1645 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1646}
1647
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001648TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001649 Decl *FromTU = getTuDecl(
1650 R"(
1651 struct X {};
1652 void operator<<(int, X);
1653 )",
1654 Lang_CXX);
1655 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1656 const Decl *To = Import(From, Lang_CXX);
1657 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1658}
1659
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001660TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001661 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1662 Decl *From, *To;
1663 std::tie(From, To) = getImportedDecl(
1664 R"(
1665 template<class T>
1666 class Base { int a; };
1667 class declToImport : Base<declToImport> {};
1668 )",
1669 Lang_CXX, "", Lang_CXX);
1670
1671 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1672 hasName("Base"),
1673 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1674 ASSERT_TRUE(
1675 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1676 EXPECT_TRUE(
1677 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1678}
1679
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001680TEST_P(ASTImporterOptionSpecificTestBase,
1681 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001682 {
1683 Decl *FromTU = getTuDecl(
1684 R"(
1685 template <typename T>
1686 struct B;
1687 )",
1688 Lang_CXX, "input0.cc");
1689 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1690 FromTU, classTemplateDecl(hasName("B")));
1691
1692 Import(FromD, Lang_CXX);
1693 }
1694
1695 {
1696 Decl *FromTU = getTuDecl(
1697 R"(
1698 template <typename T>
1699 struct B {
1700 void f();
1701 };
1702 )",
1703 Lang_CXX, "input1.cc");
1704 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1705 FromTU, functionDecl(hasName("f")));
1706 Import(FromD, Lang_CXX);
1707 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1708 FromTU, classTemplateDecl(hasName("B")));
1709 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1710 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1711 }
1712}
1713
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001714TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001715 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1716 Decl *ToTU = getToTuDecl(
1717 R"(
1718 template <typename T>
1719 struct B {
1720 void f();
1721 };
1722
1723 template <typename T>
1724 struct B;
1725 )",
1726 Lang_CXX);
1727 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1728 [](const ClassTemplateDecl *T) {
1729 return T->isThisDeclarationADefinition();
1730 })
1731 .match(ToTU, classTemplateDecl()));
1732
1733 Decl *FromTU = getTuDecl(
1734 R"(
1735 template <typename T>
1736 struct B {
1737 void f();
1738 };
1739 )",
1740 Lang_CXX, "input1.cc");
1741 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1742 FromTU, classTemplateDecl(hasName("B")));
1743
1744 Import(FromD, Lang_CXX);
1745
1746 // We should have only one definition.
1747 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1748 [](const ClassTemplateDecl *T) {
1749 return T->isThisDeclarationADefinition();
1750 })
1751 .match(ToTU, classTemplateDecl()));
1752}
1753
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001754TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001755 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1756 Decl *ToTU = getToTuDecl(
1757 R"(
1758 struct B {
1759 void f();
1760 };
1761
1762 struct B;
1763 )",
1764 Lang_CXX);
1765 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001766 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001767
1768 Decl *FromTU = getTuDecl(
1769 R"(
1770 struct B {
1771 void f();
1772 };
1773 )",
1774 Lang_CXX, "input1.cc");
1775 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1776 FromTU, cxxRecordDecl(hasName("B")));
1777
1778 Import(FromD, Lang_CXX);
1779
1780 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001781 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001782}
1783
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001784static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1785 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1786 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1787 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1788 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1789}
1790static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1791 SourceManager &SM1, SourceManager &SM2) {
1792 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1793 FullSourceLoc{ Range2.getBegin(), SM2 });
1794 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1795 FullSourceLoc{ Range2.getEnd(), SM2 });
1796}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001797TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001798 Decl *FromTU = getTuDecl(
1799 R"(
1800 #define MFOO(arg) arg = arg + 1
1801
1802 void foo() {
1803 int a = 5;
1804 MFOO(a);
1805 }
1806 )",
1807 Lang_CXX);
1808 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1809 auto ToD = Import(FromD, Lang_CXX);
1810
1811 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1812 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1813 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1814 auto FromRHS =
1815 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1816
1817 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1818 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1819 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1820 FromSM);
1821 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1822 FromSM);
1823 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1824 FromSM);
1825}
1826
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001827TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001828 Decl *FromTU = getTuDecl(
1829 R"(
1830 #define FUNC_INT void declToImport
1831 #define FUNC FUNC_INT
1832 FUNC(int a);
1833 )",
1834 Lang_CXX);
1835 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1836 auto ToD = Import(FromD, Lang_CXX);
1837
1838 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1839 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1840 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1841 FromSM);
1842}
1843
Gabor Marton9581c332018-05-23 13:53:36 +00001844TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001845 ASTImporterOptionSpecificTestBase,
1846 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001847 Decl *ToTU = getToTuDecl(
1848 R"(
1849 template <typename T>
1850 struct B;
1851
1852 template <>
1853 struct B<int> {};
1854
1855 template <>
1856 struct B<int>;
1857 )",
1858 Lang_CXX);
1859 // We should have only one definition.
1860 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1861 [](const ClassTemplateSpecializationDecl *T) {
1862 return T->isThisDeclarationADefinition();
1863 })
1864 .match(ToTU, classTemplateSpecializationDecl()));
1865
1866 Decl *FromTU = getTuDecl(
1867 R"(
1868 template <typename T>
1869 struct B;
1870
1871 template <>
1872 struct B<int> {};
1873 )",
1874 Lang_CXX, "input1.cc");
1875 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1876 FromTU, classTemplateSpecializationDecl(hasName("B")));
1877
1878 Import(FromD, Lang_CXX);
1879
1880 // We should have only one definition.
1881 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1882 [](const ClassTemplateSpecializationDecl *T) {
1883 return T->isThisDeclarationADefinition();
1884 })
1885 .match(ToTU, classTemplateSpecializationDecl()));
1886}
1887
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001888TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001889 Decl *FromTU = getTuDecl(
1890 R"(
1891 struct { int a; int b; } object0 = { 2, 3 };
1892 struct { int x; int y; int z; } object1;
1893 )",
1894 Lang_CXX, "input0.cc");
1895
Gabor Marton0bebf952018-07-05 09:51:13 +00001896 auto *Obj0 =
1897 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1898 auto *From0 = getRecordDecl(Obj0);
1899 auto *Obj1 =
1900 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1901 auto *From1 = getRecordDecl(Obj1);
1902
1903 auto *To0 = Import(From0, Lang_CXX);
1904 auto *To1 = Import(From1, Lang_CXX);
1905
1906 EXPECT_TRUE(To0);
1907 EXPECT_TRUE(To1);
1908 EXPECT_NE(To0, To1);
1909 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1910}
1911
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001912TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001913 auto *Code =
1914 R"(
1915 struct X {
1916 struct { int a; };
1917 struct { int b; };
1918 };
1919 )";
1920 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1921
1922 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1923
1924 auto *X0 =
1925 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1926 auto *X1 =
1927 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1928 Import(X0, Lang_C);
1929 Import(X1, Lang_C);
1930
1931 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1932 // We expect no (ODR) warning during the import.
1933 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1934 EXPECT_EQ(1u,
1935 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1936}
1937
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001938TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001939 Decl *FromTU0 = getTuDecl(
1940 R"(
1941 struct X {
1942 struct { int a; };
1943 struct { int b; };
1944 };
1945 )",
1946 Lang_C, "input0.c");
1947
1948 Decl *FromTU1 = getTuDecl(
1949 R"(
1950 struct X { // reversed order
1951 struct { int b; };
1952 struct { int a; };
1953 };
1954 )",
1955 Lang_C, "input1.c");
1956
1957 auto *X0 =
1958 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1959 auto *X1 =
1960 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1961 Import(X0, Lang_C);
1962 Import(X1, Lang_C);
1963
1964 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1965 // We expect one (ODR) warning during the import.
1966 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1967 EXPECT_EQ(2u,
1968 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1969}
1970
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001971TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001972 auto Pattern = varDecl(hasName("x"));
1973 VarDecl *Imported1;
1974 {
1975 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1976 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1977 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1978 }
1979 VarDecl *Imported2;
1980 {
1981 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1982 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1983 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1984 }
1985 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1986 EXPECT_FALSE(Imported2->isUsed(false));
1987 {
1988 Decl *FromTU =
1989 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001990 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1991 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001992 Import(FromD, Lang_CXX);
1993 }
1994 EXPECT_TRUE(Imported2->isUsed(false));
1995}
1996
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001997TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001998 auto Pattern = varDecl(hasName("x"));
1999 VarDecl *ExistingD;
2000 {
2001 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
2002 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2003 }
2004 EXPECT_FALSE(ExistingD->isUsed(false));
2005 {
2006 Decl *FromTU = getTuDecl(
2007 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
2008 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2009 FromTU, functionDecl(hasName("f")));
2010 Import(FromD, Lang_CXX);
2011 }
2012 EXPECT_TRUE(ExistingD->isUsed(false));
2013}
2014
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002015TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00002016 auto Pattern = varDecl(hasName("a"));
2017 VarDecl *ExistingD;
2018 {
2019 Decl *ToTU = getToTuDecl(
2020 R"(
2021 struct A {
2022 static const int a = 1;
2023 };
2024 )", Lang_CXX);
2025 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2026 }
2027 EXPECT_FALSE(ExistingD->isUsed(false));
2028 {
2029 Decl *FromTU = getTuDecl(
2030 R"(
2031 struct A {
2032 static const int a = 1;
2033 };
2034 const int *f() { return &A::a; } // requires storage,
2035 // thus used flag will be set
2036 )", Lang_CXX, "input1.cc");
2037 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
2038 FromTU, functionDecl(hasName("f")));
2039 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2040 ASSERT_TRUE(FromD->isUsed(false));
2041 Import(FromFunD, Lang_CXX);
2042 }
2043 EXPECT_TRUE(ExistingD->isUsed(false));
2044}
2045
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002046TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00002047 auto Pattern = varDecl(hasName("x"));
2048
2049 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
2050 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2051
2052 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
2053
2054 ASSERT_FALSE(Imported1->isUsed(false));
2055
2056 FromD->setIsUsed();
2057 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2058
2059 EXPECT_EQ(Imported1, Imported2);
2060 EXPECT_TRUE(Imported2->isUsed(false));
2061}
2062
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002063struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00002064
Gabor Marton5254e642018-06-27 13:32:50 +00002065TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002066 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2067 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002068 auto *From =
2069 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002070
Gabor Marton5254e642018-06-27 13:32:50 +00002071 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002072 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2073
Gabor Marton5254e642018-06-27 13:32:50 +00002074 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2075 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2076 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2077 EXPECT_TRUE(ImportedD == To0);
2078 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2079 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2080 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002081}
2082
2083TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2084 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2085 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002086 auto *From =
2087 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002088
Gabor Marton5254e642018-06-27 13:32:50 +00002089 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002090 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2091
Gabor Marton5254e642018-06-27 13:32:50 +00002092 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2093 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2094 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2095 EXPECT_TRUE(ImportedD == To1);
2096 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2097 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2098 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002099}
2100
Peter Szecsidedda6f2018-03-30 22:03:29 +00002101TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2102 auto Code =
2103 R"(
2104 struct B { virtual void f(); };
2105 void B::f() {}
2106 struct D : B { void f(); };
2107 )";
2108 auto Pattern =
2109 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2110 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2111 CXXMethodDecl *Proto =
2112 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2113
2114 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2115 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2116 EXPECT_EQ(To->size_overridden_methods(), 1u);
2117}
2118
2119TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2120 auto Code =
2121 R"(
2122 struct B { virtual void f(); };
2123 void B::f() {}
2124 )";
2125 auto Pattern =
2126 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2127 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2128 CXXMethodDecl *Proto =
2129 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2130 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2131
2132 ASSERT_TRUE(Proto->isVirtual());
2133 ASSERT_TRUE(Def->isVirtual());
2134 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2135 EXPECT_TRUE(To->isVirtual());
2136}
2137
Gabor Marton5254e642018-06-27 13:32:50 +00002138TEST_P(ImportFunctions,
2139 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2140 Decl *ToTU = getToTuDecl(
2141 R"(
2142 void f() {}
2143 void f();
2144 )",
2145 Lang_CXX);
2146 ASSERT_EQ(1u,
2147 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2148 return FD->doesThisDeclarationHaveABody();
2149 }).match(ToTU, functionDecl()));
2150
2151 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2152 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2153
2154 Import(FromD, Lang_CXX);
2155
2156 EXPECT_EQ(1u,
2157 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2158 return FD->doesThisDeclarationHaveABody();
2159 }).match(ToTU, functionDecl()));
2160}
2161
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002162TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2163 auto Code =
2164 R"(
2165 struct B { virtual void f(); };
2166 struct D:B { void f(); };
2167 )";
2168 auto BFP =
2169 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2170 auto DFP =
2171 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2172
2173 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2174 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2175 Import(DF, Lang_CXX);
2176
2177 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2178 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2179 Import(BF, Lang_CXX);
2180
2181 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2182
2183 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2184 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2185}
2186
2187TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2188 auto CodeWithoutDef =
2189 R"(
2190 struct B { virtual void f(); };
2191 struct D:B { void f(); };
2192 )";
2193 auto CodeWithDef =
2194 R"(
2195 struct B { virtual void f(){}; };
2196 struct D:B { void f(){}; };
2197 )";
2198 auto BFP =
2199 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2200 auto DFP =
2201 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2202 auto BFDefP = cxxMethodDecl(
2203 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2204 auto DFDefP = cxxMethodDecl(
2205 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2206 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2207
2208 {
2209 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2210 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2211 Import(FromD, Lang_CXX);
2212 }
2213 {
2214 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2215 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2216 Import(FromB, Lang_CXX);
2217 }
2218
2219 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2220
2221 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2222 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2223 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2224 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2225 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2226}
2227
2228TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2229 auto Code =
2230 R"(
2231 struct B { virtual void f(); };
2232 struct D:B { void f(); };
2233 void B::f(){};
2234 )";
2235
2236 auto BFP =
2237 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2238 auto BFDefP = cxxMethodDecl(
2239 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2240 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2241 unless(isDefinition()));
2242
2243 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2244 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2245 Import(D, Lang_CXX);
2246
2247 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2248 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2249 Import(B, Lang_CXX);
2250
2251 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2252
2253 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2254 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2255
2256 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2257 ToTU, cxxRecordDecl(hasName("B")));
2258 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2259 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2260 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2261
2262 // The definition should be out-of-class.
2263 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2264 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2265 ToBFOutOfClass->getLexicalDeclContext());
2266 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2267 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2268
2269 // Check that the redecl chain is intact.
2270 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2271}
2272
2273TEST_P(ImportFunctions,
2274 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2275 auto CodeTU0 =
2276 R"(
2277 struct B { virtual void f(); };
2278 struct D:B { void f(); };
2279 )";
2280 auto CodeTU1 =
2281 R"(
2282 struct B { virtual void f(); };
2283 struct D:B { void f(); };
2284 void B::f(){}
2285 void D::f(){}
2286 void foo(B &b, D &d) { b.f(); d.f(); }
2287 )";
2288
2289 auto BFP =
2290 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2291 auto BFDefP = cxxMethodDecl(
2292 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2293 auto DFP =
2294 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2295 auto DFDefP = cxxMethodDecl(
2296 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2297 auto FooDef = functionDecl(hasName("foo"));
2298
2299 {
2300 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2301 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2302 Import(D, Lang_CXX);
2303 }
2304
2305 {
2306 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2307 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2308 Import(Foo, Lang_CXX);
2309 }
2310
2311 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2312
2313 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2314 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2315 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2316 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2317
2318 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2319 ToTU, cxxRecordDecl(hasName("B")));
2320 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2321 ToTU, cxxRecordDecl(hasName("D")));
2322 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2323 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2324 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2325 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2326 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2327 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2328
2329 // The definition should be out-of-class.
2330 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2331 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2332 ToBFOutOfClass->getLexicalDeclContext());
2333 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2334 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2335
2336 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2337 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2338 ToDFOutOfClass->getLexicalDeclContext());
2339 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2340 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2341
2342 // Check that the redecl chain is intact.
2343 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2344 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2345}
2346
Gabor Marton458d1452019-02-14 13:07:03 +00002347//FIXME Move these tests to a separate test file.
2348namespace TypeAndValueParameterizedTests {
2349
2350// Type parameters for type-parameterized test fixtures.
2351struct GetFunPattern {
2352 using DeclTy = FunctionDecl;
2353 BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
2354};
2355struct GetVarPattern {
2356 using DeclTy = VarDecl;
2357 BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
2358};
2359
2360// Values for the value-parameterized test fixtures.
2361// FunctionDecl:
2362auto *ExternF = "void f();";
2363auto *StaticF = "static void f();";
2364auto *AnonF = "namespace { void f(); }";
2365// VarDecl:
2366auto *ExternV = "extern int v;";
2367auto *StaticV = "static int v;";
2368auto *AnonV = "namespace { extern int v; }";
2369
2370// First value in tuple: Compile options.
2371// Second value in tuple: Source code to be used in the test.
2372using ImportVisibilityChainParams =
2373 ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
2374// Fixture to test the redecl chain of Decls with the same visibility. Gtest
2375// makes it possible to have either value-parameterized or type-parameterized
2376// fixtures. However, we cannot have both value- and type-parameterized test
2377// fixtures. This is a value-parameterized test fixture in the gtest sense. We
2378// intend to mimic gtest's type-parameters via the PatternFactory template
2379// parameter. We manually instantiate the different tests with the each types.
2380template <typename PatternFactory>
2381class ImportVisibilityChain
2382 : public ASTImporterTestBase, public ImportVisibilityChainParams {
2383protected:
2384 using DeclTy = typename PatternFactory::DeclTy;
2385 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2386 std::string getCode() const { return std::get<1>(GetParam()); }
2387 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2388
2389 // Type-parameterized test.
2390 void TypedTest_ImportChain() {
2391 std::string Code = getCode() + getCode();
2392 auto Pattern = getPattern();
2393
2394 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
2395
2396 auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
2397 auto *FromF1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
2398
2399 auto *ToF0 = Import(FromF0, Lang_CXX);
2400 auto *ToF1 = Import(FromF1, Lang_CXX);
2401
2402 EXPECT_TRUE(ToF0);
2403 ASSERT_TRUE(ToF1);
2404 EXPECT_NE(ToF0, ToF1);
2405 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2406 }
2407};
2408
2409// Manual instantiation of the fixture with each type.
2410using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
2411using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
2412// Value-parameterized test for the first type.
2413TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
2414 TypedTest_ImportChain();
2415}
2416// Value-parameterized test for the second type.
2417TEST_P(ImportVariablesVisibilityChain, ImportChain) {
2418 TypedTest_ImportChain();
2419}
2420
2421// Automatic instantiation of the value-parameterized tests.
2422INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
2423 ::testing::Combine(
2424 DefaultTestValuesForRunOptions,
2425 ::testing::Values(ExternF, StaticF, AnonF)), );
2426INSTANTIATE_TEST_CASE_P(
2427 ParameterizedTests, ImportVariablesVisibilityChain,
2428 ::testing::Combine(
2429 DefaultTestValuesForRunOptions,
2430 // There is no point to instantiate with StaticV, because in C++ we can
2431 // forward declare a variable only with the 'extern' keyword.
2432 // Consequently, each fwd declared variable has external linkage. This
2433 // is different in the C language where any declaration without an
2434 // initializer is a tentative definition, subsequent definitions may be
2435 // provided but they must have the same linkage. See also the test
2436 // ImportVariableChainInC which test for this special C Lang case.
2437 ::testing::Values(ExternV, AnonV)), );
2438
2439// First value in tuple: Compile options.
2440// Second value in tuple: Tuple with informations for the test.
2441// Code for first import (or initial code), code to import, whether the `f`
2442// functions are expected to be linked in a declaration chain.
2443// One value of this tuple is combined with every value of compile options.
2444// The test can have a single tuple as parameter only.
2445using ImportVisibilityParams = ::testing::WithParamInterface<
2446 std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
2447
2448template <typename PatternFactory>
2449class ImportVisibility
2450 : public ASTImporterTestBase,
2451 public ImportVisibilityParams {
2452protected:
2453 using DeclTy = typename PatternFactory::DeclTy;
2454 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2455 std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
2456 std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
2457 bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
2458 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2459
2460 void TypedTest_ImportAfter() {
2461 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
2462 TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2463
2464 auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
2465 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
2466
2467 auto *ToF1 = Import(FromF1, Lang_CXX);
2468
2469 ASSERT_TRUE(ToF0);
2470 ASSERT_TRUE(ToF1);
2471 EXPECT_NE(ToF0, ToF1);
2472
2473 if (shouldBeLinked())
2474 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2475 else
2476 EXPECT_FALSE(ToF1->getPreviousDecl());
2477 }
2478
2479 void TypedTest_ImportAfterImport() {
2480 TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
2481 TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2482 auto *FromF0 =
2483 FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
2484 auto *FromF1 =
2485 FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
2486 auto *ToF0 = Import(FromF0, Lang_CXX);
2487 auto *ToF1 = Import(FromF1, Lang_CXX);
2488 ASSERT_TRUE(ToF0);
2489 ASSERT_TRUE(ToF1);
2490 EXPECT_NE(ToF0, ToF1);
2491 if (shouldBeLinked())
2492 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2493 else
2494 EXPECT_FALSE(ToF1->getPreviousDecl());
2495 }
2496};
2497using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
2498using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
2499
2500// FunctionDecl.
2501TEST_P(ImportFunctionsVisibility, ImportAfter) {
2502 TypedTest_ImportAfter();
2503}
2504TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
2505 TypedTest_ImportAfterImport();
2506}
2507// VarDecl.
2508TEST_P(ImportVariablesVisibility, ImportAfter) {
2509 TypedTest_ImportAfter();
2510}
2511TEST_P(ImportVariablesVisibility, ImportAfterImport) {
2512 TypedTest_ImportAfterImport();
2513}
2514
2515bool ExpectLink = true;
2516bool ExpectNotLink = false;
2517
2518INSTANTIATE_TEST_CASE_P(
2519 ParameterizedTests, ImportFunctionsVisibility,
2520 ::testing::Combine(
2521 DefaultTestValuesForRunOptions,
2522 ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
2523 std::make_tuple(ExternF, StaticF, ExpectNotLink),
2524 std::make_tuple(ExternF, AnonF, ExpectNotLink),
2525 std::make_tuple(StaticF, ExternF, ExpectNotLink),
2526 std::make_tuple(StaticF, StaticF, ExpectNotLink),
2527 std::make_tuple(StaticF, AnonF, ExpectNotLink),
2528 std::make_tuple(AnonF, ExternF, ExpectNotLink),
2529 std::make_tuple(AnonF, StaticF, ExpectNotLink),
2530 std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
2531INSTANTIATE_TEST_CASE_P(
2532 ParameterizedTests, ImportVariablesVisibility,
2533 ::testing::Combine(
2534 DefaultTestValuesForRunOptions,
2535 ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
2536 std::make_tuple(ExternV, StaticV, ExpectNotLink),
2537 std::make_tuple(ExternV, AnonV, ExpectNotLink),
2538 std::make_tuple(StaticV, ExternV, ExpectNotLink),
2539 std::make_tuple(StaticV, StaticV, ExpectNotLink),
2540 std::make_tuple(StaticV, AnonV, ExpectNotLink),
2541 std::make_tuple(AnonV, ExternV, ExpectNotLink),
2542 std::make_tuple(AnonV, StaticV, ExpectNotLink),
2543 std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
2544
2545} // namespace TypeAndValueParameterizedTests
2546
2547TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2548 std::string Code = "static int v; static int v = 0;";
2549 auto Pattern = varDecl(hasName("v"));
2550
2551 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2552
2553 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2554 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2555
2556 auto *To0 = Import(From0, Lang_C);
2557 auto *To1 = Import(From1, Lang_C);
2558
2559 EXPECT_TRUE(To0);
2560 ASSERT_TRUE(To1);
2561 EXPECT_NE(To0, To1);
2562 EXPECT_EQ(To1->getPreviousDecl(), To0);
2563}
2564
2565TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2566 TranslationUnitDecl *FromTu = getTuDecl(
2567 "namespace NS0 { namespace { void f(); } }"
2568 "namespace NS1 { namespace { void f(); } }",
2569 Lang_CXX, "input0.cc");
2570 auto Pattern = functionDecl(hasName("f"));
2571
2572 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2573 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2574
2575 auto *ToF0 = Import(FromF0, Lang_CXX);
2576 auto *ToF1 = Import(FromF1, Lang_CXX);
2577
2578 EXPECT_TRUE(ToF0);
2579 ASSERT_TRUE(ToF1);
2580 EXPECT_NE(ToF0, ToF1);
2581 EXPECT_FALSE(ToF1->getPreviousDecl());
2582}
2583
2584TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2585 {
2586 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2587 Lang_CXX, "input0.cc");
2588 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2589 FromTU, functionDecl(hasName("g0")));
2590
2591 Import(FromD, Lang_CXX);
2592 }
2593 {
2594 Decl *FromTU =
2595 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2596 Lang_CXX, "input1.cc");
2597 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2598 FromTU, functionDecl(hasName("g1")));
2599 Import(FromD, Lang_CXX);
2600 }
2601
2602 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2603 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2604 2u);
2605}
2606
Gabor Marton302f3002019-02-15 12:04:05 +00002607TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2608 Decl *FromTU = getTuDecl(
2609 R"(
2610 void foo() {
2611 (void)[]() { ; };
2612 }
2613 )",
2614 Lang_CXX11);
2615 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2616 FromTU, functionDecl(hasName("foo")));
2617 auto *ToD = Import(FromD, Lang_CXX);
2618 EXPECT_TRUE(ToD);
2619 CXXRecordDecl *LambdaRec =
2620 cast<LambdaExpr>(cast<CStyleCastExpr>(
2621 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2622 ->getSubExpr())
2623 ->getLambdaClass();
2624 EXPECT_TRUE(LambdaRec->getDestructor());
2625}
2626
Gabor Marton5caba302019-03-07 13:38:20 +00002627TEST_P(ImportFunctions,
2628 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2629 Decl *FromTU = getTuDecl(
2630 R"(
2631 struct X {
2632 template <typename T>
2633 void foo(){}
2634 };
2635 void f() {
2636 X x;
2637 x.foo<int>();
2638 }
2639 )",
2640 Lang_CXX);
2641 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2642 FromTU, functionDecl(hasName("f")));
2643 auto *ToD = Import(FromD, Lang_CXX);
2644 EXPECT_TRUE(ToD);
2645 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2646 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2647}
2648
2649TEST_P(ImportFunctions,
2650 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2651 Decl *FromTU = getTuDecl(
2652 R"(
2653 struct X {
2654 template <typename T>
2655 void foo(){}
2656 };
2657 template <typename T>
2658 void f() {
2659 X x;
2660 x.foo<T>();
2661 }
2662 void g() {
2663 f<int>();
2664 }
2665 )",
2666 Lang_CXX);
2667 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2668 FromTU, functionDecl(hasName("g")));
2669 auto *ToD = Import(FromD, Lang_CXX);
2670 EXPECT_TRUE(ToD);
2671 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2672 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2673 ToTU, translationUnitDecl(hasDescendant(
2674 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2675}
2676
Gabor Marton5254e642018-06-27 13:32:50 +00002677struct ImportFriendFunctions : ImportFunctions {};
2678
2679TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2680 auto Pattern = functionDecl(hasName("f"));
2681
2682 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2683 "void f();",
2684 Lang_CXX,
2685 "input0.cc");
2686 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2687
2688 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2689 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2690 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2691 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2692 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2693 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2694 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2695}
2696
2697TEST_P(ImportFriendFunctions,
2698 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2699 auto Pattern = functionDecl(hasName("f"));
2700
2701 Decl *FromTU = getTuDecl("void f();"
2702 "struct X { friend void f(); };",
2703 Lang_CXX, "input0.cc");
2704 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2705
2706 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2707 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2708 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2709 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2710 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2711 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2712 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2713}
2714
2715TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2716 auto Pattern = functionDecl(hasName("f"));
2717
2718 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2719 "void f();",
2720 Lang_CXX,
2721 "input0.cc");
2722 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2723
2724 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2725 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2726 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2727 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2728 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2729 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2730 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2731}
2732
2733TEST_P(ImportFriendFunctions,
2734 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2735 auto Pattern = functionDecl(hasName("f"));
2736
2737 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2738 "void f(){}",
2739 Lang_CXX, "input0.cc");
2740 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2741
2742 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2743 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2744 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2745 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2746 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2747 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2748 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2749}
2750
Gabor Marton26f72a92018-07-12 09:42:05 +00002751// Disabled temporarily, because the new structural equivalence check
2752// (https://reviews.llvm.org/D48628) breaks it.
2753// PreviousDecl is not set because there is no structural match.
2754// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002755TEST_P(ImportFriendFunctions,
2756 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2757 auto Pattern = functionDecl(hasName("f"));
2758
2759 Decl *FromTU = getTuDecl(
2760 R"(
2761 class X;
2762 void f(X *x){}
2763 class X{
2764 friend void f(X *x);
2765 };
2766 )",
2767 Lang_CXX, "input0.cc");
2768 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2769
2770 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2771 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2772 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2773 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2774 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2775 .match(ToTU, friendDecl())
2776 ->getFriendDecl());
2777 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2778 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2779 // The parameters must refer the same type
2780 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2781 (*ImportedD->param_begin())->getOriginalType());
2782}
2783
Gabor Marton26f72a92018-07-12 09:42:05 +00002784// Disabled temporarily, because the new structural equivalence check
2785// (https://reviews.llvm.org/D48628) breaks it.
2786// PreviousDecl is not set because there is no structural match.
2787// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002788TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002789 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002790 auto Pattern = functionDecl(hasName("f"));
2791
2792 Decl *FromTU = getTuDecl(
2793 R"(
2794 class X;
2795 void f(X *x){}
2796 class X{
2797 friend void f(X *x);
2798 };
2799 )",
2800 Lang_CXX, "input0.cc");
2801 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2802
2803 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2804 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2805 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2806 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2807 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2808 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2809
2810 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2811 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2812 // The parameters must refer the same type
2813 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2814 (*ImportedD->param_begin())->getOriginalType());
2815}
2816
2817TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2818 auto Pattern = functionDecl(hasName("f"));
2819
2820 FunctionDecl *ImportedD;
2821 {
2822 Decl *FromTU =
2823 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2824 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2825 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2826 }
2827 FunctionDecl *ImportedD1;
2828 {
2829 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2830 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2831 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2832 }
2833
2834 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2835 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2836 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2837 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2838 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2839}
2840
Balazs Keri89632b82018-08-21 14:32:21 +00002841TEST_P(ImportFriendFunctions, Lookup) {
2842 auto FunctionPattern = functionDecl(hasName("f"));
2843 auto ClassPattern = cxxRecordDecl(hasName("X"));
2844
2845 TranslationUnitDecl *FromTU =
2846 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2847 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2848 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2849 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2850 {
2851 auto FromName = FromD->getDeclName();
2852 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2853 auto LookupRes = Class->noload_lookup(FromName);
2854 ASSERT_EQ(LookupRes.size(), 0u);
2855 LookupRes = FromTU->noload_lookup(FromName);
2856 ASSERT_EQ(LookupRes.size(), 1u);
2857 }
2858
2859 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2860 auto ToName = ToD->getDeclName();
2861
2862 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2863 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2864 auto LookupRes = Class->noload_lookup(ToName);
2865 EXPECT_EQ(LookupRes.size(), 0u);
2866 LookupRes = ToTU->noload_lookup(ToName);
2867 EXPECT_EQ(LookupRes.size(), 1u);
2868
2869 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2870 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2871 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2872 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2873}
2874
2875TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2876 auto FunctionPattern = functionDecl(hasName("f"));
2877 auto ClassPattern = cxxRecordDecl(hasName("X"));
2878
2879 TranslationUnitDecl *FromTU = getTuDecl(
2880 "struct X { friend void f(); };"
2881 // This proto decl makes f available to normal
2882 // lookup, otherwise it is hidden.
2883 // Normal C++ lookup (implemented in
2884 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2885 // returns the found `NamedDecl` only if the set IDNS is matched
2886 "void f();",
2887 Lang_CXX, "input0.cc");
2888 auto *FromFriend =
2889 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2890 auto *FromNormal =
2891 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2892 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2893 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2894 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2895 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2896
2897 auto FromName = FromFriend->getDeclName();
2898 auto *FromClass =
2899 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2900 auto LookupRes = FromClass->noload_lookup(FromName);
2901 ASSERT_EQ(LookupRes.size(), 0u);
2902 LookupRes = FromTU->noload_lookup(FromName);
2903 ASSERT_EQ(LookupRes.size(), 1u);
2904
2905 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2906 auto ToName = ToFriend->getDeclName();
2907
2908 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2909 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2910 LookupRes = ToClass->noload_lookup(ToName);
2911 EXPECT_EQ(LookupRes.size(), 0u);
2912 LookupRes = ToTU->noload_lookup(ToName);
2913 // Test is disabled because this result is 2.
2914 EXPECT_EQ(LookupRes.size(), 1u);
2915
2916 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2917 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2918 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2919 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2920 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2921 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2922 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2923}
2924
2925TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2926 auto FunctionPattern = functionDecl(hasName("f"));
2927 auto ClassPattern = cxxRecordDecl(hasName("X"));
2928
2929 TranslationUnitDecl *FromTU = getTuDecl(
2930 "void f();"
2931 "struct X { friend void f(); };",
2932 Lang_CXX, "input0.cc");
2933 auto *FromNormal =
2934 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2935 auto *FromFriend =
2936 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2937 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2938 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2939 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2940 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2941
2942 auto FromName = FromNormal->getDeclName();
2943 auto *FromClass =
2944 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2945 auto LookupRes = FromClass->noload_lookup(FromName);
2946 ASSERT_EQ(LookupRes.size(), 0u);
2947 LookupRes = FromTU->noload_lookup(FromName);
2948 ASSERT_EQ(LookupRes.size(), 1u);
2949
2950 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2951 auto ToName = ToNormal->getDeclName();
2952 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2953
2954 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2955 LookupRes = ToClass->noload_lookup(ToName);
2956 EXPECT_EQ(LookupRes.size(), 0u);
2957 LookupRes = ToTU->noload_lookup(ToName);
2958 EXPECT_EQ(LookupRes.size(), 1u);
2959
2960 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2961 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2962 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2963 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2964 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2965 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2966 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2967}
2968
2969TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2970 auto Pattern = functionDecl(hasName("f"));
2971
2972 TranslationUnitDecl *FromNormalTU =
2973 getTuDecl("void f();", Lang_CXX, "input0.cc");
2974 auto *FromNormalF =
2975 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2976 TranslationUnitDecl *FromFriendTU =
2977 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2978 auto *FromFriendF =
2979 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2980 auto FromNormalName = FromNormalF->getDeclName();
2981 auto FromFriendName = FromFriendF->getDeclName();
2982
2983 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2984 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2985 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2986 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2987 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2988 ASSERT_EQ(LookupRes.size(), 1u);
2989 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2990 ASSERT_EQ(LookupRes.size(), 1u);
2991
2992 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2993 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2994 auto ToName = ToNormalF->getDeclName();
2995 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2996 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2997 LookupRes = ToTU->noload_lookup(ToName);
2998 EXPECT_EQ(LookupRes.size(), 1u);
2999 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00003000
Balazs Keri89632b82018-08-21 14:32:21 +00003001 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
3002 LookupRes = ToTU->noload_lookup(ToName);
3003 EXPECT_EQ(LookupRes.size(), 1u);
3004 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3005
3006 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3007 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3008
3009 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3010 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3011}
3012
3013TEST_P(ImportFriendFunctions, ImportFriendList) {
3014 TranslationUnitDecl *FromTU = getTuDecl(
3015 "struct X { friend void f(); };"
3016 "void f();",
3017 Lang_CXX, "input0.cc");
3018 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
3019 FromTU, functionDecl(hasName("f")));
3020
3021 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3022 FromTU, cxxRecordDecl(hasName("X")));
3023 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
3024 auto FromFriends = FromClass->friends();
3025 unsigned int FrN = 0;
3026 for (auto Fr : FromFriends) {
3027 ASSERT_EQ(Fr, FromFriend);
3028 ++FrN;
3029 }
3030 ASSERT_EQ(FrN, 1u);
3031
3032 Import(FromFriendF, Lang_CXX);
3033 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3034 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3035 ToTU, cxxRecordDecl(hasName("X")));
3036 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
3037 auto ToFriends = ToClass->friends();
3038 FrN = 0;
3039 for (auto Fr : ToFriends) {
3040 EXPECT_EQ(Fr, ToFriend);
3041 ++FrN;
3042 }
3043 EXPECT_EQ(FrN, 1u);
3044}
3045
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00003046AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
3047 InnerMatcher) {
3048 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
3049 return InnerMatcher.matches(*Typedef, Finder, Builder);
3050 return false;
3051}
3052
Gabor Marton19f4f392018-06-25 13:04:37 +00003053TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00003054 CodeFiles Samples{{"main.c",
3055 {"void foo();"
3056 "void moo();"
3057 "int main() { foo(); moo(); }",
3058 Lang_C}},
3059
3060 {"foo.c",
3061 {"typedef enum { THING_VALUE } thing_t;"
3062 "void conflict(thing_t type);"
3063 "void foo() { (void)THING_VALUE; }"
3064 "void conflict(thing_t type) {}",
3065 Lang_C}},
3066
3067 {"moo.c",
3068 {"typedef enum { THING_VALUE } thing_t;"
3069 "void conflict(thing_t type);"
3070 "void moo() { conflict(THING_VALUE); }",
3071 Lang_C}}};
3072
3073 auto VerificationMatcher =
3074 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
3075 hasTypedefForAnonDecl(hasName("thing_t")));
3076
3077 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
3078 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
3079
3080 testImportSequence(
3081 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
3082 // Just check that there is only one enum decl in the result AST.
3083 "main.c", enumDecl(), VerificationMatcher);
3084
3085 // For different import order, result should be the same.
3086 testImportSequence(
3087 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
3088 // Check that there is only one enum decl in the result AST.
3089 "main.c", enumDecl(), VerificationMatcher);
3090}
3091
Peter Szecsice7f3182018-05-07 12:08:27 +00003092const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
3093 dependentScopeDeclRefExpr;
3094
Gabor Marton19f4f392018-06-25 13:04:37 +00003095TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003096 MatchVerifier<Decl> Verifier;
3097 testImport("template <typename T> struct S { static T foo; };"
3098 "template <typename T> void declToImport() {"
3099 " (void) S<T>::foo;"
3100 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00003101 "void instantiate() { declToImport<int>(); }"
3102 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00003103 Lang_CXX11, "", Lang_CXX11, Verifier,
3104 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3105 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
3106
3107 testImport("template <typename T> struct S {"
3108 "template<typename S> static void foo(){};"
3109 "};"
3110 "template <typename T> void declToImport() {"
3111 " S<T>::template foo<T>();"
3112 "}"
3113 "void instantiate() { declToImport<int>(); }",
3114 Lang_CXX11, "", Lang_CXX11, Verifier,
3115 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3116 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
3117}
3118
3119const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
3120 dependentNameType;
3121
Gabor Marton19f4f392018-06-25 13:04:37 +00003122TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003123 MatchVerifier<Decl> Verifier;
3124 testImport("template <typename T> struct declToImport {"
3125 " typedef typename T::type dependent_name;"
3126 "};",
3127 Lang_CXX11, "", Lang_CXX11, Verifier,
3128 classTemplateDecl(has(
3129 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
3130}
3131
Gabor Marton19f4f392018-06-25 13:04:37 +00003132TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003133 MatchVerifier<Decl> Verifier;
3134 testImport("struct S { template <typename T> void mem(); };"
3135 "template <typename U> void declToImport() {"
3136 " S s;"
3137 " s.mem<U>();"
3138 "}"
3139 "void instantiate() { declToImport<int>(); }",
3140 Lang_CXX11, "", Lang_CXX11, Verifier,
3141 functionTemplateDecl(has(functionDecl(has(
3142 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3143}
3144
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003145class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00003146public:
3147 static constexpr auto DefaultCode = R"(
3148 struct A { int x; };
3149 void f() {
3150 A a;
3151 A a1(a);
3152 A a2(A{});
3153 a = a1;
3154 a = A{};
3155 a.~A();
3156 })";
3157
3158 template <typename MatcherType>
3159 void testImportOf(
3160 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3161 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3162 }
3163
3164 template <typename MatcherType>
3165 void testNoImportOf(
3166 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3167 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3168 }
3169
3170private:
3171 template <typename MatcherType>
3172 void test(const MatcherType &MethodMatcher,
3173 const char *Code, unsigned int ExpectedCount) {
3174 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3175
3176 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3177 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3178 ToTU, ClassMatcher);
3179
Balazs Keri2f752ba2018-07-16 14:05:18 +00003180 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003181
3182 {
3183 CXXMethodDecl *Method =
3184 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3185 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00003186 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003187 }
3188
Balazs Keri2f752ba2018-07-16 14:05:18 +00003189 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003190
3191 Decl *ImportedClass = nullptr;
3192 {
3193 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3194 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3195 FromTU, ClassMatcher);
3196 ImportedClass = Import(FromClass, Lang_CXX11);
3197 }
3198
3199 EXPECT_EQ(ToClass, ImportedClass);
3200 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3201 ExpectedCount);
3202 }
3203};
3204
3205TEST_P(ImportImplicitMethods, DefaultConstructor) {
3206 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3207}
3208
3209TEST_P(ImportImplicitMethods, CopyConstructor) {
3210 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3211}
3212
3213TEST_P(ImportImplicitMethods, MoveConstructor) {
3214 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3215}
3216
3217TEST_P(ImportImplicitMethods, Destructor) {
3218 testImportOf(cxxDestructorDecl());
3219}
3220
3221TEST_P(ImportImplicitMethods, CopyAssignment) {
3222 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3223}
3224
3225TEST_P(ImportImplicitMethods, MoveAssignment) {
3226 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3227}
3228
3229TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3230 auto Code = R"(
3231 struct A { A() { int x; } };
3232 )";
3233 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3234}
3235
3236TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3237 auto Code = R"(
3238 struct A { A() = default; };
3239 )";
3240 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3241}
3242
3243TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3244 auto Code = R"(
3245 struct A { A() = delete; };
3246 )";
3247 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3248}
3249
3250TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3251 auto Code = R"(
3252 struct A { void f() { } };
3253 )";
3254 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3255}
3256
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003257TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003258 Decl *ToR1;
3259 {
3260 Decl *FromTU = getTuDecl(
3261 "struct A { };", Lang_CXX, "input0.cc");
3262 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3263 FromTU, cxxRecordDecl(hasName("A")));
3264
3265 ToR1 = Import(FromR, Lang_CXX);
3266 }
3267
3268 Decl *ToR2;
3269 {
3270 Decl *FromTU = getTuDecl(
3271 "struct A { };", Lang_CXX, "input1.cc");
3272 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3273 FromTU, cxxRecordDecl(hasName("A")));
3274
3275 ToR2 = Import(FromR, Lang_CXX);
3276 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003277
Balazs Keric7797c42018-07-11 09:37:24 +00003278 EXPECT_EQ(ToR1, ToR2);
3279}
3280
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003281TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003282 Decl *ToR1;
3283 {
3284 Decl *FromTU = getTuDecl(
3285 "struct A { int x; };", Lang_CXX, "input0.cc");
3286 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3287 FromTU, cxxRecordDecl(hasName("A")));
3288 ToR1 = Import(FromR, Lang_CXX);
3289 }
3290 Decl *ToR2;
3291 {
3292 Decl *FromTU = getTuDecl(
3293 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3294 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3295 FromTU, cxxRecordDecl(hasName("A")));
3296 ToR2 = Import(FromR, Lang_CXX);
3297 }
3298 EXPECT_NE(ToR1, ToR2);
3299}
3300
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003301TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003302 Decl *ToF1;
3303 {
3304 Decl *FromTU = getTuDecl(
3305 "struct A { int x; };", Lang_CXX, "input0.cc");
3306 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3307 FromTU, fieldDecl(hasName("x")));
3308 ToF1 = Import(FromF, Lang_CXX);
3309 }
3310 Decl *ToF2;
3311 {
3312 Decl *FromTU = getTuDecl(
3313 "struct A { int x; };", Lang_CXX, "input1.cc");
3314 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3315 FromTU, fieldDecl(hasName("x")));
3316 ToF2 = Import(FromF, Lang_CXX);
3317 }
3318 EXPECT_EQ(ToF1, ToF2);
3319}
3320
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003321TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003322 Decl *ToF1;
3323 {
3324 Decl *FromTU = getTuDecl(
3325 "struct A { int x; };", Lang_CXX, "input0.cc");
3326 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3327 FromTU, fieldDecl(hasName("x")));
3328 ToF1 = Import(FromF, Lang_CXX);
3329 }
3330 Decl *ToF2;
3331 {
3332 Decl *FromTU = getTuDecl(
3333 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3334 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3335 FromTU, fieldDecl(hasName("x")));
3336 ToF2 = Import(FromF, Lang_CXX);
3337 }
3338 EXPECT_NE(ToF1, ToF2);
3339}
3340
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003341TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003342 Decl *ToM1;
3343 {
3344 Decl *FromTU = getTuDecl(
3345 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3346 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3347 FromTU, functionDecl(hasName("x"), isDefinition()));
3348 ToM1 = Import(FromM, Lang_CXX);
3349 }
3350 Decl *ToM2;
3351 {
3352 Decl *FromTU = getTuDecl(
3353 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3354 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3355 FromTU, functionDecl(hasName("x"), isDefinition()));
3356 ToM2 = Import(FromM, Lang_CXX);
3357 }
3358 EXPECT_EQ(ToM1, ToM2);
3359}
3360
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003361TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003362 Decl *ToM1;
3363 {
3364 Decl *FromTU = getTuDecl(
3365 "struct A { void x(); }; void A::x() { }",
3366 Lang_CXX, "input0.cc");
3367 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3368 FromTU, functionDecl(hasName("x"), isDefinition()));
3369 ToM1 = Import(FromM, Lang_CXX);
3370 }
3371 Decl *ToM2;
3372 {
3373 Decl *FromTU = getTuDecl(
3374 "struct A { void x() const; }; void A::x() const { }",
3375 Lang_CXX, "input1.cc");
3376 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3377 FromTU, functionDecl(hasName("x"), isDefinition()));
3378 ToM2 = Import(FromM, Lang_CXX);
3379 }
3380 EXPECT_NE(ToM1, ToM2);
3381}
3382
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003383TEST_P(ASTImporterOptionSpecificTestBase,
3384 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003385 Decl *FromTU = getTuDecl(
3386 R"(
3387 struct A {
3388 struct {
3389 struct A *next;
3390 } entry0;
3391 struct {
3392 struct A *next;
3393 } entry1;
3394 };
3395 )",
3396 Lang_C, "input0.cc");
3397 auto *From =
3398 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3399
3400 Import(From, Lang_C);
3401
3402 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3403 auto *Entry0 =
3404 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3405 auto *Entry1 =
3406 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3407 auto *R0 = getRecordDecl(Entry0);
3408 auto *R1 = getRecordDecl(Entry1);
3409 EXPECT_NE(R0, R1);
3410 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3411 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3412 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3413 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3414}
3415
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003416TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003417 Decl *FromTU = getTuDecl(
3418 R"(
3419 void f(int X, int Y, bool Z) {
3420 (void)[X, Y, Z] { (void)Z; };
3421 }
3422 )",
3423 Lang_CXX11, "input0.cc");
3424 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3425 FromTU, functionDecl(hasName("f")));
3426 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3427 EXPECT_TRUE(ToF);
3428
3429 CXXRecordDecl *FromLambda =
3430 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3431 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3432
3433 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3434 EXPECT_TRUE(ToLambda);
3435
3436 // Check if the fields of the lambda class are imported in correct order.
3437 unsigned FromIndex = 0u;
3438 for (auto *FromField : FromLambda->fields()) {
3439 ASSERT_FALSE(FromField->getDeclName());
3440 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3441 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003442 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3443 EXPECT_TRUE(ToIndex);
3444 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003445 ++FromIndex;
3446 }
3447
3448 EXPECT_EQ(FromIndex, 3u);
3449}
3450
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003451TEST_P(ASTImporterOptionSpecificTestBase,
3452 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003453 std::string ClassTemplate =
3454 R"(
3455 template <typename T>
3456 struct X {
3457 int a{0}; // FieldDecl with InitListExpr
3458 X(char) : a(3) {} // (1)
3459 X(int) {} // (2)
3460 };
3461 )";
3462 Decl *ToTU = getToTuDecl(ClassTemplate +
3463 R"(
3464 void foo() {
3465 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3466 X<char> xc('c');
3467 }
3468 )", Lang_CXX11);
3469 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3470 ToTU, classTemplateSpecializationDecl(hasName("X")));
3471 // FieldDecl without InitlistExpr:
3472 auto *ToField = *ToSpec->field_begin();
3473 ASSERT_TRUE(ToField);
3474 ASSERT_FALSE(ToField->getInClassInitializer());
3475 Decl *FromTU = getTuDecl(ClassTemplate +
3476 R"(
3477 void bar() {
3478 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3479 X<char> xc(1);
3480 }
3481 )", Lang_CXX11);
3482 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3483 FromTU, classTemplateSpecializationDecl(hasName("X")));
3484 // FieldDecl with InitlistExpr:
3485 auto *FromField = *FromSpec->field_begin();
3486 ASSERT_TRUE(FromField);
3487 ASSERT_TRUE(FromField->getInClassInitializer());
3488
3489 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3490 ASSERT_TRUE(ImportedSpec);
3491 EXPECT_EQ(ImportedSpec, ToSpec);
3492 // After the import, the FieldDecl has to be merged, thus it should have the
3493 // InitListExpr.
3494 EXPECT_TRUE(ToField->getInClassInitializer());
3495}
3496
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003497TEST_P(ASTImporterOptionSpecificTestBase,
3498 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003499 std::string ClassTemplate =
3500 R"(
3501 template <typename T>
3502 struct X {
3503 void f() {}
3504 void g() {}
3505 };
3506 )";
3507 Decl *ToTU = getToTuDecl(ClassTemplate +
3508 R"(
3509 void foo() {
3510 X<char> x;
3511 x.f();
3512 }
3513 )", Lang_CXX11);
3514 Decl *FromTU = getTuDecl(ClassTemplate +
3515 R"(
3516 void bar() {
3517 X<char> x;
3518 x.g();
3519 }
3520 )", Lang_CXX11);
3521 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3522 FromTU, classTemplateSpecializationDecl(hasName("X")));
3523 auto FunPattern = functionDecl(hasName("g"),
3524 hasParent(classTemplateSpecializationDecl()));
3525 auto *FromFun =
3526 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3527 auto *ToFun =
3528 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3529 ASSERT_TRUE(FromFun->hasBody());
3530 ASSERT_FALSE(ToFun->hasBody());
3531 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3532 ASSERT_TRUE(ImportedSpec);
3533 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3534 ToTU, classTemplateSpecializationDecl(hasName("X")));
3535 EXPECT_EQ(ImportedSpec, ToSpec);
3536 EXPECT_TRUE(ToFun->hasBody());
3537}
3538
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003539TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003540 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3541 std::string ClassTemplate =
3542 R"(
3543 template <typename T>
3544 struct X {};
3545 )";
3546 Decl *ToTU = getToTuDecl(ClassTemplate +
3547 R"(
3548 template <>
3549 struct X<char> {
3550 int a;
3551 };
3552 void foo() {
3553 X<char> x;
3554 }
3555 )",
3556 Lang_CXX11);
3557 Decl *FromTU = getTuDecl(ClassTemplate +
3558 R"(
3559 template <>
3560 struct X<char> {
3561 int b;
3562 };
3563 void foo() {
3564 X<char> x;
3565 }
3566 )",
3567 Lang_CXX11);
3568 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3569 FromTU, classTemplateSpecializationDecl(hasName("X")));
3570 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3571
3572 // We expect one (ODR) warning during the import.
3573 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3574
3575 // The second specialization is different from the first, thus it violates
3576 // ODR, consequently we expect to keep the first specialization only, which is
3577 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003578 EXPECT_FALSE(ImportedSpec);
3579 EXPECT_EQ(1u,
3580 DeclCounter<ClassTemplateSpecializationDecl>().match(
3581 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003582}
3583
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003584TEST_P(ASTImporterOptionSpecificTestBase,
3585 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003586 std::string ClassTemplate =
3587 R"(
3588 template <typename T>
3589 struct X {
3590 X(char) {}
3591 X(int) {}
3592 };
3593 )";
3594 Decl *ToTU = getToTuDecl(ClassTemplate +
3595 R"(
3596 void foo() {
3597 X<char> x('c');
3598 }
3599 )", Lang_CXX11);
3600 Decl *FromTU = getTuDecl(ClassTemplate +
3601 R"(
3602 void bar() {
3603 X<char> x(1);
3604 }
3605 )", Lang_CXX11);
3606 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3607 FromTU, classTemplateSpecializationDecl(hasName("X")));
3608 // Match the void(int) ctor.
3609 auto CtorPattern =
3610 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3611 hasParent(classTemplateSpecializationDecl()));
3612 auto *FromCtor =
3613 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3614 auto *ToCtor =
3615 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3616 ASSERT_TRUE(FromCtor->hasBody());
3617 ASSERT_FALSE(ToCtor->hasBody());
3618 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3619 ASSERT_TRUE(ImportedSpec);
3620 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3621 ToTU, classTemplateSpecializationDecl(hasName("X")));
3622 EXPECT_EQ(ImportedSpec, ToSpec);
3623 EXPECT_TRUE(ToCtor->hasBody());
3624}
3625
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003626TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003627 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3628 auto Code =
3629 R"(
3630 // primary template
3631 template<class T1, class T2, int I>
3632 class A {};
3633
3634 // partial specialization
3635 template<class T, int I>
3636 class A<T, T*, I> {};
3637 )";
3638 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3639 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3640 auto *FromSpec =
3641 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3642 FromTU, classTemplatePartialSpecializationDecl());
3643 auto *ToSpec =
3644 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3645 ToTU, classTemplatePartialSpecializationDecl());
3646
3647 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3648 EXPECT_EQ(ImportedSpec, ToSpec);
3649 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3650 ToTU, classTemplatePartialSpecializationDecl()));
3651}
3652
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003653TEST_P(ASTImporterOptionSpecificTestBase,
3654 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003655 auto Code =
3656 R"(
3657 // primary template
3658 template<class T1, class T2, int I>
3659 class A {};
3660
3661 // full specialization
3662 template<>
3663 class A<int, int, 1> {};
3664 )";
3665 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3666 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3667 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3668 FromTU, classTemplateSpecializationDecl());
3669 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3670 ToTU, classTemplateSpecializationDecl());
3671
3672 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3673 EXPECT_EQ(ImportedSpec, ToSpec);
3674 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3675 ToTU, classTemplateSpecializationDecl()));
3676}
3677
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003678TEST_P(ASTImporterOptionSpecificTestBase,
3679 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003680 std::string PrimaryTemplate =
3681 R"(
3682 template<class T1, class T2, int I>
3683 class A {};
3684 )";
3685 auto PartialSpec =
3686 R"(
3687 template<class T, int I>
3688 class A<T, T*, I> {};
3689 )";
3690 auto FullSpec =
3691 R"(
3692 template<>
3693 class A<int, int, 1> {};
3694 )";
3695 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3696 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3697 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3698 FromTU, classTemplateSpecializationDecl());
3699
3700 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3701 EXPECT_TRUE(ImportedSpec);
3702 // Check the number of partial specializations.
3703 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3704 ToTU, classTemplatePartialSpecializationDecl()));
3705 // Check the number of full specializations.
3706 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3707 ToTU, classTemplateSpecializationDecl(
3708 unless(classTemplatePartialSpecializationDecl()))));
3709}
3710
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003711TEST_P(ASTImporterOptionSpecificTestBase,
3712 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003713 Decl *TU = getTuDecl(
3714 R"(
3715 const int &init();
3716 void foo() { const int &a{init()}; }
3717 )", Lang_CXX11, "input0.cc");
3718 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3719 ASSERT_TRUE(FromD->getAnyInitializer());
3720 auto *InitExpr = FromD->getAnyInitializer();
3721 ASSERT_TRUE(InitExpr);
3722 ASSERT_TRUE(InitExpr->isGLValue());
3723
3724 auto *ToD = Import(FromD, Lang_CXX11);
3725 EXPECT_TRUE(ToD);
3726 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3727 EXPECT_TRUE(ToInitExpr);
3728 EXPECT_TRUE(ToInitExpr->isGLValue());
3729}
3730
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003731struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003732
3733TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3734 Decl *FromTU = getTuDecl(
3735 R"(
3736 struct A {
3737 static const int a = 1 + 2;
3738 };
3739 const int A::a;
3740 )", Lang_CXX, "input1.cc");
3741
3742 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3743 FromTU, varDecl(hasName("a"))); // Decl with init
3744 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3745 FromTU, varDecl(hasName("a"))); // Decl with definition
3746 ASSERT_NE(FromDWithInit, FromDWithDef);
3747 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3748
3749 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3750 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3751 ASSERT_TRUE(ToD0);
3752 ASSERT_TRUE(ToD1);
3753 EXPECT_NE(ToD0, ToD1);
3754 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3755}
3756
3757TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3758 auto StructA =
3759 R"(
3760 struct A {
3761 static const int a = 1 + 2;
3762 };
3763 )";
3764 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3765 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3766 "input1.cc");
3767
3768 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3769 FromTU, varDecl(hasName("a"))); // Decl with init
3770 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3771 FromTU, varDecl(hasName("a"))); // Decl with definition
3772 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3773 ASSERT_TRUE(FromDWithInit->getInit());
3774 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3775 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3776 ASSERT_FALSE(FromDWithDef->getInit());
3777
3778 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3779 ToTU, varDecl(hasName("a"))); // Decl with init
3780 ASSERT_TRUE(ToD->getInit());
3781 ASSERT_FALSE(ToD->getDefinition());
3782
3783 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3784 EXPECT_TRUE(ImportedD->getAnyInitializer());
3785 EXPECT_TRUE(ImportedD->getDefinition());
3786}
3787
3788TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3789 auto StructA =
3790 R"(
3791 struct A {
3792 static const int a;
3793 };
3794 )";
3795 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3796 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3797 Lang_CXX, "input1.cc");
3798
3799 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3800 FromTU, varDecl(hasName("a")));
3801 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3802 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3803 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3804 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3805 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3806 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3807 ASSERT_TRUE(FromDWithDef->getInit());
3808
3809 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3810 ToTU, varDecl(hasName("a")));
3811 ASSERT_FALSE(ToD->getInit());
3812 ASSERT_FALSE(ToD->getDefinition());
3813
3814 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3815 EXPECT_TRUE(ImportedD->getAnyInitializer());
3816 EXPECT_TRUE(ImportedD->getDefinition());
3817}
3818
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003819struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003820
Gabor Marton54058b52018-12-17 13:53:12 +00003821TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3822 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3823 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3824 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3825 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3826 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3827
3828 Decl *ImportedDef = Import(FromDef, Lang_C);
3829
3830 EXPECT_NE(ImportedDef, ToProto);
3831 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3832 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3833 EXPECT_TRUE(ImportedDef == ToDef);
3834 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3835 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3836 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3837}
3838
3839TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3840 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3841 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3842 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3843 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3844 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3845
3846 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3847
3848 EXPECT_NE(ImportedDef, ToProto);
3849 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3850 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3851 EXPECT_TRUE(ImportedDef == ToDef);
3852 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3853 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3854 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3855}
3856
3857TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3858 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3859 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3860 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3861 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3862 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3863
3864 Decl *ImportedProto = Import(FromProto, Lang_C);
3865 Decl *ImportedDef = Import(FromDef, Lang_C);
3866 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3867
3868 EXPECT_NE(ImportedDef, ImportedProto);
3869 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3870 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3871 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3872 EXPECT_TRUE(ImportedDef == ToDef);
3873 EXPECT_TRUE(ImportedProto == ToProto);
3874 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3875 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3876 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3877}
3878
Gabor Martonfc03fc62019-02-18 11:09:56 +00003879// FIXME put these structs and the tests rely on them into their own separate
3880// test file!
3881struct Function {
3882 using DeclTy = FunctionDecl;
3883 static constexpr auto *Prototype = "void X();";
3884 static constexpr auto *Definition = "void X() {}";
3885 BindableMatcher<Decl> getPattern() {
3886 return functionDecl(hasName("X"), unless(isImplicit()));
3887 }
3888};
Gabor Marton7df342a2018-12-17 12:42:12 +00003889
Gabor Martonfc03fc62019-02-18 11:09:56 +00003890struct Class {
3891 using DeclTy = CXXRecordDecl;
3892 static constexpr auto *Prototype = "class X;";
3893 static constexpr auto *Definition = "class X {};";
3894 BindableMatcher<Decl> getPattern() {
3895 return cxxRecordDecl(hasName("X"), unless(isImplicit()));
3896 }
3897};
Gabor Marton7df342a2018-12-17 12:42:12 +00003898
Gabor Martonfc03fc62019-02-18 11:09:56 +00003899struct Variable {
3900 using DeclTy = VarDecl;
3901 static constexpr auto *Prototype = "extern int X;";
3902 static constexpr auto *Definition = "int X;";
3903 BindableMatcher<Decl> getPattern() {
3904 return varDecl(hasName("X"));
3905 }
3906};
Gabor Marton7df342a2018-12-17 12:42:12 +00003907
Gabor Martonfc03fc62019-02-18 11:09:56 +00003908struct FunctionTemplate {
3909 using DeclTy = FunctionTemplateDecl;
3910 static constexpr auto *Prototype = "template <class T> void X();";
3911 static constexpr auto *Definition =
3912 R"(
3913 template <class T> void X() {};
3914 // Explicit instantiation is a must because of -fdelayed-template-parsing:
3915 template void X<int>();
3916 )";
3917 BindableMatcher<Decl> getPattern() {
3918 return functionTemplateDecl(hasName("X"), unless(isImplicit()));
3919 }
3920};
Gabor Marton7df342a2018-12-17 12:42:12 +00003921
Gabor Martonfc03fc62019-02-18 11:09:56 +00003922struct ClassTemplate {
3923 using DeclTy = ClassTemplateDecl;
3924 static constexpr auto *Prototype = "template <class T> class X;";
3925 static constexpr auto *Definition = "template <class T> class X {};";
3926 BindableMatcher<Decl> getPattern() {
3927 return classTemplateDecl(hasName("X"), unless(isImplicit()));
3928 }
3929};
Gabor Marton7df342a2018-12-17 12:42:12 +00003930
Gabor Martonfc03fc62019-02-18 11:09:56 +00003931struct FunctionTemplateSpec {
3932 using DeclTy = FunctionDecl;
3933 static constexpr auto *Prototype =
3934 R"(
3935 // Proto of the primary template.
3936 template <class T>
3937 void X();
3938 // Proto of the specialization.
3939 template <>
3940 void X<int>();
3941 )";
3942 static constexpr auto *Definition =
3943 R"(
3944 // Proto of the primary template.
3945 template <class T>
3946 void X();
3947 // Specialization and definition.
3948 template <>
3949 void X<int>() {}
3950 )";
3951 BindableMatcher<Decl> getPattern() {
3952 return functionDecl(hasName("X"), isExplicitTemplateSpecialization());
3953 }
3954};
Gabor Marton7df342a2018-12-17 12:42:12 +00003955
Gabor Marton7f8c4002019-03-19 13:34:10 +00003956struct ClassTemplateSpec {
3957 using DeclTy = ClassTemplateSpecializationDecl;
3958 static constexpr auto *Prototype =
3959 R"(
3960 template <class T> class X;
3961 template <> class X<int>;
3962 )";
3963 static constexpr auto *Definition =
3964 R"(
3965 template <class T> class X;
3966 template <> class X<int> {};
3967 )";
3968 BindableMatcher<Decl> getPattern() {
3969 return classTemplateSpecializationDecl(hasName("X"), unless(isImplicit()));
3970 }
3971};
3972
Gabor Martonfc03fc62019-02-18 11:09:56 +00003973template <typename TypeParam>
3974struct RedeclChain : ASTImporterOptionSpecificTestBase {
Gabor Marton7df342a2018-12-17 12:42:12 +00003975
Gabor Martonfc03fc62019-02-18 11:09:56 +00003976 using DeclTy = typename TypeParam::DeclTy;
3977 std::string getPrototype() { return TypeParam::Prototype; }
3978 std::string getDefinition() { return TypeParam::Definition; }
3979 BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); }
Gabor Marton7df342a2018-12-17 12:42:12 +00003980
Gabor Martondd59d272019-03-19 14:04:50 +00003981 void CheckPreviousDecl(Decl *Prev, Decl *Current) {
3982 ASSERT_NE(Prev, Current);
3983 ASSERT_EQ(&Prev->getASTContext(), &Current->getASTContext());
3984 EXPECT_EQ(Prev->getCanonicalDecl(), Current->getCanonicalDecl());
3985
3986 // Templates.
3987 if (auto *PrevT = dyn_cast<TemplateDecl>(Prev)) {
3988 EXPECT_EQ(Current->getPreviousDecl(), Prev);
3989 auto *CurrentT = cast<TemplateDecl>(Current);
3990 ASSERT_TRUE(PrevT->getTemplatedDecl());
3991 ASSERT_TRUE(CurrentT->getTemplatedDecl());
3992 EXPECT_EQ(CurrentT->getTemplatedDecl()->getPreviousDecl(),
3993 PrevT->getTemplatedDecl());
3994 return;
3995 }
3996
3997 // Specializations.
3998 if (auto *PrevF = dyn_cast<FunctionDecl>(Prev)) {
3999 if (PrevF->getTemplatedKind() ==
4000 FunctionDecl::TK_FunctionTemplateSpecialization) {
4001 // There may be a hidden fwd spec decl before a spec decl.
4002 // In that case the previous visible decl can be reached through that
4003 // invisible one.
4004 EXPECT_THAT(Prev, testing::AnyOf(
4005 Current->getPreviousDecl(),
4006 Current->getPreviousDecl()->getPreviousDecl()));
4007 auto *ToTU = Prev->getTranslationUnitDecl();
4008 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4009 ToTU, functionTemplateDecl());
4010 auto *FirstSpecD = *(TemplateD->spec_begin());
4011 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), PrevF->getCanonicalDecl());
4012 return;
4013 }
4014 }
4015
4016 // The rest: Classes, Functions, etc.
4017 EXPECT_EQ(Current->getPreviousDecl(), Prev);
4018 }
4019
Gabor Martonfc03fc62019-02-18 11:09:56 +00004020 void
4021 TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() {
4022 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX);
4023 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4024 ASSERT_FALSE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004025
Gabor Martonfc03fc62019-02-18 11:09:56 +00004026 Decl *ImportedD = Import(FromD, Lang_CXX);
4027 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004028
Gabor Martonfc03fc62019-02-18 11:09:56 +00004029 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4030 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4031 EXPECT_TRUE(ImportedD == ToD);
4032 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
4033 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
4034 EXPECT_TRUE(ToT->getTemplatedDecl());
4035 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004036
Gabor Martonfc03fc62019-02-18 11:09:56 +00004037 void TypedTest_DefinitionShouldBeImportedAsADefinition() {
4038 Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
4039 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4040 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004041
Gabor Martonfc03fc62019-02-18 11:09:56 +00004042 Decl *ImportedD = Import(FromD, Lang_CXX);
4043 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004044
Gabor Martonfc03fc62019-02-18 11:09:56 +00004045 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4046 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4047 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
4048 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
4049 EXPECT_TRUE(ToT->getTemplatedDecl());
4050 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004051
Gabor Martonfc03fc62019-02-18 11:09:56 +00004052 void TypedTest_ImportPrototypeAfterImportedPrototype() {
4053 Decl *FromTU = getTuDecl(
4054 getPrototype() + getPrototype(), Lang_CXX);
4055 auto *From0 =
4056 FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4057 auto *From1 = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4058 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4059 ASSERT_FALSE(From1->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004060
Gabor Martonfc03fc62019-02-18 11:09:56 +00004061 Decl *Imported0 = Import(From0, Lang_CXX);
4062 Decl *Imported1 = Import(From1, Lang_CXX);
4063 Decl *ToTU = Imported0->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004064
Gabor Martonfc03fc62019-02-18 11:09:56 +00004065 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4066 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4067 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4068 EXPECT_TRUE(Imported0 == To0);
4069 EXPECT_TRUE(Imported1 == To1);
4070 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4071 EXPECT_FALSE(To1->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004072
4073 CheckPreviousDecl(To0, To1);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004074 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004075
Gabor Martonfc03fc62019-02-18 11:09:56 +00004076 void TypedTest_ImportDefinitionAfterImportedPrototype() {
4077 Decl *FromTU = getTuDecl(
4078 getPrototype() + getDefinition(), Lang_CXX);
4079 auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4080 auto *FromDef = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4081 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4082 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004083
Gabor Martonfc03fc62019-02-18 11:09:56 +00004084 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4085 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4086 Decl *ToTU = ImportedProto->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004087
Gabor Martonfc03fc62019-02-18 11:09:56 +00004088 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4089 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4090 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4091 EXPECT_TRUE(ImportedProto == ToProto);
4092 EXPECT_TRUE(ImportedDef == ToDef);
4093 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4094 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004095
4096 CheckPreviousDecl(ToProto, ToDef);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004097 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004098
Gabor Martonfc03fc62019-02-18 11:09:56 +00004099 void TypedTest_ImportPrototypeAfterImportedDefinition() {
4100 Decl *FromTU = getTuDecl(
4101 getDefinition() + getPrototype(), Lang_CXX);
4102 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4103 auto *FromProto = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4104 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4105 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004106
Gabor Martonfc03fc62019-02-18 11:09:56 +00004107 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4108 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4109 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4110
4111 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4112 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4113 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4114 EXPECT_TRUE(ImportedDef == ToDef);
4115 EXPECT_TRUE(ImportedProto == ToProto);
4116 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4117 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004118
4119 CheckPreviousDecl(ToDef, ToProto);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004120 }
4121
4122 void TypedTest_ImportPrototypes() {
4123 Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4124 Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4125 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4126 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4127 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4128 ASSERT_FALSE(From1->isThisDeclarationADefinition());
4129
4130 Decl *Imported0 = Import(From0, Lang_CXX);
4131 Decl *Imported1 = Import(From1, Lang_CXX);
4132 Decl *ToTU = Imported0->getTranslationUnitDecl();
4133
4134 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4135 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4136 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4137 EXPECT_TRUE(Imported0 == To0);
4138 EXPECT_TRUE(Imported1 == To1);
4139 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4140 EXPECT_FALSE(To1->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004141
4142 CheckPreviousDecl(To0, To1);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004143 }
4144
4145 void TypedTest_ImportDefinitions() {
4146 Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4147 Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4148 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4149 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4150 ASSERT_TRUE(From0->isThisDeclarationADefinition());
4151 ASSERT_TRUE(From1->isThisDeclarationADefinition());
4152
4153 Decl *Imported0 = Import(From0, Lang_CXX);
4154 Decl *Imported1 = Import(From1, Lang_CXX);
4155 Decl *ToTU = Imported0->getTranslationUnitDecl();
4156
4157 EXPECT_EQ(Imported0, Imported1);
4158 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4159 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4160 EXPECT_TRUE(Imported0 == To0);
4161 EXPECT_TRUE(To0->isThisDeclarationADefinition());
4162 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0))
4163 EXPECT_TRUE(ToT0->getTemplatedDecl());
4164 }
4165
4166 void TypedTest_ImportDefinitionThenPrototype() {
4167 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4168 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4169 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4170 auto *FromProto =
4171 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4172 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4173 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4174
4175 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4176 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4177 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4178
4179 EXPECT_NE(ImportedDef, ImportedProto);
4180 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4181 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4182 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4183 EXPECT_TRUE(ImportedDef == ToDef);
4184 EXPECT_TRUE(ImportedProto == ToProto);
4185 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4186 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004187
4188 CheckPreviousDecl(ToDef, ToProto);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004189 }
4190
4191 void TypedTest_ImportPrototypeThenDefinition() {
4192 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4193 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4194 auto *FromProto =
4195 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4196 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4197 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4198 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4199
4200 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4201 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4202 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4203
4204 EXPECT_NE(ImportedDef, ImportedProto);
4205 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4206 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4207 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4208 EXPECT_TRUE(ImportedDef == ToDef);
4209 EXPECT_TRUE(ImportedProto == ToProto);
4210 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4211 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004212
4213 CheckPreviousDecl(ToProto, ToDef);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004214 }
4215
4216 void TypedTest_WholeRedeclChainIsImportedAtOnce() {
4217 Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
4218 auto *FromD = // Definition
4219 LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4220 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
4221
4222 Decl *ImportedD = Import(FromD, Lang_CXX);
4223 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4224
4225 // The whole redecl chain is imported at once.
4226 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4227 EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition());
4228 }
4229
4230 void TypedTest_ImportPrototypeThenProtoAndDefinition() {
4231 {
4232 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4233 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4234 Import(FromD, Lang_CXX);
4235 }
4236 {
4237 Decl *FromTU =
4238 getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc");
4239 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4240 Import(FromD, Lang_CXX);
4241 }
4242
4243 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4244
4245 ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u);
4246 DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4247 EXPECT_FALSE(ProtoD->isThisDeclarationADefinition());
4248
4249 DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4250 EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition());
4251
4252 EXPECT_TRUE(DefinitionD->getPreviousDecl());
4253 EXPECT_FALSE(
4254 DefinitionD->getPreviousDecl()->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004255
4256 CheckPreviousDecl(ProtoD, DefinitionD->getPreviousDecl());
Gabor Martonfc03fc62019-02-18 11:09:56 +00004257 }
4258};
4259
4260#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \
4261 NamePrefix, TestCase) \
4262 using BaseTemplate##TypeParam = BaseTemplate<TypeParam>; \
4263 TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \
4264 TypedTest_##TestCase(); \
4265 }
4266
4267ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4268 RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004269 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004270ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4271 RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004272 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004273ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4274 RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004275 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004276ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004277 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004278 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004279ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4280 RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004281 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004282ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4283 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004284 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004285ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4286 RedeclChain, ClassTemplateSpec, ,
4287 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004288
4289ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004290 RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004291ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004292 RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004293ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004294 RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004295ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004296 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004297 DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004298ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004299 RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004300ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4301 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004302 DefinitionShouldBeImportedAsADefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004303ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4304 RedeclChain, ClassTemplateSpec, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004305
4306ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004307 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004308ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004309 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004310ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004311 ImportPrototypeAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004312ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004313 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004314ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004315 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004316ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004317 ImportPrototypeAfterImportedPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004318ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4319 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004320
4321ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004322 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004323ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004324 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004325ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004326 ImportDefinitionAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004327ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004328 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004329ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004330 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004331ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004332 ImportDefinitionAfterImportedPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004333ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4334 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004335
4336ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004337 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004338ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004339 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004340ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004341 ImportPrototypeAfterImportedDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004342ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004343 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004344ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004345 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004346ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004347 ImportPrototypeAfterImportedDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004348ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4349 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004350
4351ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004352 ImportPrototypes)
Gabor Marton038100a2019-02-20 16:57:41 +00004353ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004354ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004355 ImportPrototypes)
Gabor Marton16d98c22019-03-07 13:01:51 +00004356ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4357 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004358ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004359 ImportPrototypes)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004360ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4361 ImportPrototypes)
Gabor Martondd59d272019-03-19 14:04:50 +00004362ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4363 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004364
4365ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004366 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004367ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004368 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004369ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004370 ImportDefinitions)
Gabor Marton16d98c22019-03-07 13:01:51 +00004371ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4372 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004373ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004374 ImportDefinitions)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004375ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4376 ImportDefinitions)
Gabor Martondd59d272019-03-19 14:04:50 +00004377ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4378 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004379
4380ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004381 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004382ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004383 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004384ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004385 ImportDefinitionThenPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004386ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004387 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004388ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004389 ImportDefinitionThenPrototype)
Gabor Martondd59d272019-03-19 14:04:50 +00004390ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004391 ImportDefinitionThenPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004392ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4393 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004394
4395ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004396 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004397ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004398 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004399ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004400 ImportPrototypeThenDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004401ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004402 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004403ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004404 ImportPrototypeThenDefinition)
Gabor Martondd59d272019-03-19 14:04:50 +00004405ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004406 ImportPrototypeThenDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004407ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4408 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004409
4410ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004411 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004412ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004413 WholeRedeclChainIsImportedAtOnce)
Gabor Marton16d98c22019-03-07 13:01:51 +00004414ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004415 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004416ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004417 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004418
4419ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004420 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004421ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004422 ImportPrototypeThenProtoAndDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004423ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004424 ImportPrototypeThenProtoAndDefinition)
Gabor Martondd59d272019-03-19 14:04:50 +00004425ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004426 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004427
4428INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction,
4429 DefaultTestValuesForRunOptions, );
4430INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass,
4431 DefaultTestValuesForRunOptions, );
4432INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable,
4433 DefaultTestValuesForRunOptions, );
4434INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
4435 DefaultTestValuesForRunOptions, );
4436INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
4437 DefaultTestValuesForRunOptions, );
4438INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
4439 DefaultTestValuesForRunOptions, );
Gabor Marton7f8c4002019-03-19 13:34:10 +00004440INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplateSpec,
4441 DefaultTestValuesForRunOptions, );
Gabor Martonfc03fc62019-02-18 11:09:56 +00004442
4443
Gabor Marton7df342a2018-12-17 12:42:12 +00004444
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004445struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00004446
4447TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4448 Decl *FromTU = getTuDecl(
4449 R"(
4450 class A {
4451 template <int I> class F {};
4452 class X {
4453 template <int I> friend class F;
4454 };
4455 };
4456 )",
4457 Lang_CXX, "input0.cc");
4458
4459 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4460 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4461 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4462 FromTU, cxxRecordDecl(hasName("F")));
4463
4464 ASSERT_TRUE(FromClass);
4465 ASSERT_TRUE(FromFriendClass);
4466 ASSERT_NE(FromClass, FromFriendClass);
4467 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4468 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4469 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4470 FromClass->getDescribedClassTemplate());
4471
4472 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
4473 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
4474
4475 EXPECT_TRUE(ToClass);
4476 EXPECT_TRUE(ToFriendClass);
4477 EXPECT_NE(ToClass, ToFriendClass);
4478 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4479 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4480 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4481 ToClass->getDescribedClassTemplate());
4482}
4483
4484TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4485 Decl *FromTu = getTuDecl(
4486 R"(
4487 class declToImport {
4488 friend class declToImport;
4489 };
4490 )",
4491 Lang_CXX, "input.cc");
4492
4493 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4494 FromTu, cxxRecordDecl(hasName("declToImport")));
4495 auto *ToD = Import(FromD, Lang_CXX);
4496 auto Pattern = cxxRecordDecl(has(friendDecl()));
4497 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4498 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4499}
4500
4501TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4502 Decl *FromTu = getTuDecl(
4503 R"(
4504 template<class A> class declToImport {
4505 template<class A1> friend class declToImport;
4506 };
4507 )",
4508 Lang_CXX, "input.cc");
4509
4510 auto *FromD =
4511 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
4512 auto *ToD = Import(FromD, Lang_CXX);
4513
4514 auto Pattern = classTemplateDecl(
4515 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4516 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4517 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4518
4519 auto *Class =
4520 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
4521 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4522 EXPECT_NE(Friend->getFriendDecl(), Class);
4523 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
4524}
4525
4526TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4527 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
4528
4529 ClassTemplateSpecializationDecl *Imported1;
4530 {
4531 Decl *FromTU = getTuDecl("template<class T> class X;"
4532 "struct Y { friend class X<int>; };",
4533 Lang_CXX, "input0.cc");
4534 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4535 FromTU, Pattern);
4536
4537 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4538 }
4539 ClassTemplateSpecializationDecl *Imported2;
4540 {
4541 Decl *FromTU = getTuDecl("template<class T> class X;"
4542 "template<> class X<int>{};"
4543 "struct Z { friend class X<int>; };",
4544 Lang_CXX, "input1.cc");
4545 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4546 FromTU, Pattern);
4547
4548 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4549 }
4550
4551 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4552 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4553 2u);
4554 ASSERT_TRUE(Imported2->getPreviousDecl());
4555 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4556}
4557
4558TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4559 Decl *FromTU0 = getTuDecl(
4560 R"(
4561 class X {
4562 class Y;
4563 };
4564 class X::Y {
4565 template <typename T>
4566 friend class F; // The decl context of F is the global namespace.
4567 };
4568 )",
4569 Lang_CXX, "input0.cc");
4570 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4571 FromTU0, classTemplateDecl(hasName("F")));
4572 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4573 Decl *FromTU1 = getTuDecl(
4574 R"(
4575 template <typename T>
4576 class F {};
4577 )",
4578 Lang_CXX, "input1.cc");
4579 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4580 FromTU1, classTemplateDecl(hasName("F")));
4581 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4582 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4583 Imported1->getTemplatedDecl()->getTypeForDecl());
4584}
4585
4586TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4587 Decl *From, *To;
4588 std::tie(From, To) =
4589 getImportedDecl("class declToImport {};", Lang_CXX,
4590 "class Y { friend class declToImport; };", Lang_CXX);
4591 auto *Imported = cast<CXXRecordDecl>(To);
4592
4593 EXPECT_TRUE(Imported->getPreviousDecl());
4594}
4595
4596TEST_P(ImportFriendClasses,
4597 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4598 Decl *ToTU = getToTuDecl(
4599 R"(
4600 class X {
4601 class Y;
4602 };
4603 class X::Y {
4604 template <typename T>
4605 friend class F; // The decl context of F is the global namespace.
4606 };
4607 )",
4608 Lang_CXX);
4609 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4610 ToTU, classTemplateDecl(hasName("F")));
4611 Decl *FromTU = getTuDecl(
4612 R"(
4613 template <typename T>
4614 class F {};
4615 )",
4616 Lang_CXX, "input0.cc");
4617 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4618 FromTU, classTemplateDecl(hasName("F")));
4619 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4620 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4621 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4622 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4623 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4624}
4625
4626TEST_P(ImportFriendClasses,
4627 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4628 Decl *FromTU0 = getTuDecl(
4629 R"(
4630 class X {
4631 class Y;
4632 };
4633 class X::Y {
4634 template <typename T>
4635 friend class F; // The decl context of F is the global namespace.
4636 };
4637 )",
4638 Lang_CXX, "input0.cc");
4639 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4640 FromTU0, classTemplateDecl(hasName("F")));
4641 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4642 Decl *FromTU1 = getTuDecl(
4643 R"(
4644 template <typename T>
4645 class F {};
4646 )",
4647 Lang_CXX, "input1.cc");
4648 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4649 FromTU1, classTemplateDecl(hasName("F")));
4650 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4651 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4652 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4653 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4654 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4655}
4656
4657TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4658 Decl *FromTU0 = getTuDecl(
4659 R"(
4660 class X {
4661 class Y;
4662 };
4663 class X::Y {
4664 friend class F; // The decl context of F is the global namespace.
4665 };
4666 )",
4667 Lang_CXX, "input0.cc");
4668 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4669 QualType FT = Friend->getFriendType()->getType();
4670 FT = FromTU0->getASTContext().getCanonicalType(FT);
4671 auto *Fwd = cast<TagType>(FT)->getDecl();
4672 auto *ImportedFwd = Import(Fwd, Lang_CXX);
4673 Decl *FromTU1 = getTuDecl(
4674 R"(
4675 class F {};
4676 )",
4677 Lang_CXX, "input1.cc");
4678 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4679 FromTU1, cxxRecordDecl(hasName("F")));
4680 auto *ImportedDef = Import(Definition, Lang_CXX);
4681 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4682 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4683}
4684
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004685TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00004686 auto *Code = R"(
4687 template <class T>
4688 struct X {
4689 friend void foo(){}
4690 };
4691 )";
4692 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4693 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4694 ToTU, functionDecl(hasName("foo")));
4695
4696 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4697 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4698 FromTU, functionDecl(hasName("foo")));
4699 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4700 EXPECT_EQ(ImportedFoo, ToFoo);
4701}
4702
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004703struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00004704
4705TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4706 Decl *TU = getTuDecl(
4707 R"(
4708 namespace NS {
4709
4710 template <typename T>
4711 struct S {};
4712 template struct S<int>;
4713
4714 inline namespace INS {
4715 template <typename T>
4716 struct S {};
4717 template struct S<int>;
4718 }
4719
4720 }
4721 )", Lang_CXX11, "input0.cc");
4722 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4723 TU, namespaceDecl());
4724 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4725 TU, classTemplateSpecializationDecl());
4726 ASSERT_TRUE(NS->containsDecl(Spec));
4727
4728 NS->removeDecl(Spec);
4729 EXPECT_FALSE(NS->containsDecl(Spec));
4730}
4731
Gabor Marton7df342a2018-12-17 12:42:12 +00004732TEST_P(DeclContextTest,
4733 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4734 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4735 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4736 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4737
4738 // Investigate the list.
4739 auto *DC = A0->getDeclContext();
4740 ASSERT_TRUE(DC->containsDecl(A0));
4741 ASSERT_TRUE(DC->containsDecl(A1));
4742
4743 // Investigate the lookup table.
4744 auto *Map = DC->getLookupPtr();
4745 ASSERT_TRUE(Map);
4746 auto I = Map->find(A0->getDeclName());
4747 ASSERT_NE(I, Map->end());
4748 StoredDeclsList &L = I->second;
4749 // The lookup table contains the most recent decl of A.
4750 ASSERT_NE(L.getAsDecl(), A0);
4751 ASSERT_EQ(L.getAsDecl(), A1);
4752
4753 ASSERT_TRUE(L.getAsDecl());
4754 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4755 // The point here is to have a Vec with only one element, which is not the
4756 // one we are going to delete from the DC later.
4757 L.setHasExternalDecls();
4758 ASSERT_TRUE(L.getAsVector());
4759 ASSERT_EQ(1u, L.getAsVector()->size());
4760
4761 // This asserts in the old implementation.
4762 DC->removeDecl(A0);
4763 EXPECT_FALSE(DC->containsDecl(A0));
4764}
4765
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004766struct ImportFunctionTemplateSpecializations
4767 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004768
4769TEST_P(ImportFunctionTemplateSpecializations,
4770 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4771
4772 Decl *FromTU = getTuDecl(
4773 R"(
4774 template<class T>
4775 int f() { return 0; }
4776 void foo() { f<int>(); }
4777 )",
4778 Lang_CXX, "input0.cc");
4779
4780 // Check that the function template instantiation is NOT the child of the TU.
4781 auto Pattern = translationUnitDecl(
4782 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4783 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4784
4785 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4786 FromTU, functionDecl(hasName("foo")));
4787 ASSERT_TRUE(Import(Foo, Lang_CXX));
4788
4789 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4790 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4791}
4792
4793TEST_P(ImportFunctionTemplateSpecializations,
4794 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4795
4796 Decl *FromTU = getTuDecl(
4797 R"(
4798 template<class T>
4799 int f() { return 0; }
4800 template int f<int>();
4801 )",
4802 Lang_CXX, "input0.cc");
4803
4804 // Check that the function template instantiation is NOT the child of the TU.
4805 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4806 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4807 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4808
4809 ASSERT_TRUE(
4810 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4811
4812 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4813 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4814}
4815
4816TEST_P(ImportFunctionTemplateSpecializations,
4817 TUshouldContainFunctionTemplateSpecialization) {
4818
4819 Decl *FromTU = getTuDecl(
4820 R"(
4821 template<class T>
4822 int f() { return 0; }
4823 template <> int f<int>() { return 4; }
4824 )",
4825 Lang_CXX, "input0.cc");
4826
4827 // Check that the function template specialization is the child of the TU.
4828 auto Specialization =
4829 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4830 auto Pattern = translationUnitDecl(has(Specialization));
4831 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4832
4833 ASSERT_TRUE(
4834 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4835
4836 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4837 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4838}
4839
4840TEST_P(ImportFunctionTemplateSpecializations,
4841 FunctionTemplateSpecializationRedeclChain) {
4842
4843 Decl *FromTU = getTuDecl(
4844 R"(
4845 template<class T>
4846 int f() { return 0; }
4847 template <> int f<int>() { return 4; }
4848 )",
4849 Lang_CXX, "input0.cc");
4850
4851 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4852 hasParent(translationUnitDecl()));
4853 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4854 {
4855 auto *TU = FromTU;
4856 auto *SpecD = FromSpecD;
4857 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4858 TU, functionTemplateDecl());
4859 auto *FirstSpecD = *(TemplateD->spec_begin());
4860 ASSERT_EQ(SpecD, FirstSpecD);
4861 ASSERT_TRUE(SpecD->getPreviousDecl());
4862 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4863 ->doesThisDeclarationHaveABody());
4864 }
4865
4866 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4867
4868 {
4869 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4870 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4871 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4872 TU, functionTemplateDecl());
4873 auto *FirstSpecD = *(TemplateD->spec_begin());
4874 EXPECT_EQ(SpecD, FirstSpecD);
4875 ASSERT_TRUE(SpecD->getPreviousDecl());
4876 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4877 ->doesThisDeclarationHaveABody());
4878 }
4879}
4880
4881TEST_P(ImportFunctionTemplateSpecializations,
4882 MatchNumberOfFunctionTemplateSpecializations) {
4883
4884 Decl *FromTU = getTuDecl(
4885 R"(
4886 template <typename T> constexpr int f() { return 0; }
4887 template <> constexpr int f<int>() { return 4; }
4888 void foo() {
4889 static_assert(f<char>() == 0, "");
4890 static_assert(f<int>() == 4, "");
4891 }
4892 )",
4893 Lang_CXX11, "input0.cc");
4894 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4895 FromTU, functionDecl(hasName("foo")));
4896
4897 Import(FromD, Lang_CXX11);
4898 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4899 EXPECT_EQ(
4900 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4901 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4902}
4903
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004904TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004905 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4906 {
4907 Decl *FromTU = getTuDecl(
4908 R"(
4909 template <typename T>
4910 struct B;
4911 )",
4912 Lang_CXX, "input0.cc");
4913 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4914 FromTU, classTemplateDecl(hasName("B")));
4915
4916 Import(FromD, Lang_CXX);
4917 }
4918
4919 {
4920 Decl *FromTU = getTuDecl(
4921 R"(
4922 template <typename T>
4923 struct B {
4924 void f();
4925 B* b;
4926 };
4927 )",
4928 Lang_CXX, "input1.cc");
4929 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4930 FromTU, functionDecl(hasName("f")));
4931 Import(FromD, Lang_CXX);
4932 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4933 FromTU, classTemplateDecl(hasName("B")));
4934 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4935 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4936
4937 // We expect no (ODR) warning during the import.
4938 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4939 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4940 }
4941}
4942
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004943TEST_P(ASTImporterOptionSpecificTestBase,
4944 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004945 // We already have an incomplete underlying type in the "To" context.
4946 auto Code =
4947 R"(
4948 template <typename T>
4949 struct S {
4950 void foo();
4951 };
4952 using U = S<int>;
4953 )";
4954 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4955 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4956 typedefNameDecl(hasName("U")));
4957 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4958
4959 // The "From" context has the same typedef, but the underlying type is
4960 // complete this time.
4961 Decl *FromTU = getTuDecl(std::string(Code) +
4962 R"(
4963 void foo(U* u) {
4964 u->foo();
4965 }
4966 )", Lang_CXX11);
4967 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4968 typedefNameDecl(hasName("U")));
4969 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4970
4971 // The imported type should be complete.
4972 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4973 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4974}
4975
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004976struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004977
4978TEST_P(ASTImporterLookupTableTest, OneDecl) {
4979 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4980 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4981 ASTImporterLookupTable LT(*ToTU);
4982 auto Res = LT.lookup(ToTU, D->getDeclName());
4983 ASSERT_EQ(Res.size(), 1u);
4984 EXPECT_EQ(*Res.begin(), D);
4985}
4986
4987static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4988 for (Decl *D : DC->decls()) {
4989 if (auto *ND = dyn_cast<NamedDecl>(D))
4990 if (ND->getDeclName() == Name)
4991 return ND;
4992 }
4993 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004994}
Gabor Marton54058b52018-12-17 13:53:12 +00004995
4996TEST_P(ASTImporterLookupTableTest,
4997 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4998 auto *Code = R"(
4999 template <class T>
5000 struct X {
5001 friend void foo(){}
5002 };
5003 )";
5004 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
5005 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
5006 ToTU, classTemplateDecl(hasName("X")));
5007 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
5008 ToTU, functionDecl(hasName("foo")));
5009 DeclContext *FooDC = Foo->getDeclContext();
5010 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5011 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
5012 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5013 DeclarationName FooName = Foo->getDeclName();
5014
5015 // Cannot find in the LookupTable of its DC (TUDecl)
5016 SmallVector<NamedDecl *, 2> FoundDecls;
5017 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5018 EXPECT_EQ(FoundDecls.size(), 0u);
5019
5020 // Cannot find in the LookupTable of its LexicalDC (X)
5021 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5022 EXPECT_EQ(FoundDecls.size(), 0u);
5023
5024 // Can't find in the list of Decls of the DC.
5025 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5026
5027 // Can't find in the list of Decls of the LexicalDC
5028 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
5029
5030 // ASTImporter specific lookup finds it.
5031 ASTImporterLookupTable LT(*ToTU);
5032 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5033 ASSERT_EQ(Res.size(), 1u);
5034 EXPECT_EQ(*Res.begin(), Foo);
5035}
5036
5037TEST_P(ASTImporterLookupTableTest,
5038 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
5039 TranslationUnitDecl *ToTU =
5040 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
5041 auto *Foo =
5042 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
5043 auto *A =
5044 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5045 DeclContext *FooDC = Foo->getDeclContext();
5046 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5047 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
5048 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5049 DeclarationName FooName = Foo->getDeclName();
5050
5051 // Cannot find in the LookupTable of its DC (TUDecl).
5052 SmallVector<NamedDecl *, 2> FoundDecls;
5053 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5054 EXPECT_EQ(FoundDecls.size(), 0u);
5055
5056 // Cannot find in the LookupTable of its LexicalDC (A).
5057 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5058 EXPECT_EQ(FoundDecls.size(), 0u);
5059
5060 // Can't find in the list of Decls of the DC.
5061 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5062
5063 // Can find in the list of Decls of the LexicalDC.
5064 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
5065
5066 // ASTImporter specific lookup finds it.
5067 ASTImporterLookupTable LT(*ToTU);
5068 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5069 ASSERT_EQ(Res.size(), 1u);
5070 EXPECT_EQ(*Res.begin(), Foo);
5071}
5072
5073TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
5074 TranslationUnitDecl *ToTU =
5075 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
5076 DeclarationName VName = FirstDeclMatcher<VarDecl>()
5077 .match(ToTU, varDecl(hasName("V")))
5078 ->getDeclName();
5079 auto *A =
5080 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5081 auto *B =
5082 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
5083
5084 ASTImporterLookupTable LT(*ToTU);
5085
5086 auto Res = LT.lookup(cast<DeclContext>(A), VName);
5087 ASSERT_EQ(Res.size(), 1u);
5088 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5089 ToTU, fieldDecl(hasName("V"),
5090 hasParent(recordDecl(hasName("A"))))));
5091 Res = LT.lookup(cast<DeclContext>(B), VName);
5092 ASSERT_EQ(Res.size(), 1u);
5093 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5094 ToTU, fieldDecl(hasName("V"),
5095 hasParent(recordDecl(hasName("B"))))));
5096 Res = LT.lookup(ToTU, VName);
5097 ASSERT_EQ(Res.size(), 1u);
5098 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
5099 ToTU, varDecl(hasName("V"),
5100 hasParent(translationUnitDecl()))));
5101}
5102
5103TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5104 TranslationUnitDecl *ToTU = getToTuDecl(
5105 R"(
5106 void foo();
5107 void foo(int);
5108 void foo(int, int);
5109 )",
5110 Lang_CXX);
5111
5112 ASTImporterLookupTable LT(*ToTU);
5113 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5114 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5115 DeclarationName Name = F0->getDeclName();
5116 auto Res = LT.lookup(ToTU, Name);
5117 EXPECT_EQ(Res.size(), 3u);
5118 EXPECT_EQ(Res.count(F0), 1u);
5119 EXPECT_EQ(Res.count(F2), 1u);
5120}
5121
Gabor Martona9cab312019-02-08 09:19:34 +00005122TEST_P(ASTImporterLookupTableTest,
5123 DifferentOperatorsShouldHaveDifferentResultSet) {
5124 TranslationUnitDecl *ToTU = getToTuDecl(
5125 R"(
5126 struct X{};
5127 void operator+(X, X);
5128 void operator-(X, X);
5129 )",
5130 Lang_CXX);
5131
5132 ASTImporterLookupTable LT(*ToTU);
5133 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5134 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5135 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5136 ToTU, functionDecl(hasOverloadedOperatorName("-")));
5137 DeclarationName NamePlus = FPlus->getDeclName();
5138 auto ResPlus = LT.lookup(ToTU, NamePlus);
5139 EXPECT_EQ(ResPlus.size(), 1u);
5140 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5141 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5142 DeclarationName NameMinus = FMinus->getDeclName();
5143 auto ResMinus = LT.lookup(ToTU, NameMinus);
5144 EXPECT_EQ(ResMinus.size(), 1u);
5145 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5146 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5147 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5148}
5149
5150TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5151 TranslationUnitDecl *ToTU = getToTuDecl(
5152 R"(
5153 struct X {};
5154 void operator+(X, X);
5155 )",
5156 Lang_CXX);
5157 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5158 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5159
5160 Decl *FromTU = getTuDecl(
5161 R"(
5162 struct X {};
5163 void operator+(X, X);
5164 )",
5165 Lang_CXX);
5166 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5167 FromTU, functionDecl(hasOverloadedOperatorName("+")));
5168
5169 // FromPlus have a different TU, thus its DeclarationName is different too.
5170 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5171
5172 ASTImporterLookupTable LT(*ToTU);
5173 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
5174 ASSERT_EQ(Res.size(), 1u);
5175 EXPECT_EQ(*Res.begin(), ToPlus);
5176
5177 // FromPlus have a different TU, thus its DeclarationName is different too.
5178 Res = LT.lookup(ToTU, FromPlus->getDeclName());
5179 ASSERT_EQ(Res.size(), 0u);
5180}
5181
Gabor Marton54058b52018-12-17 13:53:12 +00005182static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
5183 QualType Ty = FD->getFriendType()->getType();
5184 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
5185 return cast<RecordType>(NamedTy)->getDecl();
5186}
5187
5188TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
5189 TranslationUnitDecl *ToTU = getToTuDecl(
5190 R"(
5191 class Y { friend class F; };
5192 )",
5193 Lang_CXX);
5194
5195 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5196 // So we must dig up the underlying CXXRecordDecl.
5197 ASTImporterLookupTable LT(*ToTU);
5198 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5199 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5200 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5201 ToTU, cxxRecordDecl(hasName("Y")));
5202
5203 DeclarationName Name = RD->getDeclName();
5204 auto Res = LT.lookup(ToTU, Name);
5205 EXPECT_EQ(Res.size(), 1u);
5206 EXPECT_EQ(*Res.begin(), RD);
5207
5208 Res = LT.lookup(Y, Name);
5209 EXPECT_EQ(Res.size(), 0u);
5210}
5211
5212TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5213 TranslationUnitDecl *ToTU = getToTuDecl(
5214 R"(
5215 class Y { template <class T> friend class F; };
5216 )",
5217 Lang_CXX);
5218
5219 ASTImporterLookupTable LT(*ToTU);
5220 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5221 ToTU, classTemplateDecl(hasName("F")));
5222 DeclarationName Name = F->getDeclName();
5223 auto Res = LT.lookup(ToTU, Name);
5224 EXPECT_EQ(Res.size(), 2u);
5225 EXPECT_EQ(Res.count(F), 1u);
5226 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5227}
5228
5229TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5230 TranslationUnitDecl *ToTU = getToTuDecl(
5231 R"(
5232 template <typename T>
5233 class F;
5234
5235 template <typename T>
5236 class Y {
5237 friend class F<T>;
5238 };
5239 )",
5240 Lang_CXX);
5241
5242 ASTImporterLookupTable LT(*ToTU);
5243 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5244 ToTU, classTemplateDecl(hasName("F")));
5245 DeclarationName Name = F->getDeclName();
5246 auto Res = LT.lookup(ToTU, Name);
5247 EXPECT_EQ(Res.size(), 2u);
5248 EXPECT_EQ(Res.count(F), 1u);
5249 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5250}
5251
5252TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
5253 TranslationUnitDecl *ToTU = getToTuDecl(
5254 R"(
5255 template <typename T>
5256 class F;
5257
5258 class Y {
5259 friend class F<int>;
5260 };
5261 )",
5262 Lang_CXX);
5263
5264 ASTImporterLookupTable LT(*ToTU);
5265 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5266 ToTU, classTemplateDecl(hasName("F")));
5267 DeclarationName Name = F->getDeclName();
5268 auto Res = LT.lookup(ToTU, Name);
5269 ASSERT_EQ(Res.size(), 3u);
5270 EXPECT_EQ(Res.count(F), 1u);
5271 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5272 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
5273}
5274
5275TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
5276 TranslationUnitDecl *ToTU = getToTuDecl(
5277 R"(
5278 class Y { friend void F(); };
5279 )",
5280 Lang_CXX);
5281
5282 ASTImporterLookupTable LT(*ToTU);
5283 auto *F =
5284 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
5285 DeclarationName Name = F->getDeclName();
5286 auto Res = LT.lookup(ToTU, Name);
5287 EXPECT_EQ(Res.size(), 1u);
5288 EXPECT_EQ(*Res.begin(), F);
5289}
5290
5291TEST_P(ASTImporterLookupTableTest,
5292 LookupFindsDeclsInClassTemplateSpecialization) {
5293 TranslationUnitDecl *ToTU = getToTuDecl(
5294 R"(
5295 template <typename T>
5296 struct X {
5297 int F;
5298 };
5299 void foo() {
5300 X<char> xc;
5301 }
5302 )",
5303 Lang_CXX);
5304
5305 ASTImporterLookupTable LT(*ToTU);
5306
5307 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
5308 ToTU, classTemplateDecl(hasName("X")));
5309 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
5310 ToTU,
5311 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
5312
5313 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5314 ToTU, classTemplateSpecializationDecl(hasName("X")));
5315 FieldDecl *FieldInSpec = *Spec->field_begin();
5316 ASSERT_TRUE(FieldInSpec);
5317
5318 DeclarationName Name = FieldInSpec->getDeclName();
5319 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
5320
5321 SmallVector<NamedDecl *, 2> FoundDecls;
5322 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
5323 EXPECT_EQ(FoundDecls.size(), 1u);
5324 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
5325
5326 auto Res = LT.lookup(TemplateDC, Name);
5327 ASSERT_EQ(Res.size(), 1u);
5328 EXPECT_EQ(*Res.begin(), FieldInTemplate);
5329
5330 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
5331 FoundDecls);
5332 EXPECT_EQ(FoundDecls.size(), 1u);
5333 EXPECT_EQ(FoundDecls[0], FieldInSpec);
5334
5335 Res = LT.lookup(cast<DeclContext>(Spec), Name);
5336 ASSERT_EQ(Res.size(), 1u);
5337 EXPECT_EQ(*Res.begin(), FieldInSpec);
5338}
5339
5340TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
5341 TranslationUnitDecl *ToTU = getToTuDecl(
5342 R"(
5343 class Y { template <class T> friend void F(); };
5344 )",
5345 Lang_CXX);
5346
5347 ASTImporterLookupTable LT(*ToTU);
5348 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
5349 ToTU, functionTemplateDecl(hasName("F")));
5350 DeclarationName Name = F->getDeclName();
5351 auto Res = LT.lookup(ToTU, Name);
5352 EXPECT_EQ(Res.size(), 2u);
5353 EXPECT_EQ(Res.count(F), 1u);
5354 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5355}
5356
5357TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
5358 TranslationUnitDecl *ToTU = getToTuDecl(
5359 R"(
5360 struct X;
5361 struct A {
5362 friend struct X;
5363 };
5364 struct B {
5365 friend struct X;
5366 };
5367 )",
5368 Lang_CXX);
5369
5370 ASTImporterLookupTable LT(*ToTU);
5371 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
5372 ToTU, cxxRecordDecl(hasName("X")));
5373 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5374 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5375 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
5376 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
5377 ASSERT_EQ(RD0, RD1);
5378 ASSERT_EQ(RD1, X);
5379
5380 DeclarationName Name = X->getDeclName();
5381 auto Res = LT.lookup(ToTU, Name);
5382 EXPECT_EQ(Res.size(), 1u);
5383 EXPECT_EQ(*Res.begin(), X);
5384}
5385
5386TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
5387 TranslationUnitDecl *ToTU = getToTuDecl(
5388 R"(
5389 enum E {
5390 A,
5391 B
5392 };
5393 )",
5394 Lang_C);
5395
5396 ASTImporterLookupTable LT(*ToTU);
5397 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
5398 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
5399 ToTU, enumConstantDecl(hasName("A")));
5400
5401 DeclarationName Name = A->getDeclName();
5402 // Redecl context is the TU.
5403 ASSERT_EQ(E->getRedeclContext(), ToTU);
5404
5405 SmallVector<NamedDecl *, 2> FoundDecls;
5406 // Normal lookup finds in the DC.
5407 E->localUncachedLookup(Name, FoundDecls);
5408 EXPECT_EQ(FoundDecls.size(), 1u);
5409
5410 // Normal lookup finds in the Redecl context.
5411 ToTU->localUncachedLookup(Name, FoundDecls);
5412 EXPECT_EQ(FoundDecls.size(), 1u);
5413
5414 // Import specific lookup finds in the DC.
5415 auto Res = LT.lookup(E, Name);
5416 ASSERT_EQ(Res.size(), 1u);
5417 EXPECT_EQ(*Res.begin(), A);
5418
5419 // Import specific lookup finds in the Redecl context.
5420 Res = LT.lookup(ToTU, Name);
5421 ASSERT_EQ(Res.size(), 1u);
5422 EXPECT_EQ(*Res.begin(), A);
5423}
5424
5425TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
5426 TranslationUnitDecl *ToTU = getToTuDecl(
5427 R"(
5428 namespace N {
5429 int A;
5430 }
5431 namespace N {
5432 }
5433 )",
5434 Lang_CXX);
5435 auto *N1 =
5436 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
5437 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
5438 DeclarationName Name = A->getDeclName();
5439
5440 ASTImporterLookupTable LT(*ToTU);
5441 auto Res = LT.lookup(N1, Name);
5442 ASSERT_EQ(Res.size(), 1u);
5443 EXPECT_EQ(*Res.begin(), A);
5444}
5445
Gabor Marton19f4f392018-06-25 13:04:37 +00005446INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5447 ::testing::Values(ArgVector()), );
5448
Gabor Marton5254e642018-06-27 13:32:50 +00005449INSTANTIATE_TEST_CASE_P(
5450 ParameterizedTests, CanonicalRedeclChain,
5451 ::testing::Values(ArgVector()),);
5452
Gabor Marton0e04ebd2019-02-11 10:27:58 +00005453// FIXME This test is disabled currently, upcoming patches will make it
5454// possible to enable.
5455TEST_P(ASTImporterOptionSpecificTestBase,
5456 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
5457 Decl *FromTU = getTuDecl(
5458 R"(
5459 namespace NS {
5460 struct X;
5461 struct Y {
5462 static const int I = 3;
5463 };
5464 }
5465 namespace NS {
5466 struct X { // <--- To be imported
5467 void method(int i = Y::I) {}
5468 int f;
5469 };
5470 }
5471 )",
5472 Lang_CXX);
5473 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5474 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5475 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
5476 FromTU,
5477 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
5478 ASSERT_NE(FromFwd, FromDef);
5479 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
5480 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
5481 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
5482
5483 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
5484 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
5485 EXPECT_NE(ToFwd, ToDef);
5486 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
5487 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
5488 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
5489 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5490 // We expect no (ODR) warning during the import.
5491 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5492}
5493
Gabor Martone331e632019-02-18 13:09:27 +00005494struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
5495
5496TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
5497 Decl *ToTU = getToTuDecl(
5498 R"(
5499 class X {
5500 template <typename T> friend void foo();
5501 };
5502 )",
5503 Lang_CXX);
5504 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
5505 ToTU, functionTemplateDecl(hasName("foo")));
5506
5507 Decl *FromTU = getTuDecl(
5508 R"(
5509 template <typename T> void foo();
5510 )",
5511 Lang_CXX);
5512 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
5513 FromTU, functionTemplateDecl(hasName("foo")));
5514 auto *Imported = Import(FromFoo, Lang_CXX);
5515
Gabor Marton16d98c22019-03-07 13:01:51 +00005516 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00005517}
5518
Gabor Marton54058b52018-12-17 13:53:12 +00005519INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5520 DefaultTestValuesForRunOptions, );
5521
Gabor Marton19f4f392018-06-25 13:04:37 +00005522INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5523 DefaultTestValuesForRunOptions, );
5524
5525INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5526 DefaultTestValuesForRunOptions, );
5527
5528INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5529 DefaultTestValuesForRunOptions, );
5530
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005531INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005532 DefaultTestValuesForRunOptions, );
5533
5534INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5535 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005536
Gabor Martone331e632019-02-18 13:09:27 +00005537INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5538 DefaultTestValuesForRunOptions, );
5539
Gabor Marton54058b52018-12-17 13:53:12 +00005540INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005541 DefaultTestValuesForRunOptions, );
5542
Gabor Marton54058b52018-12-17 13:53:12 +00005543INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005544 DefaultTestValuesForRunOptions, );
5545
Gabor Marton7df342a2018-12-17 12:42:12 +00005546INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5547 DefaultTestValuesForRunOptions, );
5548
Gabor Marton5254e642018-06-27 13:32:50 +00005549INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5550 ImportFunctionTemplateSpecializations,
5551 DefaultTestValuesForRunOptions, );
5552
Gabor Martonac3a5d62018-09-17 12:04:52 +00005553INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5554 DefaultTestValuesForRunOptions, );
5555
5556INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5557 DefaultTestValuesForRunOptions, );
5558
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005559} // end namespace ast_matchers
5560} // end namespace clang