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