blob: 44f7a067d8ca00d7d14bfbc0404a7782cc142ed3 [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Tests for the correct import of AST nodes from one AST context to another.
10//
11//===----------------------------------------------------------------------===//
12
Gabor Marton458d1452019-02-14 13:07:03 +000013// Define this to have ::testing::Combine available.
14// FIXME: Better solution for this?
15#define GTEST_HAS_COMBINE 1
16
Gabor Marton7df342a2018-12-17 12:42:12 +000017#include "clang/AST/ASTImporter.h"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +000018#include "MatchVerifier.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000019#include "clang/AST/ASTContext.h"
Gabor Marton7df342a2018-12-17 12:42:12 +000020#include "clang/AST/DeclContextInternals.h"
Gabor Marton54058b52018-12-17 13:53:12 +000021#include "clang/AST/ASTImporter.h"
22#include "clang/AST/ASTImporterLookupTable.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000023#include "clang/ASTMatchers/ASTMatchFinder.h"
24#include "clang/ASTMatchers/ASTMatchers.h"
25#include "clang/Tooling/Tooling.h"
Peter Szecsidedda6f2018-03-30 22:03:29 +000026
27#include "DeclMatcher.h"
Gabor Marton1f667532018-05-24 08:41:07 +000028#include "Language.h"
Gabor Marton5254e642018-06-27 13:32:50 +000029#include "gmock/gmock.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000030#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000031
32namespace clang {
33namespace ast_matchers {
34
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000035using internal::Matcher;
36using internal::BindableMatcher;
37using llvm::StringMap;
38
Peter Szecsidedda6f2018-03-30 22:03:29 +000039// Creates a virtual file and assigns that to the context of given AST. If the
40// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000041static void
42createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
43 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000044 assert(ToAST);
45 ASTContext &ToCtx = ToAST->getASTContext();
Jonas Devliegherefc514902018-10-10 13:27:25 +000046 auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +000047 &ToCtx.getSourceManager().getFileManager().getVirtualFileSystem());
Jonas Devliegherefc514902018-10-10 13:27:25 +000048 auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
49 OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000050 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000051}
52
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000053static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
54 StringRef Code) {
55 return createVirtualFileIfNeeded(ToAST, FileName,
56 llvm::MemoryBuffer::getMemBuffer(Code));
57}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000058
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000059const StringRef DeclToImportID = "declToImport";
60const StringRef DeclToVerifyID = "declToVerify";
61
Gabor Marton19f4f392018-06-25 13:04:37 +000062// Common base for the different families of ASTImporter tests that are
63// parameterized on the compiler options which may result a different AST. E.g.
64// -fms-compatibility or -fdelayed-template-parsing.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000065class CompilerOptionSpecificTest : public ::testing::Test {
66protected:
67 // Return the extra arguments appended to runtime options at compilation.
68 virtual ArgVector getExtraArgs() const { return ArgVector(); }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000069
Gabor Marton19f4f392018-06-25 13:04:37 +000070 // Returns the argument vector used for a specific language option, this set
71 // can be tweaked by the test parameters.
72 ArgVector getArgVectorForLanguage(Language Lang) const {
73 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
Gabor Marton0b57ccb2019-02-07 16:52:48 +000074 ArgVector ExtraArgs = getExtraArgs();
Gabor Marton19f4f392018-06-25 13:04:37 +000075 for (const auto &Arg : ExtraArgs) {
76 Args.push_back(Arg);
77 }
78 return Args;
79 }
Gabor Marton19f4f392018-06-25 13:04:37 +000080};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000081
Gabor Marton0b57ccb2019-02-07 16:52:48 +000082auto DefaultTestValuesForRunOptions = ::testing::Values(
83 ArgVector(), ArgVector{"-fdelayed-template-parsing"},
84 ArgVector{"-fms-compatibility"},
85 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
86
Gabor Marton19f4f392018-06-25 13:04:37 +000087// Base class for those tests which use the family of `testImport` functions.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000088class TestImportBase : public CompilerOptionSpecificTest,
89 public ::testing::WithParamInterface<ArgVector> {
Adam Baloghe4192a82018-06-15 06:45:39 +000090
Gabor Marton19f4f392018-06-25 13:04:37 +000091 template <typename NodeType>
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.
Fangrui Song75e74e02019-03-31 08:48:19 +0000384 auto It = llvm::find_if(FromTUs, [From](const TU &E) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000385 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") {
Fangrui Song75e74e02019-03-31 08:48:19 +0000438 assert(llvm::find_if(FromTUs, [FileName](const TU &E) {
439 return E.FileName == FileName;
440 }) == FromTUs.end());
Peter Szecsidedda6f2018-03-30 22:03:29 +0000441
442 ArgVector Args = getArgVectorForLanguage(Lang);
443 FromTUs.emplace_back(SrcCode, FileName, Args);
444 TU &Tu = FromTUs.back();
445
446 return Tu.TUDecl;
447 }
448
Gabor Marton9581c332018-05-23 13:53:36 +0000449 // Creates the To context with the given source code and returns the TU decl.
450 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
451 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton9581c332018-05-23 13:53:36 +0000452 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000453 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Gabor Marton9581c332018-05-23 13:53:36 +0000454 return ToAST->getASTContext().getTranslationUnitDecl();
455 }
456
Peter Szecsidedda6f2018-03-30 22:03:29 +0000457 // Import the given Decl into the ToCtx.
458 // May be called several times in a given test.
459 // The different instances of the param From may have different ASTContext.
460 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000461 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000462 TU *FromTU = findFromTU(From);
Gabor Marton54058b52018-12-17 13:53:12 +0000463 assert(LookupTablePtr);
464 return FromTU->import(*LookupTablePtr, ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000465 }
466
Gabor Marton458d1452019-02-14 13:07:03 +0000467 template <class DeclT> DeclT *Import(DeclT *From, Language Lang) {
468 return cast_or_null<DeclT>(Import(cast<Decl>(From), Lang));
469 }
470
Gabor Marton6e1510c2018-07-12 11:50:21 +0000471 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000472 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000473 TU *FromTU = findFromTU(TUDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000474 assert(LookupTablePtr);
475 return FromTU->import(*LookupTablePtr, ToAST.get(), FromType);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000476 }
477
Peter Szecsidedda6f2018-03-30 22:03:29 +0000478 ~ASTImporterTestBase() {
479 if (!::testing::Test::HasFailure()) return;
480
481 for (auto &Tu : FromTUs) {
482 assert(Tu.Unit);
483 llvm::errs() << "FromAST:\n";
484 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
485 llvm::errs() << "\n";
486 }
487 if (ToAST) {
488 llvm::errs() << "ToAST:\n";
489 ToAST->getASTContext().getTranslationUnitDecl()->dump();
490 }
491 }
492};
493
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000494class ASTImporterOptionSpecificTestBase
495 : public ASTImporterTestBase,
496 public ::testing::WithParamInterface<ArgVector> {
497protected:
498 ArgVector getExtraArgs() const override { return GetParam(); }
499};
500
Gabor Marton19f4f392018-06-25 13:04:37 +0000501struct ImportExpr : TestImportBase {};
502struct ImportType : TestImportBase {};
503struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000504
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000505struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +0000506
507TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
508 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
509 auto Pattern = functionDecl(hasName("f"));
510 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
511
512 auto Redecls = getCanonicalForwardRedeclChain(D0);
513 ASSERT_EQ(Redecls.size(), 1u);
514 EXPECT_EQ(D0, Redecls[0]);
515}
516
517TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
518 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
519 auto Pattern = functionDecl(hasName("f"));
520 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
521 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
522 FunctionDecl *D1 = D2->getPreviousDecl();
523
524 auto Redecls = getCanonicalForwardRedeclChain(D0);
525 ASSERT_EQ(Redecls.size(), 3u);
526 EXPECT_EQ(D0, Redecls[0]);
527 EXPECT_EQ(D1, Redecls[1]);
528 EXPECT_EQ(D2, Redecls[2]);
529}
530
531TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
532 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
533 auto Pattern = functionDecl(hasName("f"));
534 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
535 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
536 FunctionDecl *D1 = D2->getPreviousDecl();
537
538 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
539 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
540 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
541
542 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
543 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
544}
545
Gabor Marton19f4f392018-06-25 13:04:37 +0000546TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000547 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000548 testImport(
549 "void declToImport() { (void)\"foo\"; }",
550 Lang_CXX, "", Lang_CXX, Verifier,
551 functionDecl(hasDescendant(
552 stringLiteral(hasType(asString("const char [4]"))))));
553 testImport(
554 "void declToImport() { (void)L\"foo\"; }",
555 Lang_CXX, "", Lang_CXX, Verifier,
556 functionDecl(hasDescendant(
557 stringLiteral(hasType(asString("const wchar_t [4]"))))));
558 testImport(
559 "void declToImport() { (void) \"foo\" \"bar\"; }",
560 Lang_CXX, "", Lang_CXX, Verifier,
561 functionDecl(hasDescendant(
562 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000563}
564
Tom Roeder521f0042019-02-26 19:26:41 +0000565TEST_P(ImportExpr, ImportChooseExpr) {
566 MatchVerifier<Decl> Verifier;
567
568 // This case tests C code that is not condition-dependent and has a true
569 // condition.
570 testImport(
571 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
572 Lang_C, "", Lang_C, Verifier,
573 functionDecl(hasDescendant(chooseExpr())));
574}
575
Gabor Marton19f4f392018-06-25 13:04:37 +0000576TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000577 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000578 testImport(
579 "void declToImport() { (void)__null; }",
580 Lang_CXX, "", Lang_CXX, Verifier,
581 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000582}
583
Gabor Marton19f4f392018-06-25 13:04:37 +0000584TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000585 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000586 testImport(
587 "void declToImport() { (void)nullptr; }",
588 Lang_CXX11, "", Lang_CXX11, Verifier,
589 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000590}
591
592
Gabor Marton19f4f392018-06-25 13:04:37 +0000593TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000594 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000595 testImport(
596 "void declToImport() { (void)1.0; }",
597 Lang_C, "", Lang_C, Verifier,
598 functionDecl(hasDescendant(
599 floatLiteral(equals(1.0), hasType(asString("double"))))));
600 testImport(
601 "void declToImport() { (void)1.0e-5f; }",
602 Lang_C, "", Lang_C, Verifier,
603 functionDecl(hasDescendant(
604 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000605}
606
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000607TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
608 MatchVerifier<Decl> Verifier;
609 testImport(
610 "void declToImport() { (void)1.0i; }",
611 Lang_CXX14, "", Lang_CXX14, Verifier,
612 functionDecl(hasDescendant(imaginaryLiteral())));
613}
614
Gabor Marton19f4f392018-06-25 13:04:37 +0000615TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000616 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000617 testImport(
618 "void declToImport() {"
619 " struct s { int x; long y; unsigned z; }; "
620 " (void)(struct s){ 42, 0L, 1U }; }",
621 Lang_CXX, "", Lang_CXX, Verifier,
622 functionDecl(hasDescendant(
623 compoundLiteralExpr(
624 hasType(asString("struct s")),
625 has(initListExpr(
626 hasType(asString("struct s")),
627 has(integerLiteral(
628 equals(42), hasType(asString("int")))),
629 has(integerLiteral(
630 equals(0), hasType(asString("long")))),
631 has(integerLiteral(
632 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000633}
634
Gabor Marton19f4f392018-06-25 13:04:37 +0000635TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000636 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000637 testImport(
638 "class declToImport { void f() { (void)this; } };",
639 Lang_CXX, "", Lang_CXX, Verifier,
640 cxxRecordDecl(
641 hasMethod(
642 hasDescendant(
643 cxxThisExpr(
644 hasType(
645 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000646}
647
Gabor Marton19f4f392018-06-25 13:04:37 +0000648TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000649 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000650 testImport(
651 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
652 Lang_C, "", Lang_C, Verifier,
653 functionDecl(hasDescendant(
654 atomicExpr(
655 has(ignoringParenImpCasts(
656 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
657 hasType(asString("int *"))))),
658 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000659}
660
Gabor Marton19f4f392018-06-25 13:04:37 +0000661TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000662 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000663 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000664 "void declToImport() { loop: goto loop; (void)&&loop; }",
665 Lang_C, "", Lang_C, Verifier,
666 functionDecl(
667 hasDescendant(
668 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
669 hasDescendant(
670 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000671}
672
673AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
674 internal::Matcher<NamedDecl>, InnerMatcher) {
675 const NamedDecl *Template = Node.getTemplatedDecl();
676 return Template && InnerMatcher.matches(*Template, Finder, Builder);
677}
678
Gabor Marton19f4f392018-06-25 13:04:37 +0000679TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000680 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000681 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000682 "template<typename T> class dummy { void f() { dummy X(*this); } };"
683 "typedef dummy<int> declToImport;"
684 "template class dummy<int>;",
685 Lang_CXX, "", Lang_CXX, Verifier,
686 typedefDecl(hasType(templateSpecializationType(
687 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
688 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
689 hasName("f"),
690 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
691 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
692 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000693 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000694}
695
Gabor Marton19f4f392018-06-25 13:04:37 +0000696TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000697 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000698 testImport(
699 "void declToImport() { int b; switch (b) { case 1: break; } }",
700 Lang_C, "", Lang_C, Verifier,
701 functionDecl(hasDescendant(
702 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000703}
704
Gabor Marton19f4f392018-06-25 13:04:37 +0000705TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000706 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000707 testImport(
708 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
709 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000710 functionDecl(hasDescendant(
711 varDecl(
712 hasName("C"),
713 hasType(asString("int")),
714 hasInitializer(
715 stmtExpr(
716 hasAnySubstatement(declStmt(hasSingleDecl(
717 varDecl(
718 hasName("X"),
719 hasType(asString("int")),
720 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000721 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000722 hasDescendant(
723 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000724}
725
Gabor Marton19f4f392018-06-25 13:04:37 +0000726TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000727 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000728 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000729 "void declToImport() { (void)(true ? 1 : -5); }",
730 Lang_CXX, "", Lang_CXX, Verifier,
731 functionDecl(hasDescendant(
732 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000733 hasCondition(cxxBoolLiteral(equals(true))),
734 hasTrueExpression(integerLiteral(equals(1))),
735 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000736 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
737 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000738}
739
Gabor Marton19f4f392018-06-25 13:04:37 +0000740TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000741 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000742 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000743 "void declToImport() { (void)(1 ?: -5); }",
744 Lang_CXX, "", Lang_CXX, Verifier,
745 functionDecl(hasDescendant(
746 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000747 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000748 implicitCastExpr(
749 hasSourceExpression(opaqueValueExpr(
750 hasSourceExpression(integerLiteral(equals(1))))),
751 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000752 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000753 opaqueValueExpr(
754 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000755 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000756 unaryOperator(
757 hasOperatorName("-"),
758 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000759}
760
Gabor Marton19f4f392018-06-25 13:04:37 +0000761TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000762 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000763 testImport(
764 "void declToImport() {"
765 " struct point { double x; double y; };"
766 " struct point ptarray[10] = "
767 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
768 Lang_C, "", Lang_C, Verifier,
769 functionDecl(hasDescendant(
770 initListExpr(
771 has(designatedInitExpr(
772 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000773 hasDescendant(floatLiteral(equals(1.0))),
774 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000775 has(designatedInitExpr(
776 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000777 hasDescendant(floatLiteral(equals(2.0))),
778 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000779 has(designatedInitExpr(
780 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000781 hasDescendant(floatLiteral(equals(1.0))),
782 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000783}
784
Gabor Marton19f4f392018-06-25 13:04:37 +0000785TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000786 MatchVerifier<Decl> Verifier;
787 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000788 testImport(
789 "void declToImport() { (void)__func__; }",
790 Lang_CXX, "", Lang_CXX, Verifier,
791 functionDecl(hasDescendant(
792 predefinedExpr(
793 hasType(
794 asString("const char [13]")),
795 has(stringLiteral(hasType(
796 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000797}
798
Gabor Marton19f4f392018-06-25 13:04:37 +0000799TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000800 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000801 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000802 "void declToImport() {"
803 " struct point { double x; double y; };"
804 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
805 " [0].x = 1.0 }; }",
806 Lang_CXX, "", Lang_CXX, Verifier,
807 functionDecl(hasDescendant(
808 initListExpr(
809 has(
810 cxxConstructExpr(
811 requiresZeroInitialization())),
812 has(
813 initListExpr(
814 hasType(asString("struct point")),
815 has(floatLiteral(equals(1.0))),
816 has(implicitValueInitExpr(
817 hasType(asString("double")))))),
818 has(
819 initListExpr(
820 hasType(asString("struct point")),
821 has(floatLiteral(equals(2.0))),
822 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000823}
824
825
Aleksei Sidorina693b372016-09-28 10:16:56 +0000826const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
827
Gabor Marton19f4f392018-06-25 13:04:37 +0000828TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000829 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000830 testImport(
831 "void declToImport(__builtin_va_list list, ...) {"
832 " (void)__builtin_va_arg(list, int); }",
833 Lang_CXX, "", Lang_CXX, Verifier,
834 functionDecl(hasDescendant(
835 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000836}
837
Gabor Marton19f4f392018-06-25 13:04:37 +0000838TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000839 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000840 testImport(
841 "struct C {};"
842 "void declToImport() { C c = C(); }",
843 Lang_CXX, "", Lang_CXX, Verifier,
844 functionDecl(hasDescendant(
845 exprWithCleanups(has(cxxConstructExpr(
846 has(materializeTemporaryExpr(has(implicitCastExpr(
847 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000848}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000849
Gabor Marton19f4f392018-06-25 13:04:37 +0000850TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000851 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000852 testImport(
853 "void declToImport() { typedef _Atomic(int) a_int; }",
854 Lang_CXX11, "", Lang_CXX11, Verifier,
855 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000856}
857
Gabor Marton19f4f392018-06-25 13:04:37 +0000858TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000859 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000860 testImport(
861 "template <typename T> void declToImport() { };",
862 Lang_CXX, "", Lang_CXX, Verifier,
863 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000864}
865
Gabor Marton19f4f392018-06-25 13:04:37 +0000866TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000867 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000868 testImport(
869 "template <typename T> struct C { T t; };"
870 "template <typename T> void declToImport() {"
871 " C<T> d;"
872 " (void)d.t;"
873 "}"
874 "void instantiate() { declToImport<int>(); }",
875 Lang_CXX, "", Lang_CXX, Verifier,
876 functionTemplateDecl(hasDescendant(
877 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
878 testImport(
879 "template <typename T> struct C { T t; };"
880 "template <typename T> void declToImport() {"
881 " C<T> d;"
882 " (void)(&d)->t;"
883 "}"
884 "void instantiate() { declToImport<int>(); }",
885 Lang_CXX, "", Lang_CXX, Verifier,
886 functionTemplateDecl(hasDescendant(
887 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000888}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000889
Gabor Marton19f4f392018-06-25 13:04:37 +0000890TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000891 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000892 testImport(
893 "template <int K>"
894 "struct dummy { static const int i = K; };"
895 "template <int K> using dummy2 = dummy<K>;"
896 "int declToImport() { return dummy2<3>::i; }",
897 Lang_CXX11, "", Lang_CXX11, Verifier,
898 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000899 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000900 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
901}
902
903const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
904 varTemplateSpecializationDecl;
905
Gabor Marton19f4f392018-06-25 13:04:37 +0000906TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000907 MatchVerifier<Decl> Verifier;
908 testImport(
909 "template <typename T>"
910 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000911 "void declToImport() { (void)pi<int>; }",
912 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000913 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000914 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000915 unless(hasAncestor(translationUnitDecl(has(varDecl(
916 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000917}
918
Gabor Marton19f4f392018-06-25 13:04:37 +0000919TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000920 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000921 testImport(
922 "template <typename... Args>"
923 "struct dummy {"
924 " dummy(Args... args) {}"
925 " static const int i = 4;"
926 "};"
927 "int declToImport() { return dummy<int>::i; }",
928 Lang_CXX11, "", Lang_CXX11, Verifier,
929 functionDecl(hasDescendant(
930 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000931}
932
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000933const internal::VariadicDynCastAllOfMatcher<Type,
934 DependentTemplateSpecializationType>
935 dependentTemplateSpecializationType;
936
Gabor Marton19f4f392018-06-25 13:04:37 +0000937TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000938 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000939 testImport(
940 "template<typename T>"
941 "struct A;"
942 "template<typename T>"
943 "struct declToImport {"
944 " typename A<T>::template B<T> a;"
945 "};",
946 Lang_CXX, "", Lang_CXX, Verifier,
947 classTemplateDecl(has(cxxRecordDecl(has(
948 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000949}
950
951const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
952 sizeOfPackExpr;
953
Gabor Marton19f4f392018-06-25 13:04:37 +0000954TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000955 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000956 testImport(
957 "template <typename... Ts>"
958 "void declToImport() {"
959 " const int i = sizeof...(Ts);"
960 "};"
961 "void g() { declToImport<int>(); }",
962 Lang_CXX11, "", Lang_CXX11, Verifier,
963 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000964 testImport(
965 "template <typename... Ts>"
966 "using X = int[sizeof...(Ts)];"
967 "template <typename... Us>"
968 "struct Y {"
969 " X<Us..., int, double, int, Us...> f;"
970 "};"
971 "Y<float, int> declToImport;",
972 Lang_CXX11, "", Lang_CXX11, Verifier,
973 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
974 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
975}
976
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000977/// \brief Matches __builtin_types_compatible_p:
978/// GNU extension to check equivalent types
979/// Given
980/// \code
981/// __builtin_types_compatible_p(int, int)
982/// \endcode
983// will generate TypeTraitExpr <...> 'int'
984const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
985
Gabor Marton19f4f392018-06-25 13:04:37 +0000986TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000987 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000988 testImport(
989 "void declToImport() { "
990 " (void)__builtin_types_compatible_p(int, int);"
991 "}",
992 Lang_C, "", Lang_C, Verifier,
993 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000994}
995
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000996const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
997
Gabor Marton19f4f392018-06-25 13:04:37 +0000998TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000999 MatchVerifier<Decl> Verifier;
1000 testImport(
1001 "namespace std { class type_info {}; }"
1002 "void declToImport() {"
1003 " int x;"
1004 " auto a = typeid(int); auto b = typeid(x);"
1005 "}",
1006 Lang_CXX11, "", Lang_CXX11, Verifier,
1007 functionDecl(
1008 hasDescendant(varDecl(
1009 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
1010 hasDescendant(varDecl(
1011 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
1012}
1013
Gabor Marton19f4f392018-06-25 13:04:37 +00001014TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001015 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001016 testImport(
1017 "template<typename T> struct declToImport {"
1018 " void m() { (void)__is_pod(T); }"
1019 "};"
1020 "void f() { declToImport<int>().m(); }",
1021 Lang_CXX11, "", Lang_CXX11, Verifier,
1022 classTemplateDecl(has(cxxRecordDecl(has(
1023 functionDecl(hasDescendant(
1024 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001025}
Gabor Horvath7a91c082017-11-14 11:30:38 +00001026
Gabor Marton6e1510c2018-07-12 11:50:21 +00001027TEST_P(ImportDecl, ImportRecordDeclInFunc) {
1028 MatchVerifier<Decl> Verifier;
1029 testImport("int declToImport() { "
1030 " struct data_t {int a;int b;};"
1031 " struct data_t d;"
1032 " return 0;"
1033 "}",
1034 Lang_C, "", Lang_C, Verifier,
1035 functionDecl(hasBody(compoundStmt(
1036 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
1037}
1038
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001039TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001040 Decl *FromTU = getTuDecl("int declToImport() { "
1041 " struct data_t {int a;int b;};"
1042 " struct data_t d;"
1043 " return 0;"
1044 "}",
1045 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +00001046 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +00001047 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
1048 ASSERT_TRUE(FromVar);
1049 auto ToType =
1050 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
1051 EXPECT_FALSE(ToType.isNull());
1052}
1053
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001054TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001055 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +00001056 Decl *FromTU = getTuDecl(
1057 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1058 Lang_C, "input.c");
1059 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1060 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001061 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001062 auto *To = Import(From, Lang_C);
1063 EXPECT_EQ(To, nullptr);
1064}
1065
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001066TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001067 Decl *FromTU = getTuDecl(
1068 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1069 "int declToImport(){ return NONAME_SIZEOF(int); }",
1070 Lang_C, "input.c");
1071 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1072 FromTU, functionDecl(hasName("declToImport")));
1073 ASSERT_TRUE(From);
1074 auto *To = Import(From, Lang_C);
1075 ASSERT_TRUE(To);
1076 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1077 To, functionDecl(hasName("declToImport"),
1078 hasDescendant(unaryExprOrTypeTraitExpr()))));
1079}
1080
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001081TEST_P(ASTImporterOptionSpecificTestBase,
1082 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001083 // This construct is not supported by ASTImporter.
1084 Decl *FromTU = getTuDecl(
1085 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1086 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1087 Lang_C, "input.c");
1088 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1089 FromTU, functionDecl(hasName("declToImport")));
1090 ASSERT_TRUE(From);
1091 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001092 EXPECT_EQ(To, nullptr);
1093}
1094
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001095const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1096 cxxPseudoDestructorExpr;
1097
Gabor Marton19f4f392018-06-25 13:04:37 +00001098TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001099 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001100 testImport(
1101 "typedef int T;"
1102 "void declToImport(int *p) {"
1103 " T t;"
1104 " p->T::~T();"
1105 "}",
1106 Lang_CXX, "", Lang_CXX, Verifier,
1107 functionDecl(hasDescendant(
1108 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001109}
1110
Gabor Marton19f4f392018-06-25 13:04:37 +00001111TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001112 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001113 testImport(
1114 "namespace foo { int bar; }"
1115 "void declToImport() { using foo::bar; }",
1116 Lang_CXX, "", Lang_CXX, Verifier,
1117 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001118}
1119
1120/// \brief Matches shadow declarations introduced into a scope by a
1121/// (resolved) using declaration.
1122///
1123/// Given
1124/// \code
1125/// namespace n { int f; }
1126/// namespace declToImport { using n::f; }
1127/// \endcode
1128/// usingShadowDecl()
1129/// matches \code f \endcode
1130const internal::VariadicDynCastAllOfMatcher<Decl,
1131 UsingShadowDecl> usingShadowDecl;
1132
Gabor Marton19f4f392018-06-25 13:04:37 +00001133TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001134 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001135 testImport(
1136 "namespace foo { int bar; }"
1137 "namespace declToImport { using foo::bar; }",
1138 Lang_CXX, "", Lang_CXX, Verifier,
1139 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001140}
1141
Gabor Marton19f4f392018-06-25 13:04:37 +00001142TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001143 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001144 testImport(
1145 "template<typename T> int foo();"
1146 "template <typename T> void declToImport() {"
1147 " (void)::foo<T>;"
1148 " (void)::template foo<T>;"
1149 "}"
1150 "void instantiate() { declToImport<int>(); }",
1151 Lang_CXX, "", Lang_CXX, Verifier,
1152 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001153}
1154
Gabor Marton19f4f392018-06-25 13:04:37 +00001155TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001156 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001157 testImport(
1158 "template <typename T> struct C { T t; };"
1159 "template <typename T> void declToImport() {"
1160 " C<T> d;"
1161 " d.t = T();"
1162 "}"
1163 "void instantiate() { declToImport<int>(); }",
1164 Lang_CXX, "", Lang_CXX, Verifier,
1165 functionTemplateDecl(hasDescendant(
1166 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1167 testImport(
1168 "template <typename T> struct C { T t; };"
1169 "template <typename T> void declToImport() {"
1170 " C<T> d;"
1171 " (&d)->t = T();"
1172 "}"
1173 "void instantiate() { declToImport<int>(); }",
1174 Lang_CXX, "", Lang_CXX, Verifier,
1175 functionTemplateDecl(hasDescendant(
1176 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001177}
1178
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001179/// Check that function "declToImport()" (which is the templated function
1180/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1181/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001182TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001183 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001184 testImport(
1185 "template <typename T> void declToImport() { T a = 1; }"
1186 "void instantiate() { declToImport<int>(); }",
1187 Lang_CXX, "", Lang_CXX, Verifier,
1188 functionTemplateDecl(hasAncestor(translationUnitDecl(
1189 unless(has(functionDecl(hasName("declToImport"))))))));
1190 testImport(
1191 "template <typename T> struct declToImport { T t; };"
1192 "void instantiate() { declToImport<int>(); }",
1193 Lang_CXX, "", Lang_CXX, Verifier,
1194 classTemplateDecl(hasAncestor(translationUnitDecl(
1195 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001196}
1197
Gabor Marton19f4f392018-06-25 13:04:37 +00001198TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001199 MatchVerifier<Decl> Verifier;
1200 auto Code =
1201 R"s(
1202 struct declToImport {
1203 template <typename T0> struct X;
1204 template <typename T0> struct X<T0 *> {};
1205 };
1206 )s";
1207 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1208 recordDecl(has(classTemplateDecl()),
1209 has(classTemplateSpecializationDecl())));
1210}
1211
Gabor Marton19f4f392018-06-25 13:04:37 +00001212TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001213 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001214 testImport(
1215 "class declToImport {"
1216 " void f() { *this = declToImport(); }"
1217 "};",
1218 Lang_CXX, "", Lang_CXX, Verifier,
1219 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1220 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001221}
1222
Gabor Marton19f4f392018-06-25 13:04:37 +00001223TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001224 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001225 testImport(
1226 "template<typename T, int Size> class declToImport {"
1227 " T data[Size];"
1228 "};",
1229 Lang_CXX, "", Lang_CXX, Verifier,
1230 classTemplateDecl(has(cxxRecordDecl(
1231 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001232}
1233
Balazs Keri5f4fd8b2019-03-14 14:20:23 +00001234TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1235 Decl *FromTU = getTuDecl(
1236 "class A { public: static int X; }; void f() { (void)A::X; }", Lang_CXX);
1237 auto From = FirstDeclMatcher<FunctionDecl>().match(
1238 FromTU, functionDecl(hasName("f")));
1239 ASSERT_TRUE(From);
1240 ASSERT_TRUE(
1241 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1242 ->getSubExpr()
1243 ->getBeginLoc()
1244 .isValid());
1245 FunctionDecl *To = Import(From, Lang_CXX);
1246 ASSERT_TRUE(To);
1247 ASSERT_TRUE(
1248 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1249 ->getSubExpr()
1250 ->getBeginLoc()
1251 .isValid());
1252}
1253
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001254TEST_P(ASTImporterOptionSpecificTestBase,
1255 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001256 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1257 auto From =
1258 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1259 ASSERT_TRUE(From);
1260 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1261 ASSERT_TRUE(To);
1262 Decl *ToTemplated = To->getTemplatedDecl();
1263 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1264 EXPECT_TRUE(ToTemplated1);
1265 EXPECT_EQ(ToTemplated1, ToTemplated);
1266}
1267
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001268TEST_P(ASTImporterOptionSpecificTestBase,
1269 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001270 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1271 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1272 FromTU, functionTemplateDecl());
1273 ASSERT_TRUE(From);
1274 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1275 ASSERT_TRUE(To);
1276 Decl *ToTemplated = To->getTemplatedDecl();
1277 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1278 EXPECT_TRUE(ToTemplated1);
1279 EXPECT_EQ(ToTemplated1, ToTemplated);
1280}
1281
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001282TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001283 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1284 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1285 auto FromFT =
1286 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1287 ASSERT_TRUE(FromFT);
1288
1289 auto ToTemplated =
1290 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1291 EXPECT_TRUE(ToTemplated);
1292 auto ToTU = ToTemplated->getTranslationUnitDecl();
1293 auto ToFT =
1294 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1295 EXPECT_TRUE(ToFT);
1296}
1297
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001298TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001299 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001300 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1301 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1302 FromTU, functionTemplateDecl());
1303 ASSERT_TRUE(FromFT);
1304
1305 auto ToTemplated =
1306 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1307 EXPECT_TRUE(ToTemplated);
1308 auto ToTU = ToTemplated->getTranslationUnitDecl();
1309 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1310 ToTU, functionTemplateDecl());
1311 EXPECT_TRUE(ToFT);
1312}
1313
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001314TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001315 auto Code =
1316 R"(
1317 namespace x {
1318 template<class X> struct S1{};
1319 template<class X> struct S2{};
1320 template<class X> struct S3{};
1321 }
1322 )";
1323 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1324 auto FromNs =
1325 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1326 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1327 ASSERT_TRUE(ToNs);
1328 auto From =
1329 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1330 classTemplateDecl(
1331 hasName("S2")));
1332 auto To =
1333 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1334 classTemplateDecl(
1335 hasName("S2")));
1336 ASSERT_TRUE(From);
1337 ASSERT_TRUE(To);
1338 auto ToTemplated = To->getTemplatedDecl();
1339 auto ToTemplated1 =
1340 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1341 EXPECT_TRUE(ToTemplated1);
1342 ASSERT_EQ(ToTemplated1, ToTemplated);
1343}
1344
Tom Roeder521f0042019-02-26 19:26:41 +00001345TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1346 // This tests the import of isConditionTrue directly to make sure the importer
1347 // gets it right.
1348 Decl *From, *To;
1349 std::tie(From, To) = getImportedDecl(
1350 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1351 Lang_C, "", Lang_C);
1352
1353 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1354 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1355
1356 const ChooseExpr *FromChooseExpr =
1357 selectFirst<ChooseExpr>("choose", FromResults);
1358 ASSERT_TRUE(FromChooseExpr);
1359
1360 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1361 ASSERT_TRUE(ToChooseExpr);
1362
1363 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1364 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1365 ToChooseExpr->isConditionDependent());
1366}
1367
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001368TEST_P(ASTImporterOptionSpecificTestBase,
1369 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001370 Decl *From, *To;
1371 std::tie(From, To) = getImportedDecl(
1372 R"(
1373 template <typename T> struct X {};
1374
1375 void declToImport(int y, X<int> &x) {}
1376
1377 template <> struct X<int> {
1378 void g() {
1379 X<int> x;
1380 declToImport(0, x);
1381 }
1382 };
1383 )",
1384 Lang_CXX, "", Lang_CXX);
1385
1386 MatchVerifier<Decl> Verifier;
1387 auto Matcher = functionDecl(hasName("declToImport"),
1388 parameterCountIs(2),
1389 hasParameter(0, hasName("y")),
1390 hasParameter(1, hasName("x")),
1391 hasParameter(1, hasType(asString("X<int> &"))));
1392 ASSERT_TRUE(Verifier.match(From, Matcher));
1393 EXPECT_TRUE(Verifier.match(To, Matcher));
1394}
1395
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001396TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001397 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1398 Decl *From, *To;
1399 std::tie(From, To) =
1400 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1401 "void instantiate() { declToImport<int>(); }",
1402 Lang_CXX, "", Lang_CXX);
1403
1404 auto Check = [](Decl *D) -> bool {
1405 auto TU = D->getTranslationUnitDecl();
1406 for (auto Child : TU->decls()) {
1407 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1408 if (FD->getNameAsString() == "declToImport") {
1409 GTEST_NONFATAL_FAILURE_(
1410 "TU should not contain any FunctionDecl with name declToImport");
1411 return false;
1412 }
1413 }
1414 }
1415 return true;
1416 };
1417
1418 ASSERT_TRUE(Check(From));
1419 EXPECT_TRUE(Check(To));
1420}
1421
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001422TEST_P(ASTImporterOptionSpecificTestBase,
1423 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001424 Decl *From, *To;
1425 std::tie(From, To) =
1426 getImportedDecl("template <typename T> struct declToImport { T t; };"
1427 "void instantiate() { declToImport<int>(); }",
1428 Lang_CXX, "", Lang_CXX);
1429
1430 auto Check = [](Decl *D) -> bool {
1431 auto TU = D->getTranslationUnitDecl();
1432 for (auto Child : TU->decls()) {
1433 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1434 if (RD->getNameAsString() == "declToImport") {
1435 GTEST_NONFATAL_FAILURE_(
1436 "TU should not contain any CXXRecordDecl with name declToImport");
1437 return false;
1438 }
1439 }
1440 }
1441 return true;
1442 };
1443
1444 ASSERT_TRUE(Check(From));
1445 EXPECT_TRUE(Check(To));
1446}
1447
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001448TEST_P(ASTImporterOptionSpecificTestBase,
1449 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001450 Decl *From, *To;
1451 std::tie(From, To) =
1452 getImportedDecl(
1453 "template <typename T> struct X {};"
1454 "template <typename T> using declToImport = X<T>;"
1455 "void instantiate() { declToImport<int> a; }",
1456 Lang_CXX11, "", Lang_CXX11);
1457
1458 auto Check = [](Decl *D) -> bool {
1459 auto TU = D->getTranslationUnitDecl();
1460 for (auto Child : TU->decls()) {
1461 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1462 if (AD->getNameAsString() == "declToImport") {
1463 GTEST_NONFATAL_FAILURE_(
1464 "TU should not contain any TypeAliasDecl with name declToImport");
1465 return false;
1466 }
1467 }
1468 }
1469 return true;
1470 };
1471
1472 ASSERT_TRUE(Check(From));
1473 EXPECT_TRUE(Check(To));
1474}
1475
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001476TEST_P(ASTImporterOptionSpecificTestBase,
1477 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001478
1479 Decl *From, *To;
1480 std::tie(From, To) = getImportedDecl(
1481 R"(
1482 template<class T>
1483 class Base {};
1484 class declToImport : public Base<declToImport> {};
1485 )",
1486 Lang_CXX, "", Lang_CXX);
1487
1488 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1489 auto Pattern =
1490 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1491 ASSERT_TRUE(
1492 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1493 EXPECT_TRUE(
1494 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1495
1496 // Check that the ClassTemplateSpecializationDecl is the child of the
1497 // ClassTemplateDecl.
1498 Pattern = translationUnitDecl(has(classTemplateDecl(
1499 hasName("Base"), has(classTemplateSpecializationDecl()))));
1500 ASSERT_TRUE(
1501 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1502 EXPECT_TRUE(
1503 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1504}
1505
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001506AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1507 size_t Index = 0;
1508 for (FieldDecl *Field : Node.fields()) {
1509 if (Index == Order.size())
1510 return false;
1511 if (Field->getName() != Order[Index])
1512 return false;
1513 ++Index;
1514 }
1515 return Index == Order.size();
1516}
1517
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001518TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001519 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1520 Decl *From, *To;
1521 std::tie(From, To) = getImportedDecl(
1522 R"(
1523 namespace NS {
1524 template<class T>
1525 class X {};
1526 template class X<int>;
1527 }
1528 )",
1529 Lang_CXX, "", Lang_CXX, "NS");
1530
1531 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1532 // ClassTemplateDecl.
1533 auto Pattern = namespaceDecl(has(classTemplateDecl(
1534 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1535 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1536 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1537
1538 // Check that the ClassTemplateSpecializationDecl is the child of the
1539 // NamespaceDecl.
1540 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1541 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1542 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1543}
1544
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001545TEST_P(ASTImporterOptionSpecificTestBase,
1546 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001547 Decl *From, *To;
1548 std::tie(From, To) =
1549 getImportedDecl(
1550 "struct declToImport { int a; int b; };",
1551 Lang_CXX11, "", Lang_CXX11);
1552
1553 MatchVerifier<Decl> Verifier;
1554 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1555 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1556}
1557
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001558TEST_P(ASTImporterOptionSpecificTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001559 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001560 Decl *From, *To;
1561 std::tie(From, To) = getImportedDecl(
1562 // The original recursive algorithm of ASTImporter first imports 'c' then
1563 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1564 R"s(
1565 struct declToImport {
1566 int a = c + b;
1567 int b = 1;
1568 int c = 2;
1569 };
1570 )s",
1571 Lang_CXX11, "", Lang_CXX11);
1572
1573 MatchVerifier<Decl> Verifier;
1574 ASSERT_TRUE(
1575 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1576 EXPECT_TRUE(
1577 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1578}
1579
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001580TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001581 Decl *From, *To;
1582 std::tie(From, To) = getImportedDecl(
1583 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001584 struct declToImport {
1585 };
1586 )",
1587 Lang_CXX, "", Lang_CXX);
1588
1589 MatchVerifier<Decl> Verifier;
1590 // Match the implicit Decl.
1591 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1592 ASSERT_TRUE(Verifier.match(From, Matcher));
1593 EXPECT_TRUE(Verifier.match(To, Matcher));
1594}
1595
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001596TEST_P(ASTImporterOptionSpecificTestBase,
1597 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001598 Decl *From, *To;
1599 std::tie(From, To) = getImportedDecl(
1600 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001601 template <typename U>
1602 struct declToImport {
1603 };
1604 )",
1605 Lang_CXX, "", Lang_CXX);
1606
1607 MatchVerifier<Decl> Verifier;
1608 // Match the implicit Decl.
1609 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1610 ASSERT_TRUE(Verifier.match(From, Matcher));
1611 EXPECT_TRUE(Verifier.match(To, Matcher));
1612}
1613
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001614TEST_P(ASTImporterOptionSpecificTestBase,
1615 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001616 Decl *From, *To;
1617 std::tie(From, To) = getImportedDecl(
1618 R"(
1619 template<class T>
1620 class Base {};
1621 class declToImport : public Base<declToImport> {};
1622 )",
1623 Lang_CXX, "", Lang_CXX);
1624
1625 auto hasImplicitClass = has(cxxRecordDecl());
1626 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1627 hasName("Base"),
1628 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1629 ASSERT_TRUE(
1630 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1631 EXPECT_TRUE(
1632 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1633}
1634
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001635TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001636 Decl *From, *To;
1637 std::tie(From, To) =
1638 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1639
1640 MatchVerifier<Decl> Verifier;
1641 auto Matcher = functionDecl();
1642 ASSERT_TRUE(Verifier.match(From, Matcher));
1643 EXPECT_TRUE(Verifier.match(To, Matcher));
1644 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1645}
1646
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001647TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001648 Decl *FromTU = getTuDecl(
1649 R"(
1650 struct X {};
1651 void operator<<(int, X);
1652 )",
1653 Lang_CXX);
1654 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1655 const Decl *To = Import(From, Lang_CXX);
1656 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1657}
1658
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001659TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001660 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1661 Decl *From, *To;
1662 std::tie(From, To) = getImportedDecl(
1663 R"(
1664 template<class T>
1665 class Base { int a; };
1666 class declToImport : Base<declToImport> {};
1667 )",
1668 Lang_CXX, "", Lang_CXX);
1669
1670 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1671 hasName("Base"),
1672 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1673 ASSERT_TRUE(
1674 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1675 EXPECT_TRUE(
1676 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1677}
1678
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001679TEST_P(ASTImporterOptionSpecificTestBase,
1680 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001681 {
1682 Decl *FromTU = getTuDecl(
1683 R"(
1684 template <typename T>
1685 struct B;
1686 )",
1687 Lang_CXX, "input0.cc");
1688 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1689 FromTU, classTemplateDecl(hasName("B")));
1690
1691 Import(FromD, Lang_CXX);
1692 }
1693
1694 {
1695 Decl *FromTU = getTuDecl(
1696 R"(
1697 template <typename T>
1698 struct B {
1699 void f();
1700 };
1701 )",
1702 Lang_CXX, "input1.cc");
1703 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1704 FromTU, functionDecl(hasName("f")));
1705 Import(FromD, Lang_CXX);
1706 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1707 FromTU, classTemplateDecl(hasName("B")));
1708 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1709 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1710 }
1711}
1712
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001713TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001714 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1715 Decl *ToTU = getToTuDecl(
1716 R"(
1717 template <typename T>
1718 struct B {
1719 void f();
1720 };
1721
1722 template <typename T>
1723 struct B;
1724 )",
1725 Lang_CXX);
1726 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1727 [](const ClassTemplateDecl *T) {
1728 return T->isThisDeclarationADefinition();
1729 })
1730 .match(ToTU, classTemplateDecl()));
1731
1732 Decl *FromTU = getTuDecl(
1733 R"(
1734 template <typename T>
1735 struct B {
1736 void f();
1737 };
1738 )",
1739 Lang_CXX, "input1.cc");
1740 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1741 FromTU, classTemplateDecl(hasName("B")));
1742
1743 Import(FromD, Lang_CXX);
1744
1745 // We should have only one definition.
1746 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1747 [](const ClassTemplateDecl *T) {
1748 return T->isThisDeclarationADefinition();
1749 })
1750 .match(ToTU, classTemplateDecl()));
1751}
1752
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001753TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001754 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1755 Decl *ToTU = getToTuDecl(
1756 R"(
1757 struct B {
1758 void f();
1759 };
1760
1761 struct B;
1762 )",
1763 Lang_CXX);
1764 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001765 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001766
1767 Decl *FromTU = getTuDecl(
1768 R"(
1769 struct B {
1770 void f();
1771 };
1772 )",
1773 Lang_CXX, "input1.cc");
1774 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1775 FromTU, cxxRecordDecl(hasName("B")));
1776
1777 Import(FromD, Lang_CXX);
1778
1779 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001780 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001781}
1782
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001783static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1784 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1785 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1786 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1787 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1788}
1789static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1790 SourceManager &SM1, SourceManager &SM2) {
1791 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1792 FullSourceLoc{ Range2.getBegin(), SM2 });
1793 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1794 FullSourceLoc{ Range2.getEnd(), SM2 });
1795}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001796TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001797 Decl *FromTU = getTuDecl(
1798 R"(
1799 #define MFOO(arg) arg = arg + 1
1800
1801 void foo() {
1802 int a = 5;
1803 MFOO(a);
1804 }
1805 )",
1806 Lang_CXX);
1807 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1808 auto ToD = Import(FromD, Lang_CXX);
1809
1810 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1811 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1812 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1813 auto FromRHS =
1814 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1815
1816 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1817 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1818 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1819 FromSM);
1820 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1821 FromSM);
1822 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1823 FromSM);
1824}
1825
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001826TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001827 Decl *FromTU = getTuDecl(
1828 R"(
1829 #define FUNC_INT void declToImport
1830 #define FUNC FUNC_INT
1831 FUNC(int a);
1832 )",
1833 Lang_CXX);
1834 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1835 auto ToD = Import(FromD, Lang_CXX);
1836
1837 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1838 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1839 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1840 FromSM);
1841}
1842
Gabor Marton9581c332018-05-23 13:53:36 +00001843TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001844 ASTImporterOptionSpecificTestBase,
1845 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001846 Decl *ToTU = getToTuDecl(
1847 R"(
1848 template <typename T>
1849 struct B;
1850
1851 template <>
1852 struct B<int> {};
1853
1854 template <>
1855 struct B<int>;
1856 )",
1857 Lang_CXX);
1858 // We should have only one definition.
1859 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1860 [](const ClassTemplateSpecializationDecl *T) {
1861 return T->isThisDeclarationADefinition();
1862 })
1863 .match(ToTU, classTemplateSpecializationDecl()));
1864
1865 Decl *FromTU = getTuDecl(
1866 R"(
1867 template <typename T>
1868 struct B;
1869
1870 template <>
1871 struct B<int> {};
1872 )",
1873 Lang_CXX, "input1.cc");
1874 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1875 FromTU, classTemplateSpecializationDecl(hasName("B")));
1876
1877 Import(FromD, Lang_CXX);
1878
1879 // We should have only one definition.
1880 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1881 [](const ClassTemplateSpecializationDecl *T) {
1882 return T->isThisDeclarationADefinition();
1883 })
1884 .match(ToTU, classTemplateSpecializationDecl()));
1885}
1886
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001887TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001888 Decl *FromTU = getTuDecl(
1889 R"(
1890 struct { int a; int b; } object0 = { 2, 3 };
1891 struct { int x; int y; int z; } object1;
1892 )",
1893 Lang_CXX, "input0.cc");
1894
Gabor Marton0bebf952018-07-05 09:51:13 +00001895 auto *Obj0 =
1896 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1897 auto *From0 = getRecordDecl(Obj0);
1898 auto *Obj1 =
1899 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1900 auto *From1 = getRecordDecl(Obj1);
1901
1902 auto *To0 = Import(From0, Lang_CXX);
1903 auto *To1 = Import(From1, Lang_CXX);
1904
1905 EXPECT_TRUE(To0);
1906 EXPECT_TRUE(To1);
1907 EXPECT_NE(To0, To1);
1908 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1909}
1910
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001911TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001912 auto *Code =
1913 R"(
1914 struct X {
1915 struct { int a; };
1916 struct { int b; };
1917 };
1918 )";
1919 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1920
1921 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1922
1923 auto *X0 =
1924 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1925 auto *X1 =
1926 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1927 Import(X0, Lang_C);
1928 Import(X1, Lang_C);
1929
1930 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1931 // We expect no (ODR) warning during the import.
1932 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1933 EXPECT_EQ(1u,
1934 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1935}
1936
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001937TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001938 Decl *FromTU0 = getTuDecl(
1939 R"(
1940 struct X {
1941 struct { int a; };
1942 struct { int b; };
1943 };
1944 )",
1945 Lang_C, "input0.c");
1946
1947 Decl *FromTU1 = getTuDecl(
1948 R"(
1949 struct X { // reversed order
1950 struct { int b; };
1951 struct { int a; };
1952 };
1953 )",
1954 Lang_C, "input1.c");
1955
1956 auto *X0 =
1957 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1958 auto *X1 =
1959 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1960 Import(X0, Lang_C);
1961 Import(X1, Lang_C);
1962
1963 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1964 // We expect one (ODR) warning during the import.
1965 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1966 EXPECT_EQ(2u,
1967 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1968}
1969
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001970TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001971 auto Pattern = varDecl(hasName("x"));
1972 VarDecl *Imported1;
1973 {
1974 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1975 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1976 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1977 }
1978 VarDecl *Imported2;
1979 {
1980 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1981 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1982 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1983 }
1984 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1985 EXPECT_FALSE(Imported2->isUsed(false));
1986 {
1987 Decl *FromTU =
1988 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001989 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1990 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001991 Import(FromD, Lang_CXX);
1992 }
1993 EXPECT_TRUE(Imported2->isUsed(false));
1994}
1995
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001996TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001997 auto Pattern = varDecl(hasName("x"));
1998 VarDecl *ExistingD;
1999 {
2000 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
2001 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2002 }
2003 EXPECT_FALSE(ExistingD->isUsed(false));
2004 {
2005 Decl *FromTU = getTuDecl(
2006 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
2007 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2008 FromTU, functionDecl(hasName("f")));
2009 Import(FromD, Lang_CXX);
2010 }
2011 EXPECT_TRUE(ExistingD->isUsed(false));
2012}
2013
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002014TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00002015 auto Pattern = varDecl(hasName("a"));
2016 VarDecl *ExistingD;
2017 {
2018 Decl *ToTU = getToTuDecl(
2019 R"(
2020 struct A {
2021 static const int a = 1;
2022 };
2023 )", Lang_CXX);
2024 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2025 }
2026 EXPECT_FALSE(ExistingD->isUsed(false));
2027 {
2028 Decl *FromTU = getTuDecl(
2029 R"(
2030 struct A {
2031 static const int a = 1;
2032 };
2033 const int *f() { return &A::a; } // requires storage,
2034 // thus used flag will be set
2035 )", Lang_CXX, "input1.cc");
2036 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
2037 FromTU, functionDecl(hasName("f")));
2038 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2039 ASSERT_TRUE(FromD->isUsed(false));
2040 Import(FromFunD, Lang_CXX);
2041 }
2042 EXPECT_TRUE(ExistingD->isUsed(false));
2043}
2044
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002045TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00002046 auto Pattern = varDecl(hasName("x"));
2047
2048 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
2049 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2050
2051 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
2052
2053 ASSERT_FALSE(Imported1->isUsed(false));
2054
2055 FromD->setIsUsed();
2056 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2057
2058 EXPECT_EQ(Imported1, Imported2);
2059 EXPECT_TRUE(Imported2->isUsed(false));
2060}
2061
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002062struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00002063
Gabor Marton5254e642018-06-27 13:32:50 +00002064TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002065 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2066 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002067 auto *From =
2068 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002069
Gabor Marton5254e642018-06-27 13:32:50 +00002070 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002071 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2072
Gabor Marton5254e642018-06-27 13:32:50 +00002073 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2074 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2075 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2076 EXPECT_TRUE(ImportedD == To0);
2077 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2078 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2079 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002080}
2081
2082TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2083 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2084 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002085 auto *From =
2086 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002087
Gabor Marton5254e642018-06-27 13:32:50 +00002088 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002089 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2090
Gabor Marton5254e642018-06-27 13:32:50 +00002091 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2092 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2093 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2094 EXPECT_TRUE(ImportedD == To1);
2095 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2096 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2097 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002098}
2099
Peter Szecsidedda6f2018-03-30 22:03:29 +00002100TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2101 auto Code =
2102 R"(
2103 struct B { virtual void f(); };
2104 void B::f() {}
2105 struct D : B { void f(); };
2106 )";
2107 auto Pattern =
2108 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2109 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2110 CXXMethodDecl *Proto =
2111 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2112
2113 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2114 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2115 EXPECT_EQ(To->size_overridden_methods(), 1u);
2116}
2117
2118TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2119 auto Code =
2120 R"(
2121 struct B { virtual void f(); };
2122 void B::f() {}
2123 )";
2124 auto Pattern =
2125 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2126 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2127 CXXMethodDecl *Proto =
2128 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2129 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2130
2131 ASSERT_TRUE(Proto->isVirtual());
2132 ASSERT_TRUE(Def->isVirtual());
2133 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2134 EXPECT_TRUE(To->isVirtual());
2135}
2136
Gabor Marton5254e642018-06-27 13:32:50 +00002137TEST_P(ImportFunctions,
2138 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2139 Decl *ToTU = getToTuDecl(
2140 R"(
2141 void f() {}
2142 void f();
2143 )",
2144 Lang_CXX);
2145 ASSERT_EQ(1u,
2146 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2147 return FD->doesThisDeclarationHaveABody();
2148 }).match(ToTU, functionDecl()));
2149
2150 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2151 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2152
2153 Import(FromD, Lang_CXX);
2154
2155 EXPECT_EQ(1u,
2156 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2157 return FD->doesThisDeclarationHaveABody();
2158 }).match(ToTU, functionDecl()));
2159}
2160
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002161TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2162 auto Code =
2163 R"(
2164 struct B { virtual void f(); };
2165 struct D:B { void f(); };
2166 )";
2167 auto BFP =
2168 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2169 auto DFP =
2170 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2171
2172 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2173 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2174 Import(DF, Lang_CXX);
2175
2176 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2177 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2178 Import(BF, Lang_CXX);
2179
2180 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2181
2182 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2183 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2184}
2185
2186TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2187 auto CodeWithoutDef =
2188 R"(
2189 struct B { virtual void f(); };
2190 struct D:B { void f(); };
2191 )";
2192 auto CodeWithDef =
2193 R"(
2194 struct B { virtual void f(){}; };
2195 struct D:B { void f(){}; };
2196 )";
2197 auto BFP =
2198 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2199 auto DFP =
2200 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2201 auto BFDefP = cxxMethodDecl(
2202 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2203 auto DFDefP = cxxMethodDecl(
2204 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2205 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2206
2207 {
2208 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2209 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2210 Import(FromD, Lang_CXX);
2211 }
2212 {
2213 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2214 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2215 Import(FromB, Lang_CXX);
2216 }
2217
2218 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2219
2220 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2221 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2222 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2223 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2224 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2225}
2226
2227TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2228 auto Code =
2229 R"(
2230 struct B { virtual void f(); };
2231 struct D:B { void f(); };
2232 void B::f(){};
2233 )";
2234
2235 auto BFP =
2236 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2237 auto BFDefP = cxxMethodDecl(
2238 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2239 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2240 unless(isDefinition()));
2241
2242 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2243 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2244 Import(D, Lang_CXX);
2245
2246 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2247 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2248 Import(B, Lang_CXX);
2249
2250 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2251
2252 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2253 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2254
2255 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2256 ToTU, cxxRecordDecl(hasName("B")));
2257 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2258 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2259 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2260
2261 // The definition should be out-of-class.
2262 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2263 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2264 ToBFOutOfClass->getLexicalDeclContext());
2265 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2266 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2267
2268 // Check that the redecl chain is intact.
2269 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2270}
2271
2272TEST_P(ImportFunctions,
2273 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2274 auto CodeTU0 =
2275 R"(
2276 struct B { virtual void f(); };
2277 struct D:B { void f(); };
2278 )";
2279 auto CodeTU1 =
2280 R"(
2281 struct B { virtual void f(); };
2282 struct D:B { void f(); };
2283 void B::f(){}
2284 void D::f(){}
2285 void foo(B &b, D &d) { b.f(); d.f(); }
2286 )";
2287
2288 auto BFP =
2289 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2290 auto BFDefP = cxxMethodDecl(
2291 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2292 auto DFP =
2293 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2294 auto DFDefP = cxxMethodDecl(
2295 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2296 auto FooDef = functionDecl(hasName("foo"));
2297
2298 {
2299 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2300 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2301 Import(D, Lang_CXX);
2302 }
2303
2304 {
2305 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2306 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2307 Import(Foo, Lang_CXX);
2308 }
2309
2310 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2311
2312 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2313 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2314 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2315 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2316
2317 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2318 ToTU, cxxRecordDecl(hasName("B")));
2319 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2320 ToTU, cxxRecordDecl(hasName("D")));
2321 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2322 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2323 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2324 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2325 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2326 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2327
2328 // The definition should be out-of-class.
2329 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2330 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2331 ToBFOutOfClass->getLexicalDeclContext());
2332 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2333 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2334
2335 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2336 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2337 ToDFOutOfClass->getLexicalDeclContext());
2338 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2339 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2340
2341 // Check that the redecl chain is intact.
2342 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2343 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2344}
2345
Gabor Marton458d1452019-02-14 13:07:03 +00002346//FIXME Move these tests to a separate test file.
2347namespace TypeAndValueParameterizedTests {
2348
2349// Type parameters for type-parameterized test fixtures.
2350struct GetFunPattern {
2351 using DeclTy = FunctionDecl;
2352 BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
2353};
2354struct GetVarPattern {
2355 using DeclTy = VarDecl;
2356 BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
2357};
2358
2359// Values for the value-parameterized test fixtures.
2360// FunctionDecl:
2361auto *ExternF = "void f();";
2362auto *StaticF = "static void f();";
2363auto *AnonF = "namespace { void f(); }";
2364// VarDecl:
2365auto *ExternV = "extern int v;";
2366auto *StaticV = "static int v;";
2367auto *AnonV = "namespace { extern int v; }";
2368
2369// First value in tuple: Compile options.
2370// Second value in tuple: Source code to be used in the test.
2371using ImportVisibilityChainParams =
2372 ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
2373// Fixture to test the redecl chain of Decls with the same visibility. Gtest
2374// makes it possible to have either value-parameterized or type-parameterized
2375// fixtures. However, we cannot have both value- and type-parameterized test
2376// fixtures. This is a value-parameterized test fixture in the gtest sense. We
2377// intend to mimic gtest's type-parameters via the PatternFactory template
2378// parameter. We manually instantiate the different tests with the each types.
2379template <typename PatternFactory>
2380class ImportVisibilityChain
2381 : public ASTImporterTestBase, public ImportVisibilityChainParams {
2382protected:
2383 using DeclTy = typename PatternFactory::DeclTy;
2384 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2385 std::string getCode() const { return std::get<1>(GetParam()); }
2386 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2387
2388 // Type-parameterized test.
2389 void TypedTest_ImportChain() {
2390 std::string Code = getCode() + getCode();
2391 auto Pattern = getPattern();
2392
2393 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
2394
2395 auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
2396 auto *FromF1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
2397
2398 auto *ToF0 = Import(FromF0, Lang_CXX);
2399 auto *ToF1 = Import(FromF1, Lang_CXX);
2400
2401 EXPECT_TRUE(ToF0);
2402 ASSERT_TRUE(ToF1);
2403 EXPECT_NE(ToF0, ToF1);
2404 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2405 }
2406};
2407
2408// Manual instantiation of the fixture with each type.
2409using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
2410using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
2411// Value-parameterized test for the first type.
2412TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
2413 TypedTest_ImportChain();
2414}
2415// Value-parameterized test for the second type.
2416TEST_P(ImportVariablesVisibilityChain, ImportChain) {
2417 TypedTest_ImportChain();
2418}
2419
2420// Automatic instantiation of the value-parameterized tests.
2421INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
2422 ::testing::Combine(
2423 DefaultTestValuesForRunOptions,
2424 ::testing::Values(ExternF, StaticF, AnonF)), );
2425INSTANTIATE_TEST_CASE_P(
2426 ParameterizedTests, ImportVariablesVisibilityChain,
2427 ::testing::Combine(
2428 DefaultTestValuesForRunOptions,
2429 // There is no point to instantiate with StaticV, because in C++ we can
2430 // forward declare a variable only with the 'extern' keyword.
2431 // Consequently, each fwd declared variable has external linkage. This
2432 // is different in the C language where any declaration without an
2433 // initializer is a tentative definition, subsequent definitions may be
2434 // provided but they must have the same linkage. See also the test
2435 // ImportVariableChainInC which test for this special C Lang case.
2436 ::testing::Values(ExternV, AnonV)), );
2437
2438// First value in tuple: Compile options.
2439// Second value in tuple: Tuple with informations for the test.
2440// Code for first import (or initial code), code to import, whether the `f`
2441// functions are expected to be linked in a declaration chain.
2442// One value of this tuple is combined with every value of compile options.
2443// The test can have a single tuple as parameter only.
2444using ImportVisibilityParams = ::testing::WithParamInterface<
2445 std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
2446
2447template <typename PatternFactory>
2448class ImportVisibility
2449 : public ASTImporterTestBase,
2450 public ImportVisibilityParams {
2451protected:
2452 using DeclTy = typename PatternFactory::DeclTy;
2453 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2454 std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
2455 std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
2456 bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
2457 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2458
2459 void TypedTest_ImportAfter() {
2460 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
2461 TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2462
2463 auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
2464 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
2465
2466 auto *ToF1 = Import(FromF1, Lang_CXX);
2467
2468 ASSERT_TRUE(ToF0);
2469 ASSERT_TRUE(ToF1);
2470 EXPECT_NE(ToF0, ToF1);
2471
2472 if (shouldBeLinked())
2473 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2474 else
2475 EXPECT_FALSE(ToF1->getPreviousDecl());
2476 }
2477
2478 void TypedTest_ImportAfterImport() {
2479 TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
2480 TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2481 auto *FromF0 =
2482 FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
2483 auto *FromF1 =
2484 FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
2485 auto *ToF0 = Import(FromF0, Lang_CXX);
2486 auto *ToF1 = Import(FromF1, Lang_CXX);
2487 ASSERT_TRUE(ToF0);
2488 ASSERT_TRUE(ToF1);
2489 EXPECT_NE(ToF0, ToF1);
2490 if (shouldBeLinked())
2491 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2492 else
2493 EXPECT_FALSE(ToF1->getPreviousDecl());
2494 }
2495};
2496using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
2497using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
2498
2499// FunctionDecl.
2500TEST_P(ImportFunctionsVisibility, ImportAfter) {
2501 TypedTest_ImportAfter();
2502}
2503TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
2504 TypedTest_ImportAfterImport();
2505}
2506// VarDecl.
2507TEST_P(ImportVariablesVisibility, ImportAfter) {
2508 TypedTest_ImportAfter();
2509}
2510TEST_P(ImportVariablesVisibility, ImportAfterImport) {
2511 TypedTest_ImportAfterImport();
2512}
2513
2514bool ExpectLink = true;
2515bool ExpectNotLink = false;
2516
2517INSTANTIATE_TEST_CASE_P(
2518 ParameterizedTests, ImportFunctionsVisibility,
2519 ::testing::Combine(
2520 DefaultTestValuesForRunOptions,
2521 ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
2522 std::make_tuple(ExternF, StaticF, ExpectNotLink),
2523 std::make_tuple(ExternF, AnonF, ExpectNotLink),
2524 std::make_tuple(StaticF, ExternF, ExpectNotLink),
2525 std::make_tuple(StaticF, StaticF, ExpectNotLink),
2526 std::make_tuple(StaticF, AnonF, ExpectNotLink),
2527 std::make_tuple(AnonF, ExternF, ExpectNotLink),
2528 std::make_tuple(AnonF, StaticF, ExpectNotLink),
2529 std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
2530INSTANTIATE_TEST_CASE_P(
2531 ParameterizedTests, ImportVariablesVisibility,
2532 ::testing::Combine(
2533 DefaultTestValuesForRunOptions,
2534 ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
2535 std::make_tuple(ExternV, StaticV, ExpectNotLink),
2536 std::make_tuple(ExternV, AnonV, ExpectNotLink),
2537 std::make_tuple(StaticV, ExternV, ExpectNotLink),
2538 std::make_tuple(StaticV, StaticV, ExpectNotLink),
2539 std::make_tuple(StaticV, AnonV, ExpectNotLink),
2540 std::make_tuple(AnonV, ExternV, ExpectNotLink),
2541 std::make_tuple(AnonV, StaticV, ExpectNotLink),
2542 std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
2543
2544} // namespace TypeAndValueParameterizedTests
2545
2546TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2547 std::string Code = "static int v; static int v = 0;";
2548 auto Pattern = varDecl(hasName("v"));
2549
2550 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2551
2552 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2553 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2554
2555 auto *To0 = Import(From0, Lang_C);
2556 auto *To1 = Import(From1, Lang_C);
2557
2558 EXPECT_TRUE(To0);
2559 ASSERT_TRUE(To1);
2560 EXPECT_NE(To0, To1);
2561 EXPECT_EQ(To1->getPreviousDecl(), To0);
2562}
2563
2564TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2565 TranslationUnitDecl *FromTu = getTuDecl(
2566 "namespace NS0 { namespace { void f(); } }"
2567 "namespace NS1 { namespace { void f(); } }",
2568 Lang_CXX, "input0.cc");
2569 auto Pattern = functionDecl(hasName("f"));
2570
2571 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2572 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2573
2574 auto *ToF0 = Import(FromF0, Lang_CXX);
2575 auto *ToF1 = Import(FromF1, Lang_CXX);
2576
2577 EXPECT_TRUE(ToF0);
2578 ASSERT_TRUE(ToF1);
2579 EXPECT_NE(ToF0, ToF1);
2580 EXPECT_FALSE(ToF1->getPreviousDecl());
2581}
2582
2583TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2584 {
2585 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2586 Lang_CXX, "input0.cc");
2587 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2588 FromTU, functionDecl(hasName("g0")));
2589
2590 Import(FromD, Lang_CXX);
2591 }
2592 {
2593 Decl *FromTU =
2594 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2595 Lang_CXX, "input1.cc");
2596 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2597 FromTU, functionDecl(hasName("g1")));
2598 Import(FromD, Lang_CXX);
2599 }
2600
2601 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2602 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2603 2u);
2604}
2605
Gabor Marton302f3002019-02-15 12:04:05 +00002606TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2607 Decl *FromTU = getTuDecl(
2608 R"(
2609 void foo() {
2610 (void)[]() { ; };
2611 }
2612 )",
2613 Lang_CXX11);
2614 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2615 FromTU, functionDecl(hasName("foo")));
2616 auto *ToD = Import(FromD, Lang_CXX);
2617 EXPECT_TRUE(ToD);
2618 CXXRecordDecl *LambdaRec =
2619 cast<LambdaExpr>(cast<CStyleCastExpr>(
2620 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2621 ->getSubExpr())
2622 ->getLambdaClass();
2623 EXPECT_TRUE(LambdaRec->getDestructor());
2624}
2625
Gabor Marton5caba302019-03-07 13:38:20 +00002626TEST_P(ImportFunctions,
2627 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2628 Decl *FromTU = getTuDecl(
2629 R"(
2630 struct X {
2631 template <typename T>
2632 void foo(){}
2633 };
2634 void f() {
2635 X x;
2636 x.foo<int>();
2637 }
2638 )",
2639 Lang_CXX);
2640 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2641 FromTU, functionDecl(hasName("f")));
2642 auto *ToD = Import(FromD, Lang_CXX);
2643 EXPECT_TRUE(ToD);
2644 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2645 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2646}
2647
2648TEST_P(ImportFunctions,
2649 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2650 Decl *FromTU = getTuDecl(
2651 R"(
2652 struct X {
2653 template <typename T>
2654 void foo(){}
2655 };
2656 template <typename T>
2657 void f() {
2658 X x;
2659 x.foo<T>();
2660 }
2661 void g() {
2662 f<int>();
2663 }
2664 )",
2665 Lang_CXX);
2666 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2667 FromTU, functionDecl(hasName("g")));
2668 auto *ToD = Import(FromD, Lang_CXX);
2669 EXPECT_TRUE(ToD);
2670 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2671 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2672 ToTU, translationUnitDecl(hasDescendant(
2673 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2674}
2675
Gabor Marton5254e642018-06-27 13:32:50 +00002676struct ImportFriendFunctions : ImportFunctions {};
2677
2678TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2679 auto Pattern = functionDecl(hasName("f"));
2680
2681 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2682 "void f();",
2683 Lang_CXX,
2684 "input0.cc");
2685 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2686
2687 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2688 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2689 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2690 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2691 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2692 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2693 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2694}
2695
2696TEST_P(ImportFriendFunctions,
2697 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2698 auto Pattern = functionDecl(hasName("f"));
2699
2700 Decl *FromTU = getTuDecl("void f();"
2701 "struct X { friend void f(); };",
2702 Lang_CXX, "input0.cc");
2703 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2704
2705 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2706 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2707 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2708 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2709 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2710 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2711 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2712}
2713
2714TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2715 auto Pattern = functionDecl(hasName("f"));
2716
2717 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2718 "void f();",
2719 Lang_CXX,
2720 "input0.cc");
2721 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2722
2723 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2724 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2725 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2726 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2727 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2728 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2729 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2730}
2731
2732TEST_P(ImportFriendFunctions,
2733 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2734 auto Pattern = functionDecl(hasName("f"));
2735
2736 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2737 "void f(){}",
2738 Lang_CXX, "input0.cc");
2739 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2740
2741 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2742 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2743 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2744 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2745 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2746 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2747 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2748}
2749
Gabor Marton26f72a92018-07-12 09:42:05 +00002750// Disabled temporarily, because the new structural equivalence check
2751// (https://reviews.llvm.org/D48628) breaks it.
2752// PreviousDecl is not set because there is no structural match.
2753// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002754TEST_P(ImportFriendFunctions,
2755 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2756 auto Pattern = functionDecl(hasName("f"));
2757
2758 Decl *FromTU = getTuDecl(
2759 R"(
2760 class X;
2761 void f(X *x){}
2762 class X{
2763 friend void f(X *x);
2764 };
2765 )",
2766 Lang_CXX, "input0.cc");
2767 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2768
2769 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2770 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2771 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2772 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2773 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2774 .match(ToTU, friendDecl())
2775 ->getFriendDecl());
2776 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2777 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2778 // The parameters must refer the same type
2779 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2780 (*ImportedD->param_begin())->getOriginalType());
2781}
2782
Gabor Marton26f72a92018-07-12 09:42:05 +00002783// Disabled temporarily, because the new structural equivalence check
2784// (https://reviews.llvm.org/D48628) breaks it.
2785// PreviousDecl is not set because there is no structural match.
2786// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002787TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002788 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002789 auto Pattern = functionDecl(hasName("f"));
2790
2791 Decl *FromTU = getTuDecl(
2792 R"(
2793 class X;
2794 void f(X *x){}
2795 class X{
2796 friend void f(X *x);
2797 };
2798 )",
2799 Lang_CXX, "input0.cc");
2800 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2801
2802 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2803 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2804 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2805 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2806 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2807 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2808
2809 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2810 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2811 // The parameters must refer the same type
2812 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2813 (*ImportedD->param_begin())->getOriginalType());
2814}
2815
2816TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2817 auto Pattern = functionDecl(hasName("f"));
2818
2819 FunctionDecl *ImportedD;
2820 {
2821 Decl *FromTU =
2822 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2823 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2824 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2825 }
2826 FunctionDecl *ImportedD1;
2827 {
2828 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2829 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2830 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2831 }
2832
2833 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2834 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2835 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2836 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2837 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2838}
2839
Balazs Keri89632b82018-08-21 14:32:21 +00002840TEST_P(ImportFriendFunctions, Lookup) {
2841 auto FunctionPattern = functionDecl(hasName("f"));
2842 auto ClassPattern = cxxRecordDecl(hasName("X"));
2843
2844 TranslationUnitDecl *FromTU =
2845 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2846 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2847 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2848 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2849 {
2850 auto FromName = FromD->getDeclName();
2851 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2852 auto LookupRes = Class->noload_lookup(FromName);
2853 ASSERT_EQ(LookupRes.size(), 0u);
2854 LookupRes = FromTU->noload_lookup(FromName);
2855 ASSERT_EQ(LookupRes.size(), 1u);
2856 }
2857
2858 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2859 auto ToName = ToD->getDeclName();
2860
2861 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2862 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2863 auto LookupRes = Class->noload_lookup(ToName);
2864 EXPECT_EQ(LookupRes.size(), 0u);
2865 LookupRes = ToTU->noload_lookup(ToName);
2866 EXPECT_EQ(LookupRes.size(), 1u);
2867
2868 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2869 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2870 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2871 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2872}
2873
2874TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2875 auto FunctionPattern = functionDecl(hasName("f"));
2876 auto ClassPattern = cxxRecordDecl(hasName("X"));
2877
2878 TranslationUnitDecl *FromTU = getTuDecl(
2879 "struct X { friend void f(); };"
2880 // This proto decl makes f available to normal
2881 // lookup, otherwise it is hidden.
2882 // Normal C++ lookup (implemented in
2883 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2884 // returns the found `NamedDecl` only if the set IDNS is matched
2885 "void f();",
2886 Lang_CXX, "input0.cc");
2887 auto *FromFriend =
2888 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2889 auto *FromNormal =
2890 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2891 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2892 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2893 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2894 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2895
2896 auto FromName = FromFriend->getDeclName();
2897 auto *FromClass =
2898 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2899 auto LookupRes = FromClass->noload_lookup(FromName);
2900 ASSERT_EQ(LookupRes.size(), 0u);
2901 LookupRes = FromTU->noload_lookup(FromName);
2902 ASSERT_EQ(LookupRes.size(), 1u);
2903
2904 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2905 auto ToName = ToFriend->getDeclName();
2906
2907 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2908 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2909 LookupRes = ToClass->noload_lookup(ToName);
2910 EXPECT_EQ(LookupRes.size(), 0u);
2911 LookupRes = ToTU->noload_lookup(ToName);
2912 // Test is disabled because this result is 2.
2913 EXPECT_EQ(LookupRes.size(), 1u);
2914
2915 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2916 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2917 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2918 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2919 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2920 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2921 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2922}
2923
2924TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2925 auto FunctionPattern = functionDecl(hasName("f"));
2926 auto ClassPattern = cxxRecordDecl(hasName("X"));
2927
2928 TranslationUnitDecl *FromTU = getTuDecl(
2929 "void f();"
2930 "struct X { friend void f(); };",
2931 Lang_CXX, "input0.cc");
2932 auto *FromNormal =
2933 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2934 auto *FromFriend =
2935 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2936 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2937 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2938 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2939 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2940
2941 auto FromName = FromNormal->getDeclName();
2942 auto *FromClass =
2943 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2944 auto LookupRes = FromClass->noload_lookup(FromName);
2945 ASSERT_EQ(LookupRes.size(), 0u);
2946 LookupRes = FromTU->noload_lookup(FromName);
2947 ASSERT_EQ(LookupRes.size(), 1u);
2948
2949 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2950 auto ToName = ToNormal->getDeclName();
2951 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2952
2953 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2954 LookupRes = ToClass->noload_lookup(ToName);
2955 EXPECT_EQ(LookupRes.size(), 0u);
2956 LookupRes = ToTU->noload_lookup(ToName);
2957 EXPECT_EQ(LookupRes.size(), 1u);
2958
2959 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2960 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2961 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2962 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2963 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2964 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2965 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2966}
2967
2968TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2969 auto Pattern = functionDecl(hasName("f"));
2970
2971 TranslationUnitDecl *FromNormalTU =
2972 getTuDecl("void f();", Lang_CXX, "input0.cc");
2973 auto *FromNormalF =
2974 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2975 TranslationUnitDecl *FromFriendTU =
2976 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2977 auto *FromFriendF =
2978 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2979 auto FromNormalName = FromNormalF->getDeclName();
2980 auto FromFriendName = FromFriendF->getDeclName();
2981
2982 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2983 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2984 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2985 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2986 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2987 ASSERT_EQ(LookupRes.size(), 1u);
2988 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2989 ASSERT_EQ(LookupRes.size(), 1u);
2990
2991 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2992 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2993 auto ToName = ToNormalF->getDeclName();
2994 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2995 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2996 LookupRes = ToTU->noload_lookup(ToName);
2997 EXPECT_EQ(LookupRes.size(), 1u);
2998 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002999
Balazs Keri89632b82018-08-21 14:32:21 +00003000 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
3001 LookupRes = ToTU->noload_lookup(ToName);
3002 EXPECT_EQ(LookupRes.size(), 1u);
3003 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3004
3005 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3006 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3007
3008 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3009 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3010}
3011
3012TEST_P(ImportFriendFunctions, ImportFriendList) {
3013 TranslationUnitDecl *FromTU = getTuDecl(
3014 "struct X { friend void f(); };"
3015 "void f();",
3016 Lang_CXX, "input0.cc");
3017 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
3018 FromTU, functionDecl(hasName("f")));
3019
3020 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3021 FromTU, cxxRecordDecl(hasName("X")));
3022 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
3023 auto FromFriends = FromClass->friends();
3024 unsigned int FrN = 0;
3025 for (auto Fr : FromFriends) {
3026 ASSERT_EQ(Fr, FromFriend);
3027 ++FrN;
3028 }
3029 ASSERT_EQ(FrN, 1u);
3030
3031 Import(FromFriendF, Lang_CXX);
3032 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3033 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3034 ToTU, cxxRecordDecl(hasName("X")));
3035 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
3036 auto ToFriends = ToClass->friends();
3037 FrN = 0;
3038 for (auto Fr : ToFriends) {
3039 EXPECT_EQ(Fr, ToFriend);
3040 ++FrN;
3041 }
3042 EXPECT_EQ(FrN, 1u);
3043}
3044
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00003045AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
3046 InnerMatcher) {
3047 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
3048 return InnerMatcher.matches(*Typedef, Finder, Builder);
3049 return false;
3050}
3051
Gabor Marton19f4f392018-06-25 13:04:37 +00003052TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00003053 CodeFiles Samples{{"main.c",
3054 {"void foo();"
3055 "void moo();"
3056 "int main() { foo(); moo(); }",
3057 Lang_C}},
3058
3059 {"foo.c",
3060 {"typedef enum { THING_VALUE } thing_t;"
3061 "void conflict(thing_t type);"
3062 "void foo() { (void)THING_VALUE; }"
3063 "void conflict(thing_t type) {}",
3064 Lang_C}},
3065
3066 {"moo.c",
3067 {"typedef enum { THING_VALUE } thing_t;"
3068 "void conflict(thing_t type);"
3069 "void moo() { conflict(THING_VALUE); }",
3070 Lang_C}}};
3071
3072 auto VerificationMatcher =
3073 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
3074 hasTypedefForAnonDecl(hasName("thing_t")));
3075
3076 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
3077 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
3078
3079 testImportSequence(
3080 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
3081 // Just check that there is only one enum decl in the result AST.
3082 "main.c", enumDecl(), VerificationMatcher);
3083
3084 // For different import order, result should be the same.
3085 testImportSequence(
3086 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
3087 // Check that there is only one enum decl in the result AST.
3088 "main.c", enumDecl(), VerificationMatcher);
3089}
3090
Peter Szecsice7f3182018-05-07 12:08:27 +00003091const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
3092 dependentScopeDeclRefExpr;
3093
Gabor Marton19f4f392018-06-25 13:04:37 +00003094TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003095 MatchVerifier<Decl> Verifier;
3096 testImport("template <typename T> struct S { static T foo; };"
3097 "template <typename T> void declToImport() {"
3098 " (void) S<T>::foo;"
3099 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00003100 "void instantiate() { declToImport<int>(); }"
3101 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00003102 Lang_CXX11, "", Lang_CXX11, Verifier,
3103 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3104 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
3105
3106 testImport("template <typename T> struct S {"
3107 "template<typename S> static void foo(){};"
3108 "};"
3109 "template <typename T> void declToImport() {"
3110 " S<T>::template foo<T>();"
3111 "}"
3112 "void instantiate() { declToImport<int>(); }",
3113 Lang_CXX11, "", Lang_CXX11, Verifier,
3114 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3115 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
3116}
3117
3118const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
3119 dependentNameType;
3120
Gabor Marton19f4f392018-06-25 13:04:37 +00003121TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003122 MatchVerifier<Decl> Verifier;
3123 testImport("template <typename T> struct declToImport {"
3124 " typedef typename T::type dependent_name;"
3125 "};",
3126 Lang_CXX11, "", Lang_CXX11, Verifier,
3127 classTemplateDecl(has(
3128 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
3129}
3130
Gabor Marton19f4f392018-06-25 13:04:37 +00003131TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003132 MatchVerifier<Decl> Verifier;
3133 testImport("struct S { template <typename T> void mem(); };"
3134 "template <typename U> void declToImport() {"
3135 " S s;"
3136 " s.mem<U>();"
3137 "}"
3138 "void instantiate() { declToImport<int>(); }",
3139 Lang_CXX11, "", Lang_CXX11, Verifier,
3140 functionTemplateDecl(has(functionDecl(has(
3141 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3142}
3143
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003144class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00003145public:
3146 static constexpr auto DefaultCode = R"(
3147 struct A { int x; };
3148 void f() {
3149 A a;
3150 A a1(a);
3151 A a2(A{});
3152 a = a1;
3153 a = A{};
3154 a.~A();
3155 })";
3156
3157 template <typename MatcherType>
3158 void testImportOf(
3159 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3160 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3161 }
3162
3163 template <typename MatcherType>
3164 void testNoImportOf(
3165 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3166 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3167 }
3168
3169private:
3170 template <typename MatcherType>
3171 void test(const MatcherType &MethodMatcher,
3172 const char *Code, unsigned int ExpectedCount) {
3173 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3174
3175 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3176 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3177 ToTU, ClassMatcher);
3178
Balazs Keri2f752ba2018-07-16 14:05:18 +00003179 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003180
3181 {
3182 CXXMethodDecl *Method =
3183 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3184 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00003185 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003186 }
3187
Balazs Keri2f752ba2018-07-16 14:05:18 +00003188 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003189
3190 Decl *ImportedClass = nullptr;
3191 {
3192 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3193 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3194 FromTU, ClassMatcher);
3195 ImportedClass = Import(FromClass, Lang_CXX11);
3196 }
3197
3198 EXPECT_EQ(ToClass, ImportedClass);
3199 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3200 ExpectedCount);
3201 }
3202};
3203
3204TEST_P(ImportImplicitMethods, DefaultConstructor) {
3205 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3206}
3207
3208TEST_P(ImportImplicitMethods, CopyConstructor) {
3209 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3210}
3211
3212TEST_P(ImportImplicitMethods, MoveConstructor) {
3213 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3214}
3215
3216TEST_P(ImportImplicitMethods, Destructor) {
3217 testImportOf(cxxDestructorDecl());
3218}
3219
3220TEST_P(ImportImplicitMethods, CopyAssignment) {
3221 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3222}
3223
3224TEST_P(ImportImplicitMethods, MoveAssignment) {
3225 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3226}
3227
3228TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3229 auto Code = R"(
3230 struct A { A() { int x; } };
3231 )";
3232 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3233}
3234
3235TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3236 auto Code = R"(
3237 struct A { A() = default; };
3238 )";
3239 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3240}
3241
3242TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3243 auto Code = R"(
3244 struct A { A() = delete; };
3245 )";
3246 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3247}
3248
3249TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3250 auto Code = R"(
3251 struct A { void f() { } };
3252 )";
3253 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3254}
3255
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003256TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003257 Decl *ToR1;
3258 {
3259 Decl *FromTU = getTuDecl(
3260 "struct A { };", Lang_CXX, "input0.cc");
3261 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3262 FromTU, cxxRecordDecl(hasName("A")));
3263
3264 ToR1 = Import(FromR, Lang_CXX);
3265 }
3266
3267 Decl *ToR2;
3268 {
3269 Decl *FromTU = getTuDecl(
3270 "struct A { };", Lang_CXX, "input1.cc");
3271 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3272 FromTU, cxxRecordDecl(hasName("A")));
3273
3274 ToR2 = Import(FromR, Lang_CXX);
3275 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003276
Balazs Keric7797c42018-07-11 09:37:24 +00003277 EXPECT_EQ(ToR1, ToR2);
3278}
3279
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003280TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003281 Decl *ToR1;
3282 {
3283 Decl *FromTU = getTuDecl(
3284 "struct A { int x; };", Lang_CXX, "input0.cc");
3285 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3286 FromTU, cxxRecordDecl(hasName("A")));
3287 ToR1 = Import(FromR, Lang_CXX);
3288 }
3289 Decl *ToR2;
3290 {
3291 Decl *FromTU = getTuDecl(
3292 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3293 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3294 FromTU, cxxRecordDecl(hasName("A")));
3295 ToR2 = Import(FromR, Lang_CXX);
3296 }
3297 EXPECT_NE(ToR1, ToR2);
3298}
3299
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003300TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003301 Decl *ToF1;
3302 {
3303 Decl *FromTU = getTuDecl(
3304 "struct A { int x; };", Lang_CXX, "input0.cc");
3305 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3306 FromTU, fieldDecl(hasName("x")));
3307 ToF1 = Import(FromF, Lang_CXX);
3308 }
3309 Decl *ToF2;
3310 {
3311 Decl *FromTU = getTuDecl(
3312 "struct A { int x; };", Lang_CXX, "input1.cc");
3313 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3314 FromTU, fieldDecl(hasName("x")));
3315 ToF2 = Import(FromF, Lang_CXX);
3316 }
3317 EXPECT_EQ(ToF1, ToF2);
3318}
3319
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003320TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003321 Decl *ToF1;
3322 {
3323 Decl *FromTU = getTuDecl(
3324 "struct A { int x; };", Lang_CXX, "input0.cc");
3325 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3326 FromTU, fieldDecl(hasName("x")));
3327 ToF1 = Import(FromF, Lang_CXX);
3328 }
3329 Decl *ToF2;
3330 {
3331 Decl *FromTU = getTuDecl(
3332 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3333 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3334 FromTU, fieldDecl(hasName("x")));
3335 ToF2 = Import(FromF, Lang_CXX);
3336 }
3337 EXPECT_NE(ToF1, ToF2);
3338}
3339
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003340TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003341 Decl *ToM1;
3342 {
3343 Decl *FromTU = getTuDecl(
3344 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3345 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3346 FromTU, functionDecl(hasName("x"), isDefinition()));
3347 ToM1 = Import(FromM, Lang_CXX);
3348 }
3349 Decl *ToM2;
3350 {
3351 Decl *FromTU = getTuDecl(
3352 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3353 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3354 FromTU, functionDecl(hasName("x"), isDefinition()));
3355 ToM2 = Import(FromM, Lang_CXX);
3356 }
3357 EXPECT_EQ(ToM1, ToM2);
3358}
3359
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003360TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003361 Decl *ToM1;
3362 {
3363 Decl *FromTU = getTuDecl(
3364 "struct A { void x(); }; void A::x() { }",
3365 Lang_CXX, "input0.cc");
3366 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3367 FromTU, functionDecl(hasName("x"), isDefinition()));
3368 ToM1 = Import(FromM, Lang_CXX);
3369 }
3370 Decl *ToM2;
3371 {
3372 Decl *FromTU = getTuDecl(
3373 "struct A { void x() const; }; void A::x() const { }",
3374 Lang_CXX, "input1.cc");
3375 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3376 FromTU, functionDecl(hasName("x"), isDefinition()));
3377 ToM2 = Import(FromM, Lang_CXX);
3378 }
3379 EXPECT_NE(ToM1, ToM2);
3380}
3381
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003382TEST_P(ASTImporterOptionSpecificTestBase,
3383 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003384 Decl *FromTU = getTuDecl(
3385 R"(
3386 struct A {
3387 struct {
3388 struct A *next;
3389 } entry0;
3390 struct {
3391 struct A *next;
3392 } entry1;
3393 };
3394 )",
3395 Lang_C, "input0.cc");
3396 auto *From =
3397 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3398
3399 Import(From, Lang_C);
3400
3401 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3402 auto *Entry0 =
3403 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3404 auto *Entry1 =
3405 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3406 auto *R0 = getRecordDecl(Entry0);
3407 auto *R1 = getRecordDecl(Entry1);
3408 EXPECT_NE(R0, R1);
3409 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3410 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3411 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3412 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3413}
3414
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003415TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003416 Decl *FromTU = getTuDecl(
3417 R"(
3418 void f(int X, int Y, bool Z) {
3419 (void)[X, Y, Z] { (void)Z; };
3420 }
3421 )",
3422 Lang_CXX11, "input0.cc");
3423 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3424 FromTU, functionDecl(hasName("f")));
3425 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3426 EXPECT_TRUE(ToF);
3427
3428 CXXRecordDecl *FromLambda =
3429 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3430 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3431
3432 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3433 EXPECT_TRUE(ToLambda);
3434
3435 // Check if the fields of the lambda class are imported in correct order.
3436 unsigned FromIndex = 0u;
3437 for (auto *FromField : FromLambda->fields()) {
3438 ASSERT_FALSE(FromField->getDeclName());
3439 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3440 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003441 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3442 EXPECT_TRUE(ToIndex);
3443 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003444 ++FromIndex;
3445 }
3446
3447 EXPECT_EQ(FromIndex, 3u);
3448}
3449
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003450TEST_P(ASTImporterOptionSpecificTestBase,
3451 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003452 std::string ClassTemplate =
3453 R"(
3454 template <typename T>
3455 struct X {
3456 int a{0}; // FieldDecl with InitListExpr
3457 X(char) : a(3) {} // (1)
3458 X(int) {} // (2)
3459 };
3460 )";
3461 Decl *ToTU = getToTuDecl(ClassTemplate +
3462 R"(
3463 void foo() {
3464 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3465 X<char> xc('c');
3466 }
3467 )", Lang_CXX11);
3468 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3469 ToTU, classTemplateSpecializationDecl(hasName("X")));
3470 // FieldDecl without InitlistExpr:
3471 auto *ToField = *ToSpec->field_begin();
3472 ASSERT_TRUE(ToField);
3473 ASSERT_FALSE(ToField->getInClassInitializer());
3474 Decl *FromTU = getTuDecl(ClassTemplate +
3475 R"(
3476 void bar() {
3477 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3478 X<char> xc(1);
3479 }
3480 )", Lang_CXX11);
3481 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3482 FromTU, classTemplateSpecializationDecl(hasName("X")));
3483 // FieldDecl with InitlistExpr:
3484 auto *FromField = *FromSpec->field_begin();
3485 ASSERT_TRUE(FromField);
3486 ASSERT_TRUE(FromField->getInClassInitializer());
3487
3488 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3489 ASSERT_TRUE(ImportedSpec);
3490 EXPECT_EQ(ImportedSpec, ToSpec);
3491 // After the import, the FieldDecl has to be merged, thus it should have the
3492 // InitListExpr.
3493 EXPECT_TRUE(ToField->getInClassInitializer());
3494}
3495
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003496TEST_P(ASTImporterOptionSpecificTestBase,
3497 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003498 std::string ClassTemplate =
3499 R"(
3500 template <typename T>
3501 struct X {
3502 void f() {}
3503 void g() {}
3504 };
3505 )";
3506 Decl *ToTU = getToTuDecl(ClassTemplate +
3507 R"(
3508 void foo() {
3509 X<char> x;
3510 x.f();
3511 }
3512 )", Lang_CXX11);
3513 Decl *FromTU = getTuDecl(ClassTemplate +
3514 R"(
3515 void bar() {
3516 X<char> x;
3517 x.g();
3518 }
3519 )", Lang_CXX11);
3520 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3521 FromTU, classTemplateSpecializationDecl(hasName("X")));
3522 auto FunPattern = functionDecl(hasName("g"),
3523 hasParent(classTemplateSpecializationDecl()));
3524 auto *FromFun =
3525 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3526 auto *ToFun =
3527 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3528 ASSERT_TRUE(FromFun->hasBody());
3529 ASSERT_FALSE(ToFun->hasBody());
3530 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3531 ASSERT_TRUE(ImportedSpec);
3532 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3533 ToTU, classTemplateSpecializationDecl(hasName("X")));
3534 EXPECT_EQ(ImportedSpec, ToSpec);
3535 EXPECT_TRUE(ToFun->hasBody());
3536}
3537
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003538TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003539 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3540 std::string ClassTemplate =
3541 R"(
3542 template <typename T>
3543 struct X {};
3544 )";
3545 Decl *ToTU = getToTuDecl(ClassTemplate +
3546 R"(
3547 template <>
3548 struct X<char> {
3549 int a;
3550 };
3551 void foo() {
3552 X<char> x;
3553 }
3554 )",
3555 Lang_CXX11);
3556 Decl *FromTU = getTuDecl(ClassTemplate +
3557 R"(
3558 template <>
3559 struct X<char> {
3560 int b;
3561 };
3562 void foo() {
3563 X<char> x;
3564 }
3565 )",
3566 Lang_CXX11);
3567 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3568 FromTU, classTemplateSpecializationDecl(hasName("X")));
3569 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3570
3571 // We expect one (ODR) warning during the import.
3572 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3573
3574 // The second specialization is different from the first, thus it violates
3575 // ODR, consequently we expect to keep the first specialization only, which is
3576 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003577 EXPECT_FALSE(ImportedSpec);
3578 EXPECT_EQ(1u,
3579 DeclCounter<ClassTemplateSpecializationDecl>().match(
3580 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003581}
3582
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003583TEST_P(ASTImporterOptionSpecificTestBase,
3584 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003585 std::string ClassTemplate =
3586 R"(
3587 template <typename T>
3588 struct X {
3589 X(char) {}
3590 X(int) {}
3591 };
3592 )";
3593 Decl *ToTU = getToTuDecl(ClassTemplate +
3594 R"(
3595 void foo() {
3596 X<char> x('c');
3597 }
3598 )", Lang_CXX11);
3599 Decl *FromTU = getTuDecl(ClassTemplate +
3600 R"(
3601 void bar() {
3602 X<char> x(1);
3603 }
3604 )", Lang_CXX11);
3605 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3606 FromTU, classTemplateSpecializationDecl(hasName("X")));
3607 // Match the void(int) ctor.
3608 auto CtorPattern =
3609 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3610 hasParent(classTemplateSpecializationDecl()));
3611 auto *FromCtor =
3612 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3613 auto *ToCtor =
3614 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3615 ASSERT_TRUE(FromCtor->hasBody());
3616 ASSERT_FALSE(ToCtor->hasBody());
3617 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3618 ASSERT_TRUE(ImportedSpec);
3619 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3620 ToTU, classTemplateSpecializationDecl(hasName("X")));
3621 EXPECT_EQ(ImportedSpec, ToSpec);
3622 EXPECT_TRUE(ToCtor->hasBody());
3623}
3624
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003625TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003626 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3627 auto Code =
3628 R"(
3629 // primary template
3630 template<class T1, class T2, int I>
3631 class A {};
3632
3633 // partial specialization
3634 template<class T, int I>
3635 class A<T, T*, I> {};
3636 )";
3637 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3638 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3639 auto *FromSpec =
3640 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3641 FromTU, classTemplatePartialSpecializationDecl());
3642 auto *ToSpec =
3643 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3644 ToTU, classTemplatePartialSpecializationDecl());
3645
3646 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3647 EXPECT_EQ(ImportedSpec, ToSpec);
3648 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3649 ToTU, classTemplatePartialSpecializationDecl()));
3650}
3651
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003652TEST_P(ASTImporterOptionSpecificTestBase,
3653 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003654 auto Code =
3655 R"(
3656 // primary template
3657 template<class T1, class T2, int I>
3658 class A {};
3659
3660 // full specialization
3661 template<>
3662 class A<int, int, 1> {};
3663 )";
3664 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3665 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3666 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3667 FromTU, classTemplateSpecializationDecl());
3668 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3669 ToTU, classTemplateSpecializationDecl());
3670
3671 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3672 EXPECT_EQ(ImportedSpec, ToSpec);
3673 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3674 ToTU, classTemplateSpecializationDecl()));
3675}
3676
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003677TEST_P(ASTImporterOptionSpecificTestBase,
3678 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003679 std::string PrimaryTemplate =
3680 R"(
3681 template<class T1, class T2, int I>
3682 class A {};
3683 )";
3684 auto PartialSpec =
3685 R"(
3686 template<class T, int I>
3687 class A<T, T*, I> {};
3688 )";
3689 auto FullSpec =
3690 R"(
3691 template<>
3692 class A<int, int, 1> {};
3693 )";
3694 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3695 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3696 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3697 FromTU, classTemplateSpecializationDecl());
3698
3699 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3700 EXPECT_TRUE(ImportedSpec);
3701 // Check the number of partial specializations.
3702 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3703 ToTU, classTemplatePartialSpecializationDecl()));
3704 // Check the number of full specializations.
3705 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3706 ToTU, classTemplateSpecializationDecl(
3707 unless(classTemplatePartialSpecializationDecl()))));
3708}
3709
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003710TEST_P(ASTImporterOptionSpecificTestBase,
3711 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003712 Decl *TU = getTuDecl(
3713 R"(
3714 const int &init();
3715 void foo() { const int &a{init()}; }
3716 )", Lang_CXX11, "input0.cc");
3717 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3718 ASSERT_TRUE(FromD->getAnyInitializer());
3719 auto *InitExpr = FromD->getAnyInitializer();
3720 ASSERT_TRUE(InitExpr);
3721 ASSERT_TRUE(InitExpr->isGLValue());
3722
3723 auto *ToD = Import(FromD, Lang_CXX11);
3724 EXPECT_TRUE(ToD);
3725 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3726 EXPECT_TRUE(ToInitExpr);
3727 EXPECT_TRUE(ToInitExpr->isGLValue());
3728}
3729
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003730struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003731
3732TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3733 Decl *FromTU = getTuDecl(
3734 R"(
3735 struct A {
3736 static const int a = 1 + 2;
3737 };
3738 const int A::a;
3739 )", Lang_CXX, "input1.cc");
3740
3741 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3742 FromTU, varDecl(hasName("a"))); // Decl with init
3743 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3744 FromTU, varDecl(hasName("a"))); // Decl with definition
3745 ASSERT_NE(FromDWithInit, FromDWithDef);
3746 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3747
3748 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3749 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3750 ASSERT_TRUE(ToD0);
3751 ASSERT_TRUE(ToD1);
3752 EXPECT_NE(ToD0, ToD1);
3753 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3754}
3755
3756TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3757 auto StructA =
3758 R"(
3759 struct A {
3760 static const int a = 1 + 2;
3761 };
3762 )";
3763 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3764 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3765 "input1.cc");
3766
3767 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3768 FromTU, varDecl(hasName("a"))); // Decl with init
3769 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3770 FromTU, varDecl(hasName("a"))); // Decl with definition
3771 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3772 ASSERT_TRUE(FromDWithInit->getInit());
3773 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3774 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3775 ASSERT_FALSE(FromDWithDef->getInit());
3776
3777 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3778 ToTU, varDecl(hasName("a"))); // Decl with init
3779 ASSERT_TRUE(ToD->getInit());
3780 ASSERT_FALSE(ToD->getDefinition());
3781
3782 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3783 EXPECT_TRUE(ImportedD->getAnyInitializer());
3784 EXPECT_TRUE(ImportedD->getDefinition());
3785}
3786
3787TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3788 auto StructA =
3789 R"(
3790 struct A {
3791 static const int a;
3792 };
3793 )";
3794 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3795 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3796 Lang_CXX, "input1.cc");
3797
3798 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3799 FromTU, varDecl(hasName("a")));
3800 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3801 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3802 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3803 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3804 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3805 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3806 ASSERT_TRUE(FromDWithDef->getInit());
3807
3808 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3809 ToTU, varDecl(hasName("a")));
3810 ASSERT_FALSE(ToD->getInit());
3811 ASSERT_FALSE(ToD->getDefinition());
3812
3813 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3814 EXPECT_TRUE(ImportedD->getAnyInitializer());
3815 EXPECT_TRUE(ImportedD->getDefinition());
3816}
3817
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003818struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003819
Gabor Marton54058b52018-12-17 13:53:12 +00003820TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3821 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3822 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3823 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3824 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3825 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3826
3827 Decl *ImportedDef = Import(FromDef, Lang_C);
3828
3829 EXPECT_NE(ImportedDef, ToProto);
3830 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3831 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3832 EXPECT_TRUE(ImportedDef == ToDef);
3833 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3834 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3835 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3836}
3837
3838TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3839 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3840 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3841 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3842 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3843 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3844
3845 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3846
3847 EXPECT_NE(ImportedDef, ToProto);
3848 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3849 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3850 EXPECT_TRUE(ImportedDef == ToDef);
3851 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3852 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3853 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3854}
3855
3856TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3857 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3858 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3859 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3860 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3861 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3862
3863 Decl *ImportedProto = Import(FromProto, Lang_C);
3864 Decl *ImportedDef = Import(FromDef, Lang_C);
3865 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3866
3867 EXPECT_NE(ImportedDef, ImportedProto);
3868 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3869 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3870 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3871 EXPECT_TRUE(ImportedDef == ToDef);
3872 EXPECT_TRUE(ImportedProto == ToProto);
3873 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3874 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3875 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3876}
3877
Gabor Martonfc03fc62019-02-18 11:09:56 +00003878// FIXME put these structs and the tests rely on them into their own separate
3879// test file!
3880struct Function {
3881 using DeclTy = FunctionDecl;
3882 static constexpr auto *Prototype = "void X();";
3883 static constexpr auto *Definition = "void X() {}";
3884 BindableMatcher<Decl> getPattern() {
3885 return functionDecl(hasName("X"), unless(isImplicit()));
3886 }
3887};
Gabor Marton7df342a2018-12-17 12:42:12 +00003888
Gabor Martonfc03fc62019-02-18 11:09:56 +00003889struct Class {
3890 using DeclTy = CXXRecordDecl;
3891 static constexpr auto *Prototype = "class X;";
3892 static constexpr auto *Definition = "class X {};";
3893 BindableMatcher<Decl> getPattern() {
3894 return cxxRecordDecl(hasName("X"), unless(isImplicit()));
3895 }
3896};
Gabor Marton7df342a2018-12-17 12:42:12 +00003897
Gabor Martonfc03fc62019-02-18 11:09:56 +00003898struct Variable {
3899 using DeclTy = VarDecl;
3900 static constexpr auto *Prototype = "extern int X;";
3901 static constexpr auto *Definition = "int X;";
3902 BindableMatcher<Decl> getPattern() {
3903 return varDecl(hasName("X"));
3904 }
3905};
Gabor Marton7df342a2018-12-17 12:42:12 +00003906
Gabor Martonfc03fc62019-02-18 11:09:56 +00003907struct FunctionTemplate {
3908 using DeclTy = FunctionTemplateDecl;
3909 static constexpr auto *Prototype = "template <class T> void X();";
3910 static constexpr auto *Definition =
3911 R"(
3912 template <class T> void X() {};
3913 // Explicit instantiation is a must because of -fdelayed-template-parsing:
3914 template void X<int>();
3915 )";
3916 BindableMatcher<Decl> getPattern() {
3917 return functionTemplateDecl(hasName("X"), unless(isImplicit()));
3918 }
3919};
Gabor Marton7df342a2018-12-17 12:42:12 +00003920
Gabor Martonfc03fc62019-02-18 11:09:56 +00003921struct ClassTemplate {
3922 using DeclTy = ClassTemplateDecl;
3923 static constexpr auto *Prototype = "template <class T> class X;";
3924 static constexpr auto *Definition = "template <class T> class X {};";
3925 BindableMatcher<Decl> getPattern() {
3926 return classTemplateDecl(hasName("X"), unless(isImplicit()));
3927 }
3928};
Gabor Marton7df342a2018-12-17 12:42:12 +00003929
Gabor Martonfc03fc62019-02-18 11:09:56 +00003930struct FunctionTemplateSpec {
3931 using DeclTy = FunctionDecl;
3932 static constexpr auto *Prototype =
3933 R"(
3934 // Proto of the primary template.
3935 template <class T>
3936 void X();
3937 // Proto of the specialization.
3938 template <>
3939 void X<int>();
3940 )";
3941 static constexpr auto *Definition =
3942 R"(
3943 // Proto of the primary template.
3944 template <class T>
3945 void X();
3946 // Specialization and definition.
3947 template <>
3948 void X<int>() {}
3949 )";
3950 BindableMatcher<Decl> getPattern() {
3951 return functionDecl(hasName("X"), isExplicitTemplateSpecialization());
3952 }
3953};
Gabor Marton7df342a2018-12-17 12:42:12 +00003954
Gabor Marton7f8c4002019-03-19 13:34:10 +00003955struct ClassTemplateSpec {
3956 using DeclTy = ClassTemplateSpecializationDecl;
3957 static constexpr auto *Prototype =
3958 R"(
3959 template <class T> class X;
3960 template <> class X<int>;
3961 )";
3962 static constexpr auto *Definition =
3963 R"(
3964 template <class T> class X;
3965 template <> class X<int> {};
3966 )";
3967 BindableMatcher<Decl> getPattern() {
3968 return classTemplateSpecializationDecl(hasName("X"), unless(isImplicit()));
3969 }
3970};
3971
Gabor Martonfc03fc62019-02-18 11:09:56 +00003972template <typename TypeParam>
3973struct RedeclChain : ASTImporterOptionSpecificTestBase {
Gabor Marton7df342a2018-12-17 12:42:12 +00003974
Gabor Martonfc03fc62019-02-18 11:09:56 +00003975 using DeclTy = typename TypeParam::DeclTy;
3976 std::string getPrototype() { return TypeParam::Prototype; }
3977 std::string getDefinition() { return TypeParam::Definition; }
3978 BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); }
Gabor Marton7df342a2018-12-17 12:42:12 +00003979
Gabor Martondd59d272019-03-19 14:04:50 +00003980 void CheckPreviousDecl(Decl *Prev, Decl *Current) {
3981 ASSERT_NE(Prev, Current);
3982 ASSERT_EQ(&Prev->getASTContext(), &Current->getASTContext());
3983 EXPECT_EQ(Prev->getCanonicalDecl(), Current->getCanonicalDecl());
3984
3985 // Templates.
3986 if (auto *PrevT = dyn_cast<TemplateDecl>(Prev)) {
3987 EXPECT_EQ(Current->getPreviousDecl(), Prev);
3988 auto *CurrentT = cast<TemplateDecl>(Current);
3989 ASSERT_TRUE(PrevT->getTemplatedDecl());
3990 ASSERT_TRUE(CurrentT->getTemplatedDecl());
3991 EXPECT_EQ(CurrentT->getTemplatedDecl()->getPreviousDecl(),
3992 PrevT->getTemplatedDecl());
3993 return;
3994 }
3995
3996 // Specializations.
3997 if (auto *PrevF = dyn_cast<FunctionDecl>(Prev)) {
3998 if (PrevF->getTemplatedKind() ==
3999 FunctionDecl::TK_FunctionTemplateSpecialization) {
4000 // There may be a hidden fwd spec decl before a spec decl.
4001 // In that case the previous visible decl can be reached through that
4002 // invisible one.
4003 EXPECT_THAT(Prev, testing::AnyOf(
4004 Current->getPreviousDecl(),
4005 Current->getPreviousDecl()->getPreviousDecl()));
4006 auto *ToTU = Prev->getTranslationUnitDecl();
4007 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4008 ToTU, functionTemplateDecl());
4009 auto *FirstSpecD = *(TemplateD->spec_begin());
4010 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), PrevF->getCanonicalDecl());
4011 return;
4012 }
4013 }
4014
4015 // The rest: Classes, Functions, etc.
4016 EXPECT_EQ(Current->getPreviousDecl(), Prev);
4017 }
4018
Gabor Martonfc03fc62019-02-18 11:09:56 +00004019 void
4020 TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() {
4021 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX);
4022 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4023 ASSERT_FALSE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004024
Gabor Martonfc03fc62019-02-18 11:09:56 +00004025 Decl *ImportedD = Import(FromD, Lang_CXX);
4026 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004027
Gabor Martonfc03fc62019-02-18 11:09:56 +00004028 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4029 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4030 EXPECT_TRUE(ImportedD == ToD);
4031 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
4032 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
4033 EXPECT_TRUE(ToT->getTemplatedDecl());
4034 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004035
Gabor Martonfc03fc62019-02-18 11:09:56 +00004036 void TypedTest_DefinitionShouldBeImportedAsADefinition() {
4037 Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
4038 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4039 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004040
Gabor Martonfc03fc62019-02-18 11:09:56 +00004041 Decl *ImportedD = Import(FromD, Lang_CXX);
4042 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004043
Gabor Martonfc03fc62019-02-18 11:09:56 +00004044 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4045 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4046 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
4047 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
4048 EXPECT_TRUE(ToT->getTemplatedDecl());
4049 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004050
Gabor Martonfc03fc62019-02-18 11:09:56 +00004051 void TypedTest_ImportPrototypeAfterImportedPrototype() {
4052 Decl *FromTU = getTuDecl(
4053 getPrototype() + getPrototype(), Lang_CXX);
4054 auto *From0 =
4055 FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4056 auto *From1 = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4057 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4058 ASSERT_FALSE(From1->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004059
Gabor Martonfc03fc62019-02-18 11:09:56 +00004060 Decl *Imported0 = Import(From0, Lang_CXX);
4061 Decl *Imported1 = Import(From1, Lang_CXX);
4062 Decl *ToTU = Imported0->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004063
Gabor Martonfc03fc62019-02-18 11:09:56 +00004064 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4065 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4066 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4067 EXPECT_TRUE(Imported0 == To0);
4068 EXPECT_TRUE(Imported1 == To1);
4069 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4070 EXPECT_FALSE(To1->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004071
4072 CheckPreviousDecl(To0, To1);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004073 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004074
Gabor Martonfc03fc62019-02-18 11:09:56 +00004075 void TypedTest_ImportDefinitionAfterImportedPrototype() {
4076 Decl *FromTU = getTuDecl(
4077 getPrototype() + getDefinition(), Lang_CXX);
4078 auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4079 auto *FromDef = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4080 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4081 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004082
Gabor Martonfc03fc62019-02-18 11:09:56 +00004083 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4084 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4085 Decl *ToTU = ImportedProto->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00004086
Gabor Martonfc03fc62019-02-18 11:09:56 +00004087 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4088 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4089 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4090 EXPECT_TRUE(ImportedProto == ToProto);
4091 EXPECT_TRUE(ImportedDef == ToDef);
4092 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4093 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004094
4095 CheckPreviousDecl(ToProto, ToDef);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004096 }
Gabor Marton7df342a2018-12-17 12:42:12 +00004097
Gabor Martonfc03fc62019-02-18 11:09:56 +00004098 void TypedTest_ImportPrototypeAfterImportedDefinition() {
4099 Decl *FromTU = getTuDecl(
4100 getDefinition() + getPrototype(), Lang_CXX);
4101 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4102 auto *FromProto = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4103 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4104 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00004105
Gabor Martonfc03fc62019-02-18 11:09:56 +00004106 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4107 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4108 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4109
4110 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4111 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4112 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4113 EXPECT_TRUE(ImportedDef == ToDef);
4114 EXPECT_TRUE(ImportedProto == ToProto);
4115 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4116 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004117
4118 CheckPreviousDecl(ToDef, ToProto);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004119 }
4120
4121 void TypedTest_ImportPrototypes() {
4122 Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4123 Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4124 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4125 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4126 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4127 ASSERT_FALSE(From1->isThisDeclarationADefinition());
4128
4129 Decl *Imported0 = Import(From0, Lang_CXX);
4130 Decl *Imported1 = Import(From1, Lang_CXX);
4131 Decl *ToTU = Imported0->getTranslationUnitDecl();
4132
4133 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4134 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4135 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4136 EXPECT_TRUE(Imported0 == To0);
4137 EXPECT_TRUE(Imported1 == To1);
4138 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4139 EXPECT_FALSE(To1->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004140
4141 CheckPreviousDecl(To0, To1);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004142 }
4143
4144 void TypedTest_ImportDefinitions() {
4145 Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4146 Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4147 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4148 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4149 ASSERT_TRUE(From0->isThisDeclarationADefinition());
4150 ASSERT_TRUE(From1->isThisDeclarationADefinition());
4151
4152 Decl *Imported0 = Import(From0, Lang_CXX);
4153 Decl *Imported1 = Import(From1, Lang_CXX);
4154 Decl *ToTU = Imported0->getTranslationUnitDecl();
4155
4156 EXPECT_EQ(Imported0, Imported1);
4157 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4158 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4159 EXPECT_TRUE(Imported0 == To0);
4160 EXPECT_TRUE(To0->isThisDeclarationADefinition());
4161 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0))
4162 EXPECT_TRUE(ToT0->getTemplatedDecl());
4163 }
4164
4165 void TypedTest_ImportDefinitionThenPrototype() {
4166 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4167 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4168 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4169 auto *FromProto =
4170 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4171 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4172 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4173
4174 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4175 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4176 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4177
4178 EXPECT_NE(ImportedDef, ImportedProto);
4179 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4180 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4181 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4182 EXPECT_TRUE(ImportedDef == ToDef);
4183 EXPECT_TRUE(ImportedProto == ToProto);
4184 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4185 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004186
4187 CheckPreviousDecl(ToDef, ToProto);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004188 }
4189
4190 void TypedTest_ImportPrototypeThenDefinition() {
4191 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4192 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4193 auto *FromProto =
4194 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4195 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4196 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4197 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4198
4199 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4200 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4201 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4202
4203 EXPECT_NE(ImportedDef, ImportedProto);
4204 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4205 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4206 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4207 EXPECT_TRUE(ImportedDef == ToDef);
4208 EXPECT_TRUE(ImportedProto == ToProto);
4209 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4210 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004211
4212 CheckPreviousDecl(ToProto, ToDef);
Gabor Martonfc03fc62019-02-18 11:09:56 +00004213 }
4214
4215 void TypedTest_WholeRedeclChainIsImportedAtOnce() {
4216 Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
4217 auto *FromD = // Definition
4218 LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4219 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
4220
4221 Decl *ImportedD = Import(FromD, Lang_CXX);
4222 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4223
4224 // The whole redecl chain is imported at once.
4225 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4226 EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition());
4227 }
4228
4229 void TypedTest_ImportPrototypeThenProtoAndDefinition() {
4230 {
4231 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4232 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4233 Import(FromD, Lang_CXX);
4234 }
4235 {
4236 Decl *FromTU =
4237 getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc");
4238 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4239 Import(FromD, Lang_CXX);
4240 }
4241
4242 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4243
4244 ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u);
4245 DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4246 EXPECT_FALSE(ProtoD->isThisDeclarationADefinition());
4247
4248 DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4249 EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition());
4250
4251 EXPECT_TRUE(DefinitionD->getPreviousDecl());
4252 EXPECT_FALSE(
4253 DefinitionD->getPreviousDecl()->isThisDeclarationADefinition());
Gabor Martondd59d272019-03-19 14:04:50 +00004254
4255 CheckPreviousDecl(ProtoD, DefinitionD->getPreviousDecl());
Gabor Martonfc03fc62019-02-18 11:09:56 +00004256 }
4257};
4258
4259#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \
4260 NamePrefix, TestCase) \
4261 using BaseTemplate##TypeParam = BaseTemplate<TypeParam>; \
4262 TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \
4263 TypedTest_##TestCase(); \
4264 }
4265
4266ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4267 RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004268 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004269ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4270 RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004271 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004272ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4273 RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004274 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004275ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004276 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004277 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004278ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4279 RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004280 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004281ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4282 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004283 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004284ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4285 RedeclChain, ClassTemplateSpec, ,
4286 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004287
4288ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004289 RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004290ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004291 RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004292ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004293 RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004294ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004295 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004296 DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004297ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004298 RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004299ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4300 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004301 DefinitionShouldBeImportedAsADefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004302ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4303 RedeclChain, ClassTemplateSpec, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004304
4305ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004306 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004307ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004308 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004309ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004310 ImportPrototypeAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004311ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004312 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004313ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004314 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004315ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004316 ImportPrototypeAfterImportedPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004317ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4318 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004319
4320ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004321 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004322ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004323 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004324ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004325 ImportDefinitionAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004326ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004327 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004328ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004329 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004330ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004331 ImportDefinitionAfterImportedPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004332ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4333 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004334
4335ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004336 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004337ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004338 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004339ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004340 ImportPrototypeAfterImportedDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004341ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004342 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004343ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004344 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004345ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004346 ImportPrototypeAfterImportedDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004347ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4348 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004349
4350ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004351 ImportPrototypes)
Gabor Marton038100a2019-02-20 16:57:41 +00004352ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004353ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004354 ImportPrototypes)
Gabor Marton16d98c22019-03-07 13:01:51 +00004355ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4356 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004357ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004358 ImportPrototypes)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004359ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4360 ImportPrototypes)
Gabor Martondd59d272019-03-19 14:04:50 +00004361ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4362 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004363
4364ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004365 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004366ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004367 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004368ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004369 ImportDefinitions)
Gabor Marton16d98c22019-03-07 13:01:51 +00004370ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4371 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004372ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004373 ImportDefinitions)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004374ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4375 ImportDefinitions)
Gabor Martondd59d272019-03-19 14:04:50 +00004376ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4377 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004378
4379ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004380 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004381ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004382 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004383ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004384 ImportDefinitionThenPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004385ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004386 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004387ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004388 ImportDefinitionThenPrototype)
Gabor Martondd59d272019-03-19 14:04:50 +00004389ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004390 ImportDefinitionThenPrototype)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004391ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4392 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004393
4394ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004395 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004396ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004397 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004398ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004399 ImportPrototypeThenDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004400ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004401 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004402ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004403 ImportPrototypeThenDefinition)
Gabor Martondd59d272019-03-19 14:04:50 +00004404ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004405 ImportPrototypeThenDefinition)
Gabor Marton7f8c4002019-03-19 13:34:10 +00004406ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
4407 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004408
4409ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004410 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004411ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004412 WholeRedeclChainIsImportedAtOnce)
Gabor Marton16d98c22019-03-07 13:01:51 +00004413ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004414 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004415ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004416 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004417
4418ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004419 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004420ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004421 ImportPrototypeThenProtoAndDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004422ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004423 ImportPrototypeThenProtoAndDefinition)
Gabor Martondd59d272019-03-19 14:04:50 +00004424ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004425 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004426
4427INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction,
4428 DefaultTestValuesForRunOptions, );
4429INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass,
4430 DefaultTestValuesForRunOptions, );
4431INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable,
4432 DefaultTestValuesForRunOptions, );
4433INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
4434 DefaultTestValuesForRunOptions, );
4435INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
4436 DefaultTestValuesForRunOptions, );
4437INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
4438 DefaultTestValuesForRunOptions, );
Gabor Marton7f8c4002019-03-19 13:34:10 +00004439INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplateSpec,
4440 DefaultTestValuesForRunOptions, );
Gabor Martonfc03fc62019-02-18 11:09:56 +00004441
4442
Gabor Marton7df342a2018-12-17 12:42:12 +00004443
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004444struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00004445
4446TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4447 Decl *FromTU = getTuDecl(
4448 R"(
4449 class A {
4450 template <int I> class F {};
4451 class X {
4452 template <int I> friend class F;
4453 };
4454 };
4455 )",
4456 Lang_CXX, "input0.cc");
4457
4458 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4459 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4460 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4461 FromTU, cxxRecordDecl(hasName("F")));
4462
4463 ASSERT_TRUE(FromClass);
4464 ASSERT_TRUE(FromFriendClass);
4465 ASSERT_NE(FromClass, FromFriendClass);
4466 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4467 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4468 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4469 FromClass->getDescribedClassTemplate());
4470
4471 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
4472 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
4473
4474 EXPECT_TRUE(ToClass);
4475 EXPECT_TRUE(ToFriendClass);
4476 EXPECT_NE(ToClass, ToFriendClass);
4477 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4478 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4479 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4480 ToClass->getDescribedClassTemplate());
4481}
4482
4483TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4484 Decl *FromTu = getTuDecl(
4485 R"(
4486 class declToImport {
4487 friend class declToImport;
4488 };
4489 )",
4490 Lang_CXX, "input.cc");
4491
4492 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4493 FromTu, cxxRecordDecl(hasName("declToImport")));
4494 auto *ToD = Import(FromD, Lang_CXX);
4495 auto Pattern = cxxRecordDecl(has(friendDecl()));
4496 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4497 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4498}
4499
4500TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4501 Decl *FromTu = getTuDecl(
4502 R"(
4503 template<class A> class declToImport {
4504 template<class A1> friend class declToImport;
4505 };
4506 )",
4507 Lang_CXX, "input.cc");
4508
4509 auto *FromD =
4510 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
4511 auto *ToD = Import(FromD, Lang_CXX);
4512
4513 auto Pattern = classTemplateDecl(
4514 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4515 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4516 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4517
4518 auto *Class =
4519 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
4520 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4521 EXPECT_NE(Friend->getFriendDecl(), Class);
4522 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
4523}
4524
4525TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4526 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
4527
4528 ClassTemplateSpecializationDecl *Imported1;
4529 {
4530 Decl *FromTU = getTuDecl("template<class T> class X;"
4531 "struct Y { friend class X<int>; };",
4532 Lang_CXX, "input0.cc");
4533 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4534 FromTU, Pattern);
4535
4536 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4537 }
4538 ClassTemplateSpecializationDecl *Imported2;
4539 {
4540 Decl *FromTU = getTuDecl("template<class T> class X;"
4541 "template<> class X<int>{};"
4542 "struct Z { friend class X<int>; };",
4543 Lang_CXX, "input1.cc");
4544 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4545 FromTU, Pattern);
4546
4547 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4548 }
4549
4550 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4551 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4552 2u);
4553 ASSERT_TRUE(Imported2->getPreviousDecl());
4554 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4555}
4556
4557TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4558 Decl *FromTU0 = getTuDecl(
4559 R"(
4560 class X {
4561 class Y;
4562 };
4563 class X::Y {
4564 template <typename T>
4565 friend class F; // The decl context of F is the global namespace.
4566 };
4567 )",
4568 Lang_CXX, "input0.cc");
4569 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4570 FromTU0, classTemplateDecl(hasName("F")));
4571 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4572 Decl *FromTU1 = getTuDecl(
4573 R"(
4574 template <typename T>
4575 class F {};
4576 )",
4577 Lang_CXX, "input1.cc");
4578 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4579 FromTU1, classTemplateDecl(hasName("F")));
4580 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4581 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4582 Imported1->getTemplatedDecl()->getTypeForDecl());
4583}
4584
4585TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4586 Decl *From, *To;
4587 std::tie(From, To) =
4588 getImportedDecl("class declToImport {};", Lang_CXX,
4589 "class Y { friend class declToImport; };", Lang_CXX);
4590 auto *Imported = cast<CXXRecordDecl>(To);
4591
4592 EXPECT_TRUE(Imported->getPreviousDecl());
4593}
4594
4595TEST_P(ImportFriendClasses,
4596 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4597 Decl *ToTU = getToTuDecl(
4598 R"(
4599 class X {
4600 class Y;
4601 };
4602 class X::Y {
4603 template <typename T>
4604 friend class F; // The decl context of F is the global namespace.
4605 };
4606 )",
4607 Lang_CXX);
4608 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4609 ToTU, classTemplateDecl(hasName("F")));
4610 Decl *FromTU = getTuDecl(
4611 R"(
4612 template <typename T>
4613 class F {};
4614 )",
4615 Lang_CXX, "input0.cc");
4616 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4617 FromTU, classTemplateDecl(hasName("F")));
4618 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4619 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4620 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4621 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4622 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4623}
4624
4625TEST_P(ImportFriendClasses,
4626 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4627 Decl *FromTU0 = getTuDecl(
4628 R"(
4629 class X {
4630 class Y;
4631 };
4632 class X::Y {
4633 template <typename T>
4634 friend class F; // The decl context of F is the global namespace.
4635 };
4636 )",
4637 Lang_CXX, "input0.cc");
4638 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4639 FromTU0, classTemplateDecl(hasName("F")));
4640 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4641 Decl *FromTU1 = getTuDecl(
4642 R"(
4643 template <typename T>
4644 class F {};
4645 )",
4646 Lang_CXX, "input1.cc");
4647 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4648 FromTU1, classTemplateDecl(hasName("F")));
4649 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4650 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4651 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4652 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4653 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4654}
4655
4656TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4657 Decl *FromTU0 = getTuDecl(
4658 R"(
4659 class X {
4660 class Y;
4661 };
4662 class X::Y {
4663 friend class F; // The decl context of F is the global namespace.
4664 };
4665 )",
4666 Lang_CXX, "input0.cc");
4667 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4668 QualType FT = Friend->getFriendType()->getType();
4669 FT = FromTU0->getASTContext().getCanonicalType(FT);
4670 auto *Fwd = cast<TagType>(FT)->getDecl();
4671 auto *ImportedFwd = Import(Fwd, Lang_CXX);
4672 Decl *FromTU1 = getTuDecl(
4673 R"(
4674 class F {};
4675 )",
4676 Lang_CXX, "input1.cc");
4677 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4678 FromTU1, cxxRecordDecl(hasName("F")));
4679 auto *ImportedDef = Import(Definition, Lang_CXX);
4680 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4681 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4682}
4683
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004684TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00004685 auto *Code = R"(
4686 template <class T>
4687 struct X {
4688 friend void foo(){}
4689 };
4690 )";
4691 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4692 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4693 ToTU, functionDecl(hasName("foo")));
4694
4695 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4696 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4697 FromTU, functionDecl(hasName("foo")));
4698 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4699 EXPECT_EQ(ImportedFoo, ToFoo);
4700}
4701
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004702struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00004703
4704TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4705 Decl *TU = getTuDecl(
4706 R"(
4707 namespace NS {
4708
4709 template <typename T>
4710 struct S {};
4711 template struct S<int>;
4712
4713 inline namespace INS {
4714 template <typename T>
4715 struct S {};
4716 template struct S<int>;
4717 }
4718
4719 }
4720 )", Lang_CXX11, "input0.cc");
4721 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4722 TU, namespaceDecl());
4723 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4724 TU, classTemplateSpecializationDecl());
4725 ASSERT_TRUE(NS->containsDecl(Spec));
4726
4727 NS->removeDecl(Spec);
4728 EXPECT_FALSE(NS->containsDecl(Spec));
4729}
4730
Gabor Marton7df342a2018-12-17 12:42:12 +00004731TEST_P(DeclContextTest,
4732 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4733 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4734 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4735 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4736
4737 // Investigate the list.
4738 auto *DC = A0->getDeclContext();
4739 ASSERT_TRUE(DC->containsDecl(A0));
4740 ASSERT_TRUE(DC->containsDecl(A1));
4741
4742 // Investigate the lookup table.
4743 auto *Map = DC->getLookupPtr();
4744 ASSERT_TRUE(Map);
4745 auto I = Map->find(A0->getDeclName());
4746 ASSERT_NE(I, Map->end());
4747 StoredDeclsList &L = I->second;
4748 // The lookup table contains the most recent decl of A.
4749 ASSERT_NE(L.getAsDecl(), A0);
4750 ASSERT_EQ(L.getAsDecl(), A1);
4751
4752 ASSERT_TRUE(L.getAsDecl());
4753 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4754 // The point here is to have a Vec with only one element, which is not the
4755 // one we are going to delete from the DC later.
4756 L.setHasExternalDecls();
4757 ASSERT_TRUE(L.getAsVector());
4758 ASSERT_EQ(1u, L.getAsVector()->size());
4759
4760 // This asserts in the old implementation.
4761 DC->removeDecl(A0);
4762 EXPECT_FALSE(DC->containsDecl(A0));
4763}
4764
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004765struct ImportFunctionTemplateSpecializations
4766 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004767
4768TEST_P(ImportFunctionTemplateSpecializations,
4769 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4770
4771 Decl *FromTU = getTuDecl(
4772 R"(
4773 template<class T>
4774 int f() { return 0; }
4775 void foo() { f<int>(); }
4776 )",
4777 Lang_CXX, "input0.cc");
4778
4779 // Check that the function template instantiation is NOT the child of the TU.
4780 auto Pattern = translationUnitDecl(
4781 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4782 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4783
4784 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4785 FromTU, functionDecl(hasName("foo")));
4786 ASSERT_TRUE(Import(Foo, Lang_CXX));
4787
4788 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4789 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4790}
4791
4792TEST_P(ImportFunctionTemplateSpecializations,
4793 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4794
4795 Decl *FromTU = getTuDecl(
4796 R"(
4797 template<class T>
4798 int f() { return 0; }
4799 template int f<int>();
4800 )",
4801 Lang_CXX, "input0.cc");
4802
4803 // Check that the function template instantiation is NOT the child of the TU.
4804 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4805 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4806 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4807
4808 ASSERT_TRUE(
4809 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4810
4811 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4812 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4813}
4814
4815TEST_P(ImportFunctionTemplateSpecializations,
4816 TUshouldContainFunctionTemplateSpecialization) {
4817
4818 Decl *FromTU = getTuDecl(
4819 R"(
4820 template<class T>
4821 int f() { return 0; }
4822 template <> int f<int>() { return 4; }
4823 )",
4824 Lang_CXX, "input0.cc");
4825
4826 // Check that the function template specialization is the child of the TU.
4827 auto Specialization =
4828 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4829 auto Pattern = translationUnitDecl(has(Specialization));
4830 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4831
4832 ASSERT_TRUE(
4833 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4834
4835 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4836 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4837}
4838
4839TEST_P(ImportFunctionTemplateSpecializations,
4840 FunctionTemplateSpecializationRedeclChain) {
4841
4842 Decl *FromTU = getTuDecl(
4843 R"(
4844 template<class T>
4845 int f() { return 0; }
4846 template <> int f<int>() { return 4; }
4847 )",
4848 Lang_CXX, "input0.cc");
4849
4850 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4851 hasParent(translationUnitDecl()));
4852 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4853 {
4854 auto *TU = FromTU;
4855 auto *SpecD = FromSpecD;
4856 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4857 TU, functionTemplateDecl());
4858 auto *FirstSpecD = *(TemplateD->spec_begin());
4859 ASSERT_EQ(SpecD, FirstSpecD);
4860 ASSERT_TRUE(SpecD->getPreviousDecl());
4861 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4862 ->doesThisDeclarationHaveABody());
4863 }
4864
4865 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4866
4867 {
4868 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4869 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4870 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4871 TU, functionTemplateDecl());
4872 auto *FirstSpecD = *(TemplateD->spec_begin());
4873 EXPECT_EQ(SpecD, FirstSpecD);
4874 ASSERT_TRUE(SpecD->getPreviousDecl());
4875 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4876 ->doesThisDeclarationHaveABody());
4877 }
4878}
4879
4880TEST_P(ImportFunctionTemplateSpecializations,
4881 MatchNumberOfFunctionTemplateSpecializations) {
4882
4883 Decl *FromTU = getTuDecl(
4884 R"(
4885 template <typename T> constexpr int f() { return 0; }
4886 template <> constexpr int f<int>() { return 4; }
4887 void foo() {
4888 static_assert(f<char>() == 0, "");
4889 static_assert(f<int>() == 4, "");
4890 }
4891 )",
4892 Lang_CXX11, "input0.cc");
4893 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4894 FromTU, functionDecl(hasName("foo")));
4895
4896 Import(FromD, Lang_CXX11);
4897 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4898 EXPECT_EQ(
4899 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4900 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4901}
4902
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004903TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004904 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4905 {
4906 Decl *FromTU = getTuDecl(
4907 R"(
4908 template <typename T>
4909 struct B;
4910 )",
4911 Lang_CXX, "input0.cc");
4912 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4913 FromTU, classTemplateDecl(hasName("B")));
4914
4915 Import(FromD, Lang_CXX);
4916 }
4917
4918 {
4919 Decl *FromTU = getTuDecl(
4920 R"(
4921 template <typename T>
4922 struct B {
4923 void f();
4924 B* b;
4925 };
4926 )",
4927 Lang_CXX, "input1.cc");
4928 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4929 FromTU, functionDecl(hasName("f")));
4930 Import(FromD, Lang_CXX);
4931 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4932 FromTU, classTemplateDecl(hasName("B")));
4933 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4934 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4935
4936 // We expect no (ODR) warning during the import.
4937 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4938 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4939 }
4940}
4941
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004942TEST_P(ASTImporterOptionSpecificTestBase,
4943 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004944 // We already have an incomplete underlying type in the "To" context.
4945 auto Code =
4946 R"(
4947 template <typename T>
4948 struct S {
4949 void foo();
4950 };
4951 using U = S<int>;
4952 )";
4953 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4954 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4955 typedefNameDecl(hasName("U")));
4956 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4957
4958 // The "From" context has the same typedef, but the underlying type is
4959 // complete this time.
4960 Decl *FromTU = getTuDecl(std::string(Code) +
4961 R"(
4962 void foo(U* u) {
4963 u->foo();
4964 }
4965 )", Lang_CXX11);
4966 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4967 typedefNameDecl(hasName("U")));
4968 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4969
4970 // The imported type should be complete.
4971 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4972 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4973}
4974
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004975struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004976
4977TEST_P(ASTImporterLookupTableTest, OneDecl) {
4978 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4979 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4980 ASTImporterLookupTable LT(*ToTU);
4981 auto Res = LT.lookup(ToTU, D->getDeclName());
4982 ASSERT_EQ(Res.size(), 1u);
4983 EXPECT_EQ(*Res.begin(), D);
4984}
4985
4986static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4987 for (Decl *D : DC->decls()) {
4988 if (auto *ND = dyn_cast<NamedDecl>(D))
4989 if (ND->getDeclName() == Name)
4990 return ND;
4991 }
4992 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004993}
Gabor Marton54058b52018-12-17 13:53:12 +00004994
4995TEST_P(ASTImporterLookupTableTest,
4996 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4997 auto *Code = R"(
4998 template <class T>
4999 struct X {
5000 friend void foo(){}
5001 };
5002 )";
5003 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
5004 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
5005 ToTU, classTemplateDecl(hasName("X")));
5006 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
5007 ToTU, functionDecl(hasName("foo")));
5008 DeclContext *FooDC = Foo->getDeclContext();
5009 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5010 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
5011 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5012 DeclarationName FooName = Foo->getDeclName();
5013
5014 // Cannot find in the LookupTable of its DC (TUDecl)
5015 SmallVector<NamedDecl *, 2> FoundDecls;
5016 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5017 EXPECT_EQ(FoundDecls.size(), 0u);
5018
5019 // Cannot find in the LookupTable of its LexicalDC (X)
5020 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5021 EXPECT_EQ(FoundDecls.size(), 0u);
5022
5023 // Can't find in the list of Decls of the DC.
5024 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5025
5026 // Can't find in the list of Decls of the LexicalDC
5027 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
5028
5029 // ASTImporter specific lookup finds it.
5030 ASTImporterLookupTable LT(*ToTU);
5031 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5032 ASSERT_EQ(Res.size(), 1u);
5033 EXPECT_EQ(*Res.begin(), Foo);
5034}
5035
5036TEST_P(ASTImporterLookupTableTest,
5037 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
5038 TranslationUnitDecl *ToTU =
5039 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
5040 auto *Foo =
5041 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
5042 auto *A =
5043 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5044 DeclContext *FooDC = Foo->getDeclContext();
5045 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5046 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
5047 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5048 DeclarationName FooName = Foo->getDeclName();
5049
5050 // Cannot find in the LookupTable of its DC (TUDecl).
5051 SmallVector<NamedDecl *, 2> FoundDecls;
5052 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5053 EXPECT_EQ(FoundDecls.size(), 0u);
5054
5055 // Cannot find in the LookupTable of its LexicalDC (A).
5056 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5057 EXPECT_EQ(FoundDecls.size(), 0u);
5058
5059 // Can't find in the list of Decls of the DC.
5060 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5061
5062 // Can find in the list of Decls of the LexicalDC.
5063 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
5064
5065 // ASTImporter specific lookup finds it.
5066 ASTImporterLookupTable LT(*ToTU);
5067 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5068 ASSERT_EQ(Res.size(), 1u);
5069 EXPECT_EQ(*Res.begin(), Foo);
5070}
5071
5072TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
5073 TranslationUnitDecl *ToTU =
5074 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
5075 DeclarationName VName = FirstDeclMatcher<VarDecl>()
5076 .match(ToTU, varDecl(hasName("V")))
5077 ->getDeclName();
5078 auto *A =
5079 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5080 auto *B =
5081 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
5082
5083 ASTImporterLookupTable LT(*ToTU);
5084
5085 auto Res = LT.lookup(cast<DeclContext>(A), VName);
5086 ASSERT_EQ(Res.size(), 1u);
5087 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5088 ToTU, fieldDecl(hasName("V"),
5089 hasParent(recordDecl(hasName("A"))))));
5090 Res = LT.lookup(cast<DeclContext>(B), VName);
5091 ASSERT_EQ(Res.size(), 1u);
5092 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5093 ToTU, fieldDecl(hasName("V"),
5094 hasParent(recordDecl(hasName("B"))))));
5095 Res = LT.lookup(ToTU, VName);
5096 ASSERT_EQ(Res.size(), 1u);
5097 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
5098 ToTU, varDecl(hasName("V"),
5099 hasParent(translationUnitDecl()))));
5100}
5101
5102TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5103 TranslationUnitDecl *ToTU = getToTuDecl(
5104 R"(
5105 void foo();
5106 void foo(int);
5107 void foo(int, int);
5108 )",
5109 Lang_CXX);
5110
5111 ASTImporterLookupTable LT(*ToTU);
5112 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5113 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5114 DeclarationName Name = F0->getDeclName();
5115 auto Res = LT.lookup(ToTU, Name);
5116 EXPECT_EQ(Res.size(), 3u);
5117 EXPECT_EQ(Res.count(F0), 1u);
5118 EXPECT_EQ(Res.count(F2), 1u);
5119}
5120
Gabor Martona9cab312019-02-08 09:19:34 +00005121TEST_P(ASTImporterLookupTableTest,
5122 DifferentOperatorsShouldHaveDifferentResultSet) {
5123 TranslationUnitDecl *ToTU = getToTuDecl(
5124 R"(
5125 struct X{};
5126 void operator+(X, X);
5127 void operator-(X, X);
5128 )",
5129 Lang_CXX);
5130
5131 ASTImporterLookupTable LT(*ToTU);
5132 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5133 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5134 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5135 ToTU, functionDecl(hasOverloadedOperatorName("-")));
5136 DeclarationName NamePlus = FPlus->getDeclName();
5137 auto ResPlus = LT.lookup(ToTU, NamePlus);
5138 EXPECT_EQ(ResPlus.size(), 1u);
5139 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5140 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5141 DeclarationName NameMinus = FMinus->getDeclName();
5142 auto ResMinus = LT.lookup(ToTU, NameMinus);
5143 EXPECT_EQ(ResMinus.size(), 1u);
5144 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5145 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5146 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5147}
5148
5149TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5150 TranslationUnitDecl *ToTU = getToTuDecl(
5151 R"(
5152 struct X {};
5153 void operator+(X, X);
5154 )",
5155 Lang_CXX);
5156 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5157 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5158
5159 Decl *FromTU = getTuDecl(
5160 R"(
5161 struct X {};
5162 void operator+(X, X);
5163 )",
5164 Lang_CXX);
5165 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5166 FromTU, functionDecl(hasOverloadedOperatorName("+")));
5167
5168 // FromPlus have a different TU, thus its DeclarationName is different too.
5169 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5170
5171 ASTImporterLookupTable LT(*ToTU);
5172 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
5173 ASSERT_EQ(Res.size(), 1u);
5174 EXPECT_EQ(*Res.begin(), ToPlus);
5175
5176 // FromPlus have a different TU, thus its DeclarationName is different too.
5177 Res = LT.lookup(ToTU, FromPlus->getDeclName());
5178 ASSERT_EQ(Res.size(), 0u);
5179}
5180
Gabor Marton54058b52018-12-17 13:53:12 +00005181static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
5182 QualType Ty = FD->getFriendType()->getType();
5183 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
5184 return cast<RecordType>(NamedTy)->getDecl();
5185}
5186
5187TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
5188 TranslationUnitDecl *ToTU = getToTuDecl(
5189 R"(
5190 class Y { friend class F; };
5191 )",
5192 Lang_CXX);
5193
5194 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5195 // So we must dig up the underlying CXXRecordDecl.
5196 ASTImporterLookupTable LT(*ToTU);
5197 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5198 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5199 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5200 ToTU, cxxRecordDecl(hasName("Y")));
5201
5202 DeclarationName Name = RD->getDeclName();
5203 auto Res = LT.lookup(ToTU, Name);
5204 EXPECT_EQ(Res.size(), 1u);
5205 EXPECT_EQ(*Res.begin(), RD);
5206
5207 Res = LT.lookup(Y, Name);
5208 EXPECT_EQ(Res.size(), 0u);
5209}
5210
5211TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5212 TranslationUnitDecl *ToTU = getToTuDecl(
5213 R"(
5214 class Y { template <class T> friend class F; };
5215 )",
5216 Lang_CXX);
5217
5218 ASTImporterLookupTable LT(*ToTU);
5219 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5220 ToTU, classTemplateDecl(hasName("F")));
5221 DeclarationName Name = F->getDeclName();
5222 auto Res = LT.lookup(ToTU, Name);
5223 EXPECT_EQ(Res.size(), 2u);
5224 EXPECT_EQ(Res.count(F), 1u);
5225 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5226}
5227
5228TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5229 TranslationUnitDecl *ToTU = getToTuDecl(
5230 R"(
5231 template <typename T>
5232 class F;
5233
5234 template <typename T>
5235 class Y {
5236 friend class F<T>;
5237 };
5238 )",
5239 Lang_CXX);
5240
5241 ASTImporterLookupTable LT(*ToTU);
5242 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5243 ToTU, classTemplateDecl(hasName("F")));
5244 DeclarationName Name = F->getDeclName();
5245 auto Res = LT.lookup(ToTU, Name);
5246 EXPECT_EQ(Res.size(), 2u);
5247 EXPECT_EQ(Res.count(F), 1u);
5248 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5249}
5250
5251TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
5252 TranslationUnitDecl *ToTU = getToTuDecl(
5253 R"(
5254 template <typename T>
5255 class F;
5256
5257 class Y {
5258 friend class F<int>;
5259 };
5260 )",
5261 Lang_CXX);
5262
5263 ASTImporterLookupTable LT(*ToTU);
5264 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5265 ToTU, classTemplateDecl(hasName("F")));
5266 DeclarationName Name = F->getDeclName();
5267 auto Res = LT.lookup(ToTU, Name);
5268 ASSERT_EQ(Res.size(), 3u);
5269 EXPECT_EQ(Res.count(F), 1u);
5270 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5271 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
5272}
5273
5274TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
5275 TranslationUnitDecl *ToTU = getToTuDecl(
5276 R"(
5277 class Y { friend void F(); };
5278 )",
5279 Lang_CXX);
5280
5281 ASTImporterLookupTable LT(*ToTU);
5282 auto *F =
5283 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
5284 DeclarationName Name = F->getDeclName();
5285 auto Res = LT.lookup(ToTU, Name);
5286 EXPECT_EQ(Res.size(), 1u);
5287 EXPECT_EQ(*Res.begin(), F);
5288}
5289
5290TEST_P(ASTImporterLookupTableTest,
5291 LookupFindsDeclsInClassTemplateSpecialization) {
5292 TranslationUnitDecl *ToTU = getToTuDecl(
5293 R"(
5294 template <typename T>
5295 struct X {
5296 int F;
5297 };
5298 void foo() {
5299 X<char> xc;
5300 }
5301 )",
5302 Lang_CXX);
5303
5304 ASTImporterLookupTable LT(*ToTU);
5305
5306 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
5307 ToTU, classTemplateDecl(hasName("X")));
5308 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
5309 ToTU,
5310 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
5311
5312 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5313 ToTU, classTemplateSpecializationDecl(hasName("X")));
5314 FieldDecl *FieldInSpec = *Spec->field_begin();
5315 ASSERT_TRUE(FieldInSpec);
5316
5317 DeclarationName Name = FieldInSpec->getDeclName();
5318 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
5319
5320 SmallVector<NamedDecl *, 2> FoundDecls;
5321 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
5322 EXPECT_EQ(FoundDecls.size(), 1u);
5323 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
5324
5325 auto Res = LT.lookup(TemplateDC, Name);
5326 ASSERT_EQ(Res.size(), 1u);
5327 EXPECT_EQ(*Res.begin(), FieldInTemplate);
5328
5329 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
5330 FoundDecls);
5331 EXPECT_EQ(FoundDecls.size(), 1u);
5332 EXPECT_EQ(FoundDecls[0], FieldInSpec);
5333
5334 Res = LT.lookup(cast<DeclContext>(Spec), Name);
5335 ASSERT_EQ(Res.size(), 1u);
5336 EXPECT_EQ(*Res.begin(), FieldInSpec);
5337}
5338
5339TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
5340 TranslationUnitDecl *ToTU = getToTuDecl(
5341 R"(
5342 class Y { template <class T> friend void F(); };
5343 )",
5344 Lang_CXX);
5345
5346 ASTImporterLookupTable LT(*ToTU);
5347 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
5348 ToTU, functionTemplateDecl(hasName("F")));
5349 DeclarationName Name = F->getDeclName();
5350 auto Res = LT.lookup(ToTU, Name);
5351 EXPECT_EQ(Res.size(), 2u);
5352 EXPECT_EQ(Res.count(F), 1u);
5353 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5354}
5355
5356TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
5357 TranslationUnitDecl *ToTU = getToTuDecl(
5358 R"(
5359 struct X;
5360 struct A {
5361 friend struct X;
5362 };
5363 struct B {
5364 friend struct X;
5365 };
5366 )",
5367 Lang_CXX);
5368
5369 ASTImporterLookupTable LT(*ToTU);
5370 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
5371 ToTU, cxxRecordDecl(hasName("X")));
5372 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5373 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5374 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
5375 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
5376 ASSERT_EQ(RD0, RD1);
5377 ASSERT_EQ(RD1, X);
5378
5379 DeclarationName Name = X->getDeclName();
5380 auto Res = LT.lookup(ToTU, Name);
5381 EXPECT_EQ(Res.size(), 1u);
5382 EXPECT_EQ(*Res.begin(), X);
5383}
5384
5385TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
5386 TranslationUnitDecl *ToTU = getToTuDecl(
5387 R"(
5388 enum E {
5389 A,
5390 B
5391 };
5392 )",
5393 Lang_C);
5394
5395 ASTImporterLookupTable LT(*ToTU);
5396 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
5397 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
5398 ToTU, enumConstantDecl(hasName("A")));
5399
5400 DeclarationName Name = A->getDeclName();
5401 // Redecl context is the TU.
5402 ASSERT_EQ(E->getRedeclContext(), ToTU);
5403
5404 SmallVector<NamedDecl *, 2> FoundDecls;
5405 // Normal lookup finds in the DC.
5406 E->localUncachedLookup(Name, FoundDecls);
5407 EXPECT_EQ(FoundDecls.size(), 1u);
5408
5409 // Normal lookup finds in the Redecl context.
5410 ToTU->localUncachedLookup(Name, FoundDecls);
5411 EXPECT_EQ(FoundDecls.size(), 1u);
5412
5413 // Import specific lookup finds in the DC.
5414 auto Res = LT.lookup(E, Name);
5415 ASSERT_EQ(Res.size(), 1u);
5416 EXPECT_EQ(*Res.begin(), A);
5417
5418 // Import specific lookup finds in the Redecl context.
5419 Res = LT.lookup(ToTU, Name);
5420 ASSERT_EQ(Res.size(), 1u);
5421 EXPECT_EQ(*Res.begin(), A);
5422}
5423
5424TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
5425 TranslationUnitDecl *ToTU = getToTuDecl(
5426 R"(
5427 namespace N {
5428 int A;
5429 }
5430 namespace N {
5431 }
5432 )",
5433 Lang_CXX);
5434 auto *N1 =
5435 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
5436 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
5437 DeclarationName Name = A->getDeclName();
5438
5439 ASTImporterLookupTable LT(*ToTU);
5440 auto Res = LT.lookup(N1, Name);
5441 ASSERT_EQ(Res.size(), 1u);
5442 EXPECT_EQ(*Res.begin(), A);
5443}
5444
Gabor Marton19f4f392018-06-25 13:04:37 +00005445INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5446 ::testing::Values(ArgVector()), );
5447
Gabor Marton5254e642018-06-27 13:32:50 +00005448INSTANTIATE_TEST_CASE_P(
5449 ParameterizedTests, CanonicalRedeclChain,
5450 ::testing::Values(ArgVector()),);
5451
Gabor Marton0e04ebd2019-02-11 10:27:58 +00005452// FIXME This test is disabled currently, upcoming patches will make it
5453// possible to enable.
5454TEST_P(ASTImporterOptionSpecificTestBase,
5455 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
5456 Decl *FromTU = getTuDecl(
5457 R"(
5458 namespace NS {
5459 struct X;
5460 struct Y {
5461 static const int I = 3;
5462 };
5463 }
5464 namespace NS {
5465 struct X { // <--- To be imported
5466 void method(int i = Y::I) {}
5467 int f;
5468 };
5469 }
5470 )",
5471 Lang_CXX);
5472 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5473 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5474 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
5475 FromTU,
5476 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
5477 ASSERT_NE(FromFwd, FromDef);
5478 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
5479 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
5480 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
5481
5482 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
5483 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
5484 EXPECT_NE(ToFwd, ToDef);
5485 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
5486 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
5487 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
5488 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5489 // We expect no (ODR) warning during the import.
5490 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5491}
5492
Gabor Martone331e632019-02-18 13:09:27 +00005493struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
5494
5495TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
5496 Decl *ToTU = getToTuDecl(
5497 R"(
5498 class X {
5499 template <typename T> friend void foo();
5500 };
5501 )",
5502 Lang_CXX);
5503 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
5504 ToTU, functionTemplateDecl(hasName("foo")));
5505
5506 Decl *FromTU = getTuDecl(
5507 R"(
5508 template <typename T> void foo();
5509 )",
5510 Lang_CXX);
5511 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
5512 FromTU, functionTemplateDecl(hasName("foo")));
5513 auto *Imported = Import(FromFoo, Lang_CXX);
5514
Gabor Marton16d98c22019-03-07 13:01:51 +00005515 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00005516}
5517
Gabor Marton54058b52018-12-17 13:53:12 +00005518INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5519 DefaultTestValuesForRunOptions, );
5520
Gabor Marton19f4f392018-06-25 13:04:37 +00005521INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5522 DefaultTestValuesForRunOptions, );
5523
5524INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5525 DefaultTestValuesForRunOptions, );
5526
5527INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5528 DefaultTestValuesForRunOptions, );
5529
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005530INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005531 DefaultTestValuesForRunOptions, );
5532
5533INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5534 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005535
Gabor Martone331e632019-02-18 13:09:27 +00005536INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5537 DefaultTestValuesForRunOptions, );
5538
Gabor Marton54058b52018-12-17 13:53:12 +00005539INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005540 DefaultTestValuesForRunOptions, );
5541
Gabor Marton54058b52018-12-17 13:53:12 +00005542INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005543 DefaultTestValuesForRunOptions, );
5544
Gabor Marton7df342a2018-12-17 12:42:12 +00005545INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5546 DefaultTestValuesForRunOptions, );
5547
Gabor Marton5254e642018-06-27 13:32:50 +00005548INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5549 ImportFunctionTemplateSpecializations,
5550 DefaultTestValuesForRunOptions, );
5551
Gabor Martonac3a5d62018-09-17 12:04:52 +00005552INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5553 DefaultTestValuesForRunOptions, );
5554
5555INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5556 DefaultTestValuesForRunOptions, );
5557
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005558} // end namespace ast_matchers
5559} // end namespace clang