blob: 00e12d75bc8535295978b448b0717ddd360a3fcc [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
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001235TEST_P(ASTImporterOptionSpecificTestBase,
1236 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001237 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1238 auto From =
1239 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1240 ASSERT_TRUE(From);
1241 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1242 ASSERT_TRUE(To);
1243 Decl *ToTemplated = To->getTemplatedDecl();
1244 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1245 EXPECT_TRUE(ToTemplated1);
1246 EXPECT_EQ(ToTemplated1, ToTemplated);
1247}
1248
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001249TEST_P(ASTImporterOptionSpecificTestBase,
1250 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001251 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1252 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1253 FromTU, functionTemplateDecl());
1254 ASSERT_TRUE(From);
1255 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1256 ASSERT_TRUE(To);
1257 Decl *ToTemplated = To->getTemplatedDecl();
1258 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1259 EXPECT_TRUE(ToTemplated1);
1260 EXPECT_EQ(ToTemplated1, ToTemplated);
1261}
1262
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001263TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001264 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1265 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1266 auto FromFT =
1267 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1268 ASSERT_TRUE(FromFT);
1269
1270 auto ToTemplated =
1271 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1272 EXPECT_TRUE(ToTemplated);
1273 auto ToTU = ToTemplated->getTranslationUnitDecl();
1274 auto ToFT =
1275 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1276 EXPECT_TRUE(ToFT);
1277}
1278
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001279TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001280 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001281 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1282 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1283 FromTU, functionTemplateDecl());
1284 ASSERT_TRUE(FromFT);
1285
1286 auto ToTemplated =
1287 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1288 EXPECT_TRUE(ToTemplated);
1289 auto ToTU = ToTemplated->getTranslationUnitDecl();
1290 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1291 ToTU, functionTemplateDecl());
1292 EXPECT_TRUE(ToFT);
1293}
1294
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001295TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001296 auto Code =
1297 R"(
1298 namespace x {
1299 template<class X> struct S1{};
1300 template<class X> struct S2{};
1301 template<class X> struct S3{};
1302 }
1303 )";
1304 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1305 auto FromNs =
1306 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1307 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1308 ASSERT_TRUE(ToNs);
1309 auto From =
1310 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1311 classTemplateDecl(
1312 hasName("S2")));
1313 auto To =
1314 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1315 classTemplateDecl(
1316 hasName("S2")));
1317 ASSERT_TRUE(From);
1318 ASSERT_TRUE(To);
1319 auto ToTemplated = To->getTemplatedDecl();
1320 auto ToTemplated1 =
1321 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1322 EXPECT_TRUE(ToTemplated1);
1323 ASSERT_EQ(ToTemplated1, ToTemplated);
1324}
1325
Tom Roeder521f0042019-02-26 19:26:41 +00001326TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1327 // This tests the import of isConditionTrue directly to make sure the importer
1328 // gets it right.
1329 Decl *From, *To;
1330 std::tie(From, To) = getImportedDecl(
1331 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1332 Lang_C, "", Lang_C);
1333
1334 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1335 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1336
1337 const ChooseExpr *FromChooseExpr =
1338 selectFirst<ChooseExpr>("choose", FromResults);
1339 ASSERT_TRUE(FromChooseExpr);
1340
1341 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1342 ASSERT_TRUE(ToChooseExpr);
1343
1344 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1345 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1346 ToChooseExpr->isConditionDependent());
1347}
1348
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001349TEST_P(ASTImporterOptionSpecificTestBase,
1350 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001351 Decl *From, *To;
1352 std::tie(From, To) = getImportedDecl(
1353 R"(
1354 template <typename T> struct X {};
1355
1356 void declToImport(int y, X<int> &x) {}
1357
1358 template <> struct X<int> {
1359 void g() {
1360 X<int> x;
1361 declToImport(0, x);
1362 }
1363 };
1364 )",
1365 Lang_CXX, "", Lang_CXX);
1366
1367 MatchVerifier<Decl> Verifier;
1368 auto Matcher = functionDecl(hasName("declToImport"),
1369 parameterCountIs(2),
1370 hasParameter(0, hasName("y")),
1371 hasParameter(1, hasName("x")),
1372 hasParameter(1, hasType(asString("X<int> &"))));
1373 ASSERT_TRUE(Verifier.match(From, Matcher));
1374 EXPECT_TRUE(Verifier.match(To, Matcher));
1375}
1376
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001377TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001378 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1379 Decl *From, *To;
1380 std::tie(From, To) =
1381 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1382 "void instantiate() { declToImport<int>(); }",
1383 Lang_CXX, "", Lang_CXX);
1384
1385 auto Check = [](Decl *D) -> bool {
1386 auto TU = D->getTranslationUnitDecl();
1387 for (auto Child : TU->decls()) {
1388 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1389 if (FD->getNameAsString() == "declToImport") {
1390 GTEST_NONFATAL_FAILURE_(
1391 "TU should not contain any FunctionDecl with name declToImport");
1392 return false;
1393 }
1394 }
1395 }
1396 return true;
1397 };
1398
1399 ASSERT_TRUE(Check(From));
1400 EXPECT_TRUE(Check(To));
1401}
1402
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001403TEST_P(ASTImporterOptionSpecificTestBase,
1404 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001405 Decl *From, *To;
1406 std::tie(From, To) =
1407 getImportedDecl("template <typename T> struct declToImport { T t; };"
1408 "void instantiate() { declToImport<int>(); }",
1409 Lang_CXX, "", Lang_CXX);
1410
1411 auto Check = [](Decl *D) -> bool {
1412 auto TU = D->getTranslationUnitDecl();
1413 for (auto Child : TU->decls()) {
1414 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1415 if (RD->getNameAsString() == "declToImport") {
1416 GTEST_NONFATAL_FAILURE_(
1417 "TU should not contain any CXXRecordDecl with name declToImport");
1418 return false;
1419 }
1420 }
1421 }
1422 return true;
1423 };
1424
1425 ASSERT_TRUE(Check(From));
1426 EXPECT_TRUE(Check(To));
1427}
1428
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001429TEST_P(ASTImporterOptionSpecificTestBase,
1430 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001431 Decl *From, *To;
1432 std::tie(From, To) =
1433 getImportedDecl(
1434 "template <typename T> struct X {};"
1435 "template <typename T> using declToImport = X<T>;"
1436 "void instantiate() { declToImport<int> a; }",
1437 Lang_CXX11, "", Lang_CXX11);
1438
1439 auto Check = [](Decl *D) -> bool {
1440 auto TU = D->getTranslationUnitDecl();
1441 for (auto Child : TU->decls()) {
1442 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1443 if (AD->getNameAsString() == "declToImport") {
1444 GTEST_NONFATAL_FAILURE_(
1445 "TU should not contain any TypeAliasDecl with name declToImport");
1446 return false;
1447 }
1448 }
1449 }
1450 return true;
1451 };
1452
1453 ASSERT_TRUE(Check(From));
1454 EXPECT_TRUE(Check(To));
1455}
1456
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001457TEST_P(ASTImporterOptionSpecificTestBase,
1458 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001459
1460 Decl *From, *To;
1461 std::tie(From, To) = getImportedDecl(
1462 R"(
1463 template<class T>
1464 class Base {};
1465 class declToImport : public Base<declToImport> {};
1466 )",
1467 Lang_CXX, "", Lang_CXX);
1468
1469 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1470 auto Pattern =
1471 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1472 ASSERT_TRUE(
1473 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1474 EXPECT_TRUE(
1475 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1476
1477 // Check that the ClassTemplateSpecializationDecl is the child of the
1478 // ClassTemplateDecl.
1479 Pattern = translationUnitDecl(has(classTemplateDecl(
1480 hasName("Base"), has(classTemplateSpecializationDecl()))));
1481 ASSERT_TRUE(
1482 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1483 EXPECT_TRUE(
1484 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1485}
1486
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001487AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1488 size_t Index = 0;
1489 for (FieldDecl *Field : Node.fields()) {
1490 if (Index == Order.size())
1491 return false;
1492 if (Field->getName() != Order[Index])
1493 return false;
1494 ++Index;
1495 }
1496 return Index == Order.size();
1497}
1498
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001499TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001500 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1501 Decl *From, *To;
1502 std::tie(From, To) = getImportedDecl(
1503 R"(
1504 namespace NS {
1505 template<class T>
1506 class X {};
1507 template class X<int>;
1508 }
1509 )",
1510 Lang_CXX, "", Lang_CXX, "NS");
1511
1512 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1513 // ClassTemplateDecl.
1514 auto Pattern = namespaceDecl(has(classTemplateDecl(
1515 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1516 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1517 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1518
1519 // Check that the ClassTemplateSpecializationDecl is the child of the
1520 // NamespaceDecl.
1521 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1522 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1523 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1524}
1525
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001526TEST_P(ASTImporterOptionSpecificTestBase,
1527 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001528 Decl *From, *To;
1529 std::tie(From, To) =
1530 getImportedDecl(
1531 "struct declToImport { int a; int b; };",
1532 Lang_CXX11, "", Lang_CXX11);
1533
1534 MatchVerifier<Decl> Verifier;
1535 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1536 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1537}
1538
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001539TEST_P(ASTImporterOptionSpecificTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001540 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001541 Decl *From, *To;
1542 std::tie(From, To) = getImportedDecl(
1543 // The original recursive algorithm of ASTImporter first imports 'c' then
1544 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1545 R"s(
1546 struct declToImport {
1547 int a = c + b;
1548 int b = 1;
1549 int c = 2;
1550 };
1551 )s",
1552 Lang_CXX11, "", Lang_CXX11);
1553
1554 MatchVerifier<Decl> Verifier;
1555 ASSERT_TRUE(
1556 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1557 EXPECT_TRUE(
1558 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1559}
1560
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001561TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001562 Decl *From, *To;
1563 std::tie(From, To) = getImportedDecl(
1564 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001565 struct declToImport {
1566 };
1567 )",
1568 Lang_CXX, "", Lang_CXX);
1569
1570 MatchVerifier<Decl> Verifier;
1571 // Match the implicit Decl.
1572 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1573 ASSERT_TRUE(Verifier.match(From, Matcher));
1574 EXPECT_TRUE(Verifier.match(To, Matcher));
1575}
1576
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001577TEST_P(ASTImporterOptionSpecificTestBase,
1578 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001579 Decl *From, *To;
1580 std::tie(From, To) = getImportedDecl(
1581 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001582 template <typename U>
1583 struct declToImport {
1584 };
1585 )",
1586 Lang_CXX, "", Lang_CXX);
1587
1588 MatchVerifier<Decl> Verifier;
1589 // Match the implicit Decl.
1590 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1591 ASSERT_TRUE(Verifier.match(From, Matcher));
1592 EXPECT_TRUE(Verifier.match(To, Matcher));
1593}
1594
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001595TEST_P(ASTImporterOptionSpecificTestBase,
1596 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001597 Decl *From, *To;
1598 std::tie(From, To) = getImportedDecl(
1599 R"(
1600 template<class T>
1601 class Base {};
1602 class declToImport : public Base<declToImport> {};
1603 )",
1604 Lang_CXX, "", Lang_CXX);
1605
1606 auto hasImplicitClass = has(cxxRecordDecl());
1607 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1608 hasName("Base"),
1609 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1610 ASSERT_TRUE(
1611 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1612 EXPECT_TRUE(
1613 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1614}
1615
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001616TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001617 Decl *From, *To;
1618 std::tie(From, To) =
1619 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1620
1621 MatchVerifier<Decl> Verifier;
1622 auto Matcher = functionDecl();
1623 ASSERT_TRUE(Verifier.match(From, Matcher));
1624 EXPECT_TRUE(Verifier.match(To, Matcher));
1625 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1626}
1627
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001628TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001629 Decl *FromTU = getTuDecl(
1630 R"(
1631 struct X {};
1632 void operator<<(int, X);
1633 )",
1634 Lang_CXX);
1635 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1636 const Decl *To = Import(From, Lang_CXX);
1637 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1638}
1639
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001640TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001641 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1642 Decl *From, *To;
1643 std::tie(From, To) = getImportedDecl(
1644 R"(
1645 template<class T>
1646 class Base { int a; };
1647 class declToImport : Base<declToImport> {};
1648 )",
1649 Lang_CXX, "", Lang_CXX);
1650
1651 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1652 hasName("Base"),
1653 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1654 ASSERT_TRUE(
1655 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1656 EXPECT_TRUE(
1657 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1658}
1659
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001660TEST_P(ASTImporterOptionSpecificTestBase,
1661 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001662 {
1663 Decl *FromTU = getTuDecl(
1664 R"(
1665 template <typename T>
1666 struct B;
1667 )",
1668 Lang_CXX, "input0.cc");
1669 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1670 FromTU, classTemplateDecl(hasName("B")));
1671
1672 Import(FromD, Lang_CXX);
1673 }
1674
1675 {
1676 Decl *FromTU = getTuDecl(
1677 R"(
1678 template <typename T>
1679 struct B {
1680 void f();
1681 };
1682 )",
1683 Lang_CXX, "input1.cc");
1684 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1685 FromTU, functionDecl(hasName("f")));
1686 Import(FromD, Lang_CXX);
1687 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1688 FromTU, classTemplateDecl(hasName("B")));
1689 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1690 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1691 }
1692}
1693
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001694TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001695 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1696 Decl *ToTU = getToTuDecl(
1697 R"(
1698 template <typename T>
1699 struct B {
1700 void f();
1701 };
1702
1703 template <typename T>
1704 struct B;
1705 )",
1706 Lang_CXX);
1707 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1708 [](const ClassTemplateDecl *T) {
1709 return T->isThisDeclarationADefinition();
1710 })
1711 .match(ToTU, classTemplateDecl()));
1712
1713 Decl *FromTU = getTuDecl(
1714 R"(
1715 template <typename T>
1716 struct B {
1717 void f();
1718 };
1719 )",
1720 Lang_CXX, "input1.cc");
1721 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1722 FromTU, classTemplateDecl(hasName("B")));
1723
1724 Import(FromD, Lang_CXX);
1725
1726 // We should have only one definition.
1727 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1728 [](const ClassTemplateDecl *T) {
1729 return T->isThisDeclarationADefinition();
1730 })
1731 .match(ToTU, classTemplateDecl()));
1732}
1733
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001734TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001735 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1736 Decl *ToTU = getToTuDecl(
1737 R"(
1738 struct B {
1739 void f();
1740 };
1741
1742 struct B;
1743 )",
1744 Lang_CXX);
1745 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001746 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001747
1748 Decl *FromTU = getTuDecl(
1749 R"(
1750 struct B {
1751 void f();
1752 };
1753 )",
1754 Lang_CXX, "input1.cc");
1755 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1756 FromTU, cxxRecordDecl(hasName("B")));
1757
1758 Import(FromD, Lang_CXX);
1759
1760 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001761 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001762}
1763
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001764static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1765 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1766 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1767 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1768 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1769}
1770static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1771 SourceManager &SM1, SourceManager &SM2) {
1772 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1773 FullSourceLoc{ Range2.getBegin(), SM2 });
1774 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1775 FullSourceLoc{ Range2.getEnd(), SM2 });
1776}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001777TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001778 Decl *FromTU = getTuDecl(
1779 R"(
1780 #define MFOO(arg) arg = arg + 1
1781
1782 void foo() {
1783 int a = 5;
1784 MFOO(a);
1785 }
1786 )",
1787 Lang_CXX);
1788 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1789 auto ToD = Import(FromD, Lang_CXX);
1790
1791 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1792 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1793 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1794 auto FromRHS =
1795 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1796
1797 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1798 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1799 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1800 FromSM);
1801 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1802 FromSM);
1803 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1804 FromSM);
1805}
1806
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001807TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001808 Decl *FromTU = getTuDecl(
1809 R"(
1810 #define FUNC_INT void declToImport
1811 #define FUNC FUNC_INT
1812 FUNC(int a);
1813 )",
1814 Lang_CXX);
1815 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1816 auto ToD = Import(FromD, Lang_CXX);
1817
1818 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1819 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1820 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1821 FromSM);
1822}
1823
Gabor Marton9581c332018-05-23 13:53:36 +00001824TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001825 ASTImporterOptionSpecificTestBase,
1826 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001827 Decl *ToTU = getToTuDecl(
1828 R"(
1829 template <typename T>
1830 struct B;
1831
1832 template <>
1833 struct B<int> {};
1834
1835 template <>
1836 struct B<int>;
1837 )",
1838 Lang_CXX);
1839 // We should have only one definition.
1840 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1841 [](const ClassTemplateSpecializationDecl *T) {
1842 return T->isThisDeclarationADefinition();
1843 })
1844 .match(ToTU, classTemplateSpecializationDecl()));
1845
1846 Decl *FromTU = getTuDecl(
1847 R"(
1848 template <typename T>
1849 struct B;
1850
1851 template <>
1852 struct B<int> {};
1853 )",
1854 Lang_CXX, "input1.cc");
1855 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1856 FromTU, classTemplateSpecializationDecl(hasName("B")));
1857
1858 Import(FromD, Lang_CXX);
1859
1860 // We should have only one definition.
1861 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1862 [](const ClassTemplateSpecializationDecl *T) {
1863 return T->isThisDeclarationADefinition();
1864 })
1865 .match(ToTU, classTemplateSpecializationDecl()));
1866}
1867
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001868TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001869 Decl *FromTU = getTuDecl(
1870 R"(
1871 struct { int a; int b; } object0 = { 2, 3 };
1872 struct { int x; int y; int z; } object1;
1873 )",
1874 Lang_CXX, "input0.cc");
1875
Gabor Marton0bebf952018-07-05 09:51:13 +00001876 auto *Obj0 =
1877 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1878 auto *From0 = getRecordDecl(Obj0);
1879 auto *Obj1 =
1880 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1881 auto *From1 = getRecordDecl(Obj1);
1882
1883 auto *To0 = Import(From0, Lang_CXX);
1884 auto *To1 = Import(From1, Lang_CXX);
1885
1886 EXPECT_TRUE(To0);
1887 EXPECT_TRUE(To1);
1888 EXPECT_NE(To0, To1);
1889 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1890}
1891
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001892TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001893 auto *Code =
1894 R"(
1895 struct X {
1896 struct { int a; };
1897 struct { int b; };
1898 };
1899 )";
1900 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1901
1902 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1903
1904 auto *X0 =
1905 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1906 auto *X1 =
1907 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1908 Import(X0, Lang_C);
1909 Import(X1, Lang_C);
1910
1911 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1912 // We expect no (ODR) warning during the import.
1913 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1914 EXPECT_EQ(1u,
1915 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1916}
1917
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001918TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001919 Decl *FromTU0 = getTuDecl(
1920 R"(
1921 struct X {
1922 struct { int a; };
1923 struct { int b; };
1924 };
1925 )",
1926 Lang_C, "input0.c");
1927
1928 Decl *FromTU1 = getTuDecl(
1929 R"(
1930 struct X { // reversed order
1931 struct { int b; };
1932 struct { int a; };
1933 };
1934 )",
1935 Lang_C, "input1.c");
1936
1937 auto *X0 =
1938 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1939 auto *X1 =
1940 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1941 Import(X0, Lang_C);
1942 Import(X1, Lang_C);
1943
1944 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1945 // We expect one (ODR) warning during the import.
1946 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1947 EXPECT_EQ(2u,
1948 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1949}
1950
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001951TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001952 auto Pattern = varDecl(hasName("x"));
1953 VarDecl *Imported1;
1954 {
1955 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1956 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1957 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1958 }
1959 VarDecl *Imported2;
1960 {
1961 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1962 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1963 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1964 }
1965 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1966 EXPECT_FALSE(Imported2->isUsed(false));
1967 {
1968 Decl *FromTU =
1969 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001970 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1971 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001972 Import(FromD, Lang_CXX);
1973 }
1974 EXPECT_TRUE(Imported2->isUsed(false));
1975}
1976
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001977TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001978 auto Pattern = varDecl(hasName("x"));
1979 VarDecl *ExistingD;
1980 {
1981 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1982 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1983 }
1984 EXPECT_FALSE(ExistingD->isUsed(false));
1985 {
1986 Decl *FromTU = getTuDecl(
1987 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1988 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1989 FromTU, functionDecl(hasName("f")));
1990 Import(FromD, Lang_CXX);
1991 }
1992 EXPECT_TRUE(ExistingD->isUsed(false));
1993}
1994
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001995TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001996 auto Pattern = varDecl(hasName("a"));
1997 VarDecl *ExistingD;
1998 {
1999 Decl *ToTU = getToTuDecl(
2000 R"(
2001 struct A {
2002 static const int a = 1;
2003 };
2004 )", Lang_CXX);
2005 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2006 }
2007 EXPECT_FALSE(ExistingD->isUsed(false));
2008 {
2009 Decl *FromTU = getTuDecl(
2010 R"(
2011 struct A {
2012 static const int a = 1;
2013 };
2014 const int *f() { return &A::a; } // requires storage,
2015 // thus used flag will be set
2016 )", Lang_CXX, "input1.cc");
2017 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
2018 FromTU, functionDecl(hasName("f")));
2019 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2020 ASSERT_TRUE(FromD->isUsed(false));
2021 Import(FromFunD, Lang_CXX);
2022 }
2023 EXPECT_TRUE(ExistingD->isUsed(false));
2024}
2025
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002026TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00002027 auto Pattern = varDecl(hasName("x"));
2028
2029 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
2030 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2031
2032 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
2033
2034 ASSERT_FALSE(Imported1->isUsed(false));
2035
2036 FromD->setIsUsed();
2037 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2038
2039 EXPECT_EQ(Imported1, Imported2);
2040 EXPECT_TRUE(Imported2->isUsed(false));
2041}
2042
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002043struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00002044
Gabor Marton5254e642018-06-27 13:32:50 +00002045TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002046 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2047 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002048 auto *From =
2049 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002050
Gabor Marton5254e642018-06-27 13:32:50 +00002051 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002052 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2053
Gabor Marton5254e642018-06-27 13:32:50 +00002054 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2055 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2056 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2057 EXPECT_TRUE(ImportedD == To0);
2058 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2059 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2060 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002061}
2062
2063TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2064 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2065 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002066 auto *From =
2067 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002068
Gabor Marton5254e642018-06-27 13:32:50 +00002069 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002070 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2071
Gabor Marton5254e642018-06-27 13:32:50 +00002072 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2073 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2074 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2075 EXPECT_TRUE(ImportedD == To1);
2076 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2077 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2078 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002079}
2080
Peter Szecsidedda6f2018-03-30 22:03:29 +00002081TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2082 auto Code =
2083 R"(
2084 struct B { virtual void f(); };
2085 void B::f() {}
2086 struct D : B { void f(); };
2087 )";
2088 auto Pattern =
2089 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2090 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2091 CXXMethodDecl *Proto =
2092 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2093
2094 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2095 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2096 EXPECT_EQ(To->size_overridden_methods(), 1u);
2097}
2098
2099TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2100 auto Code =
2101 R"(
2102 struct B { virtual void f(); };
2103 void B::f() {}
2104 )";
2105 auto Pattern =
2106 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2107 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2108 CXXMethodDecl *Proto =
2109 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2110 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2111
2112 ASSERT_TRUE(Proto->isVirtual());
2113 ASSERT_TRUE(Def->isVirtual());
2114 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2115 EXPECT_TRUE(To->isVirtual());
2116}
2117
Gabor Marton5254e642018-06-27 13:32:50 +00002118TEST_P(ImportFunctions,
2119 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2120 Decl *ToTU = getToTuDecl(
2121 R"(
2122 void f() {}
2123 void f();
2124 )",
2125 Lang_CXX);
2126 ASSERT_EQ(1u,
2127 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2128 return FD->doesThisDeclarationHaveABody();
2129 }).match(ToTU, functionDecl()));
2130
2131 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2132 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2133
2134 Import(FromD, Lang_CXX);
2135
2136 EXPECT_EQ(1u,
2137 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2138 return FD->doesThisDeclarationHaveABody();
2139 }).match(ToTU, functionDecl()));
2140}
2141
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002142TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2143 auto Code =
2144 R"(
2145 struct B { virtual void f(); };
2146 struct D:B { void f(); };
2147 )";
2148 auto BFP =
2149 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2150 auto DFP =
2151 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2152
2153 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2154 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2155 Import(DF, Lang_CXX);
2156
2157 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2158 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2159 Import(BF, Lang_CXX);
2160
2161 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2162
2163 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2164 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2165}
2166
2167TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2168 auto CodeWithoutDef =
2169 R"(
2170 struct B { virtual void f(); };
2171 struct D:B { void f(); };
2172 )";
2173 auto CodeWithDef =
2174 R"(
2175 struct B { virtual void f(){}; };
2176 struct D:B { void f(){}; };
2177 )";
2178 auto BFP =
2179 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2180 auto DFP =
2181 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2182 auto BFDefP = cxxMethodDecl(
2183 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2184 auto DFDefP = cxxMethodDecl(
2185 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2186 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2187
2188 {
2189 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2190 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2191 Import(FromD, Lang_CXX);
2192 }
2193 {
2194 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2195 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2196 Import(FromB, Lang_CXX);
2197 }
2198
2199 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2200
2201 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2202 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2203 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2204 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2205 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2206}
2207
2208TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2209 auto Code =
2210 R"(
2211 struct B { virtual void f(); };
2212 struct D:B { void f(); };
2213 void B::f(){};
2214 )";
2215
2216 auto BFP =
2217 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2218 auto BFDefP = cxxMethodDecl(
2219 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2220 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2221 unless(isDefinition()));
2222
2223 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2224 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2225 Import(D, Lang_CXX);
2226
2227 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2228 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2229 Import(B, Lang_CXX);
2230
2231 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2232
2233 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2234 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2235
2236 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2237 ToTU, cxxRecordDecl(hasName("B")));
2238 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2239 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2240 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2241
2242 // The definition should be out-of-class.
2243 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2244 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2245 ToBFOutOfClass->getLexicalDeclContext());
2246 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2247 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2248
2249 // Check that the redecl chain is intact.
2250 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2251}
2252
2253TEST_P(ImportFunctions,
2254 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2255 auto CodeTU0 =
2256 R"(
2257 struct B { virtual void f(); };
2258 struct D:B { void f(); };
2259 )";
2260 auto CodeTU1 =
2261 R"(
2262 struct B { virtual void f(); };
2263 struct D:B { void f(); };
2264 void B::f(){}
2265 void D::f(){}
2266 void foo(B &b, D &d) { b.f(); d.f(); }
2267 )";
2268
2269 auto BFP =
2270 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2271 auto BFDefP = cxxMethodDecl(
2272 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2273 auto DFP =
2274 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2275 auto DFDefP = cxxMethodDecl(
2276 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2277 auto FooDef = functionDecl(hasName("foo"));
2278
2279 {
2280 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2281 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2282 Import(D, Lang_CXX);
2283 }
2284
2285 {
2286 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2287 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2288 Import(Foo, Lang_CXX);
2289 }
2290
2291 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2292
2293 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2294 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2295 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2296 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2297
2298 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2299 ToTU, cxxRecordDecl(hasName("B")));
2300 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2301 ToTU, cxxRecordDecl(hasName("D")));
2302 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2303 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2304 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2305 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2306 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2307 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2308
2309 // The definition should be out-of-class.
2310 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2311 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2312 ToBFOutOfClass->getLexicalDeclContext());
2313 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2314 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2315
2316 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2317 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2318 ToDFOutOfClass->getLexicalDeclContext());
2319 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2320 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2321
2322 // Check that the redecl chain is intact.
2323 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2324 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2325}
2326
Gabor Marton458d1452019-02-14 13:07:03 +00002327//FIXME Move these tests to a separate test file.
2328namespace TypeAndValueParameterizedTests {
2329
2330// Type parameters for type-parameterized test fixtures.
2331struct GetFunPattern {
2332 using DeclTy = FunctionDecl;
2333 BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
2334};
2335struct GetVarPattern {
2336 using DeclTy = VarDecl;
2337 BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
2338};
2339
2340// Values for the value-parameterized test fixtures.
2341// FunctionDecl:
2342auto *ExternF = "void f();";
2343auto *StaticF = "static void f();";
2344auto *AnonF = "namespace { void f(); }";
2345// VarDecl:
2346auto *ExternV = "extern int v;";
2347auto *StaticV = "static int v;";
2348auto *AnonV = "namespace { extern int v; }";
2349
2350// First value in tuple: Compile options.
2351// Second value in tuple: Source code to be used in the test.
2352using ImportVisibilityChainParams =
2353 ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
2354// Fixture to test the redecl chain of Decls with the same visibility. Gtest
2355// makes it possible to have either value-parameterized or type-parameterized
2356// fixtures. However, we cannot have both value- and type-parameterized test
2357// fixtures. This is a value-parameterized test fixture in the gtest sense. We
2358// intend to mimic gtest's type-parameters via the PatternFactory template
2359// parameter. We manually instantiate the different tests with the each types.
2360template <typename PatternFactory>
2361class ImportVisibilityChain
2362 : public ASTImporterTestBase, public ImportVisibilityChainParams {
2363protected:
2364 using DeclTy = typename PatternFactory::DeclTy;
2365 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2366 std::string getCode() const { return std::get<1>(GetParam()); }
2367 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2368
2369 // Type-parameterized test.
2370 void TypedTest_ImportChain() {
2371 std::string Code = getCode() + getCode();
2372 auto Pattern = getPattern();
2373
2374 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
2375
2376 auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
2377 auto *FromF1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
2378
2379 auto *ToF0 = Import(FromF0, Lang_CXX);
2380 auto *ToF1 = Import(FromF1, Lang_CXX);
2381
2382 EXPECT_TRUE(ToF0);
2383 ASSERT_TRUE(ToF1);
2384 EXPECT_NE(ToF0, ToF1);
2385 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2386 }
2387};
2388
2389// Manual instantiation of the fixture with each type.
2390using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
2391using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
2392// Value-parameterized test for the first type.
2393TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
2394 TypedTest_ImportChain();
2395}
2396// Value-parameterized test for the second type.
2397TEST_P(ImportVariablesVisibilityChain, ImportChain) {
2398 TypedTest_ImportChain();
2399}
2400
2401// Automatic instantiation of the value-parameterized tests.
2402INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
2403 ::testing::Combine(
2404 DefaultTestValuesForRunOptions,
2405 ::testing::Values(ExternF, StaticF, AnonF)), );
2406INSTANTIATE_TEST_CASE_P(
2407 ParameterizedTests, ImportVariablesVisibilityChain,
2408 ::testing::Combine(
2409 DefaultTestValuesForRunOptions,
2410 // There is no point to instantiate with StaticV, because in C++ we can
2411 // forward declare a variable only with the 'extern' keyword.
2412 // Consequently, each fwd declared variable has external linkage. This
2413 // is different in the C language where any declaration without an
2414 // initializer is a tentative definition, subsequent definitions may be
2415 // provided but they must have the same linkage. See also the test
2416 // ImportVariableChainInC which test for this special C Lang case.
2417 ::testing::Values(ExternV, AnonV)), );
2418
2419// First value in tuple: Compile options.
2420// Second value in tuple: Tuple with informations for the test.
2421// Code for first import (or initial code), code to import, whether the `f`
2422// functions are expected to be linked in a declaration chain.
2423// One value of this tuple is combined with every value of compile options.
2424// The test can have a single tuple as parameter only.
2425using ImportVisibilityParams = ::testing::WithParamInterface<
2426 std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
2427
2428template <typename PatternFactory>
2429class ImportVisibility
2430 : public ASTImporterTestBase,
2431 public ImportVisibilityParams {
2432protected:
2433 using DeclTy = typename PatternFactory::DeclTy;
2434 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2435 std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
2436 std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
2437 bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
2438 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2439
2440 void TypedTest_ImportAfter() {
2441 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
2442 TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2443
2444 auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
2445 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
2446
2447 auto *ToF1 = Import(FromF1, Lang_CXX);
2448
2449 ASSERT_TRUE(ToF0);
2450 ASSERT_TRUE(ToF1);
2451 EXPECT_NE(ToF0, ToF1);
2452
2453 if (shouldBeLinked())
2454 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2455 else
2456 EXPECT_FALSE(ToF1->getPreviousDecl());
2457 }
2458
2459 void TypedTest_ImportAfterImport() {
2460 TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
2461 TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2462 auto *FromF0 =
2463 FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
2464 auto *FromF1 =
2465 FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
2466 auto *ToF0 = Import(FromF0, Lang_CXX);
2467 auto *ToF1 = Import(FromF1, Lang_CXX);
2468 ASSERT_TRUE(ToF0);
2469 ASSERT_TRUE(ToF1);
2470 EXPECT_NE(ToF0, ToF1);
2471 if (shouldBeLinked())
2472 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2473 else
2474 EXPECT_FALSE(ToF1->getPreviousDecl());
2475 }
2476};
2477using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
2478using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
2479
2480// FunctionDecl.
2481TEST_P(ImportFunctionsVisibility, ImportAfter) {
2482 TypedTest_ImportAfter();
2483}
2484TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
2485 TypedTest_ImportAfterImport();
2486}
2487// VarDecl.
2488TEST_P(ImportVariablesVisibility, ImportAfter) {
2489 TypedTest_ImportAfter();
2490}
2491TEST_P(ImportVariablesVisibility, ImportAfterImport) {
2492 TypedTest_ImportAfterImport();
2493}
2494
2495bool ExpectLink = true;
2496bool ExpectNotLink = false;
2497
2498INSTANTIATE_TEST_CASE_P(
2499 ParameterizedTests, ImportFunctionsVisibility,
2500 ::testing::Combine(
2501 DefaultTestValuesForRunOptions,
2502 ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
2503 std::make_tuple(ExternF, StaticF, ExpectNotLink),
2504 std::make_tuple(ExternF, AnonF, ExpectNotLink),
2505 std::make_tuple(StaticF, ExternF, ExpectNotLink),
2506 std::make_tuple(StaticF, StaticF, ExpectNotLink),
2507 std::make_tuple(StaticF, AnonF, ExpectNotLink),
2508 std::make_tuple(AnonF, ExternF, ExpectNotLink),
2509 std::make_tuple(AnonF, StaticF, ExpectNotLink),
2510 std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
2511INSTANTIATE_TEST_CASE_P(
2512 ParameterizedTests, ImportVariablesVisibility,
2513 ::testing::Combine(
2514 DefaultTestValuesForRunOptions,
2515 ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
2516 std::make_tuple(ExternV, StaticV, ExpectNotLink),
2517 std::make_tuple(ExternV, AnonV, ExpectNotLink),
2518 std::make_tuple(StaticV, ExternV, ExpectNotLink),
2519 std::make_tuple(StaticV, StaticV, ExpectNotLink),
2520 std::make_tuple(StaticV, AnonV, ExpectNotLink),
2521 std::make_tuple(AnonV, ExternV, ExpectNotLink),
2522 std::make_tuple(AnonV, StaticV, ExpectNotLink),
2523 std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
2524
2525} // namespace TypeAndValueParameterizedTests
2526
2527TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2528 std::string Code = "static int v; static int v = 0;";
2529 auto Pattern = varDecl(hasName("v"));
2530
2531 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2532
2533 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2534 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2535
2536 auto *To0 = Import(From0, Lang_C);
2537 auto *To1 = Import(From1, Lang_C);
2538
2539 EXPECT_TRUE(To0);
2540 ASSERT_TRUE(To1);
2541 EXPECT_NE(To0, To1);
2542 EXPECT_EQ(To1->getPreviousDecl(), To0);
2543}
2544
2545TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2546 TranslationUnitDecl *FromTu = getTuDecl(
2547 "namespace NS0 { namespace { void f(); } }"
2548 "namespace NS1 { namespace { void f(); } }",
2549 Lang_CXX, "input0.cc");
2550 auto Pattern = functionDecl(hasName("f"));
2551
2552 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2553 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2554
2555 auto *ToF0 = Import(FromF0, Lang_CXX);
2556 auto *ToF1 = Import(FromF1, Lang_CXX);
2557
2558 EXPECT_TRUE(ToF0);
2559 ASSERT_TRUE(ToF1);
2560 EXPECT_NE(ToF0, ToF1);
2561 EXPECT_FALSE(ToF1->getPreviousDecl());
2562}
2563
2564TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2565 {
2566 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2567 Lang_CXX, "input0.cc");
2568 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2569 FromTU, functionDecl(hasName("g0")));
2570
2571 Import(FromD, Lang_CXX);
2572 }
2573 {
2574 Decl *FromTU =
2575 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2576 Lang_CXX, "input1.cc");
2577 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2578 FromTU, functionDecl(hasName("g1")));
2579 Import(FromD, Lang_CXX);
2580 }
2581
2582 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2583 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2584 2u);
2585}
2586
Gabor Marton302f3002019-02-15 12:04:05 +00002587TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2588 Decl *FromTU = getTuDecl(
2589 R"(
2590 void foo() {
2591 (void)[]() { ; };
2592 }
2593 )",
2594 Lang_CXX11);
2595 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2596 FromTU, functionDecl(hasName("foo")));
2597 auto *ToD = Import(FromD, Lang_CXX);
2598 EXPECT_TRUE(ToD);
2599 CXXRecordDecl *LambdaRec =
2600 cast<LambdaExpr>(cast<CStyleCastExpr>(
2601 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2602 ->getSubExpr())
2603 ->getLambdaClass();
2604 EXPECT_TRUE(LambdaRec->getDestructor());
2605}
2606
Gabor Marton5254e642018-06-27 13:32:50 +00002607struct ImportFriendFunctions : ImportFunctions {};
2608
2609TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2610 auto Pattern = functionDecl(hasName("f"));
2611
2612 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2613 "void f();",
2614 Lang_CXX,
2615 "input0.cc");
2616 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2617
2618 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2619 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2620 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2621 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2622 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2623 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2624 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2625}
2626
2627TEST_P(ImportFriendFunctions,
2628 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2629 auto Pattern = functionDecl(hasName("f"));
2630
2631 Decl *FromTU = getTuDecl("void f();"
2632 "struct X { friend void f(); };",
2633 Lang_CXX, "input0.cc");
2634 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2635
2636 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2637 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2638 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2639 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2640 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2641 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2642 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2643}
2644
2645TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2646 auto Pattern = functionDecl(hasName("f"));
2647
2648 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2649 "void f();",
2650 Lang_CXX,
2651 "input0.cc");
2652 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2653
2654 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2655 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2656 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2657 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2658 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2659 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2660 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2661}
2662
2663TEST_P(ImportFriendFunctions,
2664 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2665 auto Pattern = functionDecl(hasName("f"));
2666
2667 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2668 "void f(){}",
2669 Lang_CXX, "input0.cc");
2670 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2671
2672 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2673 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2674 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2675 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2676 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2677 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2678 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2679}
2680
Gabor Marton26f72a92018-07-12 09:42:05 +00002681// Disabled temporarily, because the new structural equivalence check
2682// (https://reviews.llvm.org/D48628) breaks it.
2683// PreviousDecl is not set because there is no structural match.
2684// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002685TEST_P(ImportFriendFunctions,
2686 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2687 auto Pattern = functionDecl(hasName("f"));
2688
2689 Decl *FromTU = getTuDecl(
2690 R"(
2691 class X;
2692 void f(X *x){}
2693 class X{
2694 friend void f(X *x);
2695 };
2696 )",
2697 Lang_CXX, "input0.cc");
2698 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2699
2700 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2701 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2702 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2703 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2704 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2705 .match(ToTU, friendDecl())
2706 ->getFriendDecl());
2707 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2708 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2709 // The parameters must refer the same type
2710 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2711 (*ImportedD->param_begin())->getOriginalType());
2712}
2713
Gabor Marton26f72a92018-07-12 09:42:05 +00002714// Disabled temporarily, because the new structural equivalence check
2715// (https://reviews.llvm.org/D48628) breaks it.
2716// PreviousDecl is not set because there is no structural match.
2717// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002718TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002719 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002720 auto Pattern = functionDecl(hasName("f"));
2721
2722 Decl *FromTU = getTuDecl(
2723 R"(
2724 class X;
2725 void f(X *x){}
2726 class X{
2727 friend void f(X *x);
2728 };
2729 )",
2730 Lang_CXX, "input0.cc");
2731 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2732
2733 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2734 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2735 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2736 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2737 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2738 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2739
2740 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2741 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2742 // The parameters must refer the same type
2743 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2744 (*ImportedD->param_begin())->getOriginalType());
2745}
2746
2747TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2748 auto Pattern = functionDecl(hasName("f"));
2749
2750 FunctionDecl *ImportedD;
2751 {
2752 Decl *FromTU =
2753 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2754 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2755 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2756 }
2757 FunctionDecl *ImportedD1;
2758 {
2759 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2760 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2761 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2762 }
2763
2764 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2765 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2766 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2767 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2768 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2769}
2770
Balazs Keri89632b82018-08-21 14:32:21 +00002771TEST_P(ImportFriendFunctions, Lookup) {
2772 auto FunctionPattern = functionDecl(hasName("f"));
2773 auto ClassPattern = cxxRecordDecl(hasName("X"));
2774
2775 TranslationUnitDecl *FromTU =
2776 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2777 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2778 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2779 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2780 {
2781 auto FromName = FromD->getDeclName();
2782 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2783 auto LookupRes = Class->noload_lookup(FromName);
2784 ASSERT_EQ(LookupRes.size(), 0u);
2785 LookupRes = FromTU->noload_lookup(FromName);
2786 ASSERT_EQ(LookupRes.size(), 1u);
2787 }
2788
2789 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2790 auto ToName = ToD->getDeclName();
2791
2792 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2793 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2794 auto LookupRes = Class->noload_lookup(ToName);
2795 EXPECT_EQ(LookupRes.size(), 0u);
2796 LookupRes = ToTU->noload_lookup(ToName);
2797 EXPECT_EQ(LookupRes.size(), 1u);
2798
2799 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2800 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2801 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2802 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2803}
2804
2805TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2806 auto FunctionPattern = functionDecl(hasName("f"));
2807 auto ClassPattern = cxxRecordDecl(hasName("X"));
2808
2809 TranslationUnitDecl *FromTU = getTuDecl(
2810 "struct X { friend void f(); };"
2811 // This proto decl makes f available to normal
2812 // lookup, otherwise it is hidden.
2813 // Normal C++ lookup (implemented in
2814 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2815 // returns the found `NamedDecl` only if the set IDNS is matched
2816 "void f();",
2817 Lang_CXX, "input0.cc");
2818 auto *FromFriend =
2819 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2820 auto *FromNormal =
2821 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2822 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2823 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2824 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2825 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2826
2827 auto FromName = FromFriend->getDeclName();
2828 auto *FromClass =
2829 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2830 auto LookupRes = FromClass->noload_lookup(FromName);
2831 ASSERT_EQ(LookupRes.size(), 0u);
2832 LookupRes = FromTU->noload_lookup(FromName);
2833 ASSERT_EQ(LookupRes.size(), 1u);
2834
2835 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2836 auto ToName = ToFriend->getDeclName();
2837
2838 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2839 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2840 LookupRes = ToClass->noload_lookup(ToName);
2841 EXPECT_EQ(LookupRes.size(), 0u);
2842 LookupRes = ToTU->noload_lookup(ToName);
2843 // Test is disabled because this result is 2.
2844 EXPECT_EQ(LookupRes.size(), 1u);
2845
2846 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2847 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2848 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2849 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2850 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2851 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2852 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2853}
2854
2855TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2856 auto FunctionPattern = functionDecl(hasName("f"));
2857 auto ClassPattern = cxxRecordDecl(hasName("X"));
2858
2859 TranslationUnitDecl *FromTU = getTuDecl(
2860 "void f();"
2861 "struct X { friend void f(); };",
2862 Lang_CXX, "input0.cc");
2863 auto *FromNormal =
2864 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2865 auto *FromFriend =
2866 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2867 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2868 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2869 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2870 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2871
2872 auto FromName = FromNormal->getDeclName();
2873 auto *FromClass =
2874 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2875 auto LookupRes = FromClass->noload_lookup(FromName);
2876 ASSERT_EQ(LookupRes.size(), 0u);
2877 LookupRes = FromTU->noload_lookup(FromName);
2878 ASSERT_EQ(LookupRes.size(), 1u);
2879
2880 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2881 auto ToName = ToNormal->getDeclName();
2882 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2883
2884 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2885 LookupRes = ToClass->noload_lookup(ToName);
2886 EXPECT_EQ(LookupRes.size(), 0u);
2887 LookupRes = ToTU->noload_lookup(ToName);
2888 EXPECT_EQ(LookupRes.size(), 1u);
2889
2890 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2891 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2892 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2893 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2894 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2895 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2896 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2897}
2898
2899TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2900 auto Pattern = functionDecl(hasName("f"));
2901
2902 TranslationUnitDecl *FromNormalTU =
2903 getTuDecl("void f();", Lang_CXX, "input0.cc");
2904 auto *FromNormalF =
2905 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2906 TranslationUnitDecl *FromFriendTU =
2907 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2908 auto *FromFriendF =
2909 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2910 auto FromNormalName = FromNormalF->getDeclName();
2911 auto FromFriendName = FromFriendF->getDeclName();
2912
2913 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2914 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2915 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2916 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2917 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2918 ASSERT_EQ(LookupRes.size(), 1u);
2919 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2920 ASSERT_EQ(LookupRes.size(), 1u);
2921
2922 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2923 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2924 auto ToName = ToNormalF->getDeclName();
2925 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2926 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2927 LookupRes = ToTU->noload_lookup(ToName);
2928 EXPECT_EQ(LookupRes.size(), 1u);
2929 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002930
Balazs Keri89632b82018-08-21 14:32:21 +00002931 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2932 LookupRes = ToTU->noload_lookup(ToName);
2933 EXPECT_EQ(LookupRes.size(), 1u);
2934 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2935
2936 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2937 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2938
2939 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2940 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2941}
2942
2943TEST_P(ImportFriendFunctions, ImportFriendList) {
2944 TranslationUnitDecl *FromTU = getTuDecl(
2945 "struct X { friend void f(); };"
2946 "void f();",
2947 Lang_CXX, "input0.cc");
2948 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2949 FromTU, functionDecl(hasName("f")));
2950
2951 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2952 FromTU, cxxRecordDecl(hasName("X")));
2953 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2954 auto FromFriends = FromClass->friends();
2955 unsigned int FrN = 0;
2956 for (auto Fr : FromFriends) {
2957 ASSERT_EQ(Fr, FromFriend);
2958 ++FrN;
2959 }
2960 ASSERT_EQ(FrN, 1u);
2961
2962 Import(FromFriendF, Lang_CXX);
2963 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2964 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2965 ToTU, cxxRecordDecl(hasName("X")));
2966 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2967 auto ToFriends = ToClass->friends();
2968 FrN = 0;
2969 for (auto Fr : ToFriends) {
2970 EXPECT_EQ(Fr, ToFriend);
2971 ++FrN;
2972 }
2973 EXPECT_EQ(FrN, 1u);
2974}
2975
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002976AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2977 InnerMatcher) {
2978 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2979 return InnerMatcher.matches(*Typedef, Finder, Builder);
2980 return false;
2981}
2982
Gabor Marton19f4f392018-06-25 13:04:37 +00002983TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002984 CodeFiles Samples{{"main.c",
2985 {"void foo();"
2986 "void moo();"
2987 "int main() { foo(); moo(); }",
2988 Lang_C}},
2989
2990 {"foo.c",
2991 {"typedef enum { THING_VALUE } thing_t;"
2992 "void conflict(thing_t type);"
2993 "void foo() { (void)THING_VALUE; }"
2994 "void conflict(thing_t type) {}",
2995 Lang_C}},
2996
2997 {"moo.c",
2998 {"typedef enum { THING_VALUE } thing_t;"
2999 "void conflict(thing_t type);"
3000 "void moo() { conflict(THING_VALUE); }",
3001 Lang_C}}};
3002
3003 auto VerificationMatcher =
3004 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
3005 hasTypedefForAnonDecl(hasName("thing_t")));
3006
3007 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
3008 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
3009
3010 testImportSequence(
3011 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
3012 // Just check that there is only one enum decl in the result AST.
3013 "main.c", enumDecl(), VerificationMatcher);
3014
3015 // For different import order, result should be the same.
3016 testImportSequence(
3017 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
3018 // Check that there is only one enum decl in the result AST.
3019 "main.c", enumDecl(), VerificationMatcher);
3020}
3021
Peter Szecsice7f3182018-05-07 12:08:27 +00003022const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
3023 dependentScopeDeclRefExpr;
3024
Gabor Marton19f4f392018-06-25 13:04:37 +00003025TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003026 MatchVerifier<Decl> Verifier;
3027 testImport("template <typename T> struct S { static T foo; };"
3028 "template <typename T> void declToImport() {"
3029 " (void) S<T>::foo;"
3030 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00003031 "void instantiate() { declToImport<int>(); }"
3032 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00003033 Lang_CXX11, "", Lang_CXX11, Verifier,
3034 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3035 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
3036
3037 testImport("template <typename T> struct S {"
3038 "template<typename S> static void foo(){};"
3039 "};"
3040 "template <typename T> void declToImport() {"
3041 " S<T>::template foo<T>();"
3042 "}"
3043 "void instantiate() { declToImport<int>(); }",
3044 Lang_CXX11, "", Lang_CXX11, Verifier,
3045 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3046 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
3047}
3048
3049const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
3050 dependentNameType;
3051
Gabor Marton19f4f392018-06-25 13:04:37 +00003052TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003053 MatchVerifier<Decl> Verifier;
3054 testImport("template <typename T> struct declToImport {"
3055 " typedef typename T::type dependent_name;"
3056 "};",
3057 Lang_CXX11, "", Lang_CXX11, Verifier,
3058 classTemplateDecl(has(
3059 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
3060}
3061
Gabor Marton19f4f392018-06-25 13:04:37 +00003062TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003063 MatchVerifier<Decl> Verifier;
3064 testImport("struct S { template <typename T> void mem(); };"
3065 "template <typename U> void declToImport() {"
3066 " S s;"
3067 " s.mem<U>();"
3068 "}"
3069 "void instantiate() { declToImport<int>(); }",
3070 Lang_CXX11, "", Lang_CXX11, Verifier,
3071 functionTemplateDecl(has(functionDecl(has(
3072 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3073}
3074
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003075class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00003076public:
3077 static constexpr auto DefaultCode = R"(
3078 struct A { int x; };
3079 void f() {
3080 A a;
3081 A a1(a);
3082 A a2(A{});
3083 a = a1;
3084 a = A{};
3085 a.~A();
3086 })";
3087
3088 template <typename MatcherType>
3089 void testImportOf(
3090 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3091 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3092 }
3093
3094 template <typename MatcherType>
3095 void testNoImportOf(
3096 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3097 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3098 }
3099
3100private:
3101 template <typename MatcherType>
3102 void test(const MatcherType &MethodMatcher,
3103 const char *Code, unsigned int ExpectedCount) {
3104 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3105
3106 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3107 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3108 ToTU, ClassMatcher);
3109
Balazs Keri2f752ba2018-07-16 14:05:18 +00003110 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003111
3112 {
3113 CXXMethodDecl *Method =
3114 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3115 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00003116 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003117 }
3118
Balazs Keri2f752ba2018-07-16 14:05:18 +00003119 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003120
3121 Decl *ImportedClass = nullptr;
3122 {
3123 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3124 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3125 FromTU, ClassMatcher);
3126 ImportedClass = Import(FromClass, Lang_CXX11);
3127 }
3128
3129 EXPECT_EQ(ToClass, ImportedClass);
3130 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3131 ExpectedCount);
3132 }
3133};
3134
3135TEST_P(ImportImplicitMethods, DefaultConstructor) {
3136 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3137}
3138
3139TEST_P(ImportImplicitMethods, CopyConstructor) {
3140 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3141}
3142
3143TEST_P(ImportImplicitMethods, MoveConstructor) {
3144 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3145}
3146
3147TEST_P(ImportImplicitMethods, Destructor) {
3148 testImportOf(cxxDestructorDecl());
3149}
3150
3151TEST_P(ImportImplicitMethods, CopyAssignment) {
3152 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3153}
3154
3155TEST_P(ImportImplicitMethods, MoveAssignment) {
3156 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3157}
3158
3159TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3160 auto Code = R"(
3161 struct A { A() { int x; } };
3162 )";
3163 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3164}
3165
3166TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3167 auto Code = R"(
3168 struct A { A() = default; };
3169 )";
3170 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3171}
3172
3173TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3174 auto Code = R"(
3175 struct A { A() = delete; };
3176 )";
3177 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3178}
3179
3180TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3181 auto Code = R"(
3182 struct A { void f() { } };
3183 )";
3184 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3185}
3186
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003187TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003188 Decl *ToR1;
3189 {
3190 Decl *FromTU = getTuDecl(
3191 "struct A { };", Lang_CXX, "input0.cc");
3192 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3193 FromTU, cxxRecordDecl(hasName("A")));
3194
3195 ToR1 = Import(FromR, Lang_CXX);
3196 }
3197
3198 Decl *ToR2;
3199 {
3200 Decl *FromTU = getTuDecl(
3201 "struct A { };", Lang_CXX, "input1.cc");
3202 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3203 FromTU, cxxRecordDecl(hasName("A")));
3204
3205 ToR2 = Import(FromR, Lang_CXX);
3206 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003207
Balazs Keric7797c42018-07-11 09:37:24 +00003208 EXPECT_EQ(ToR1, ToR2);
3209}
3210
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003211TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003212 Decl *ToR1;
3213 {
3214 Decl *FromTU = getTuDecl(
3215 "struct A { int x; };", Lang_CXX, "input0.cc");
3216 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3217 FromTU, cxxRecordDecl(hasName("A")));
3218 ToR1 = Import(FromR, Lang_CXX);
3219 }
3220 Decl *ToR2;
3221 {
3222 Decl *FromTU = getTuDecl(
3223 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3224 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3225 FromTU, cxxRecordDecl(hasName("A")));
3226 ToR2 = Import(FromR, Lang_CXX);
3227 }
3228 EXPECT_NE(ToR1, ToR2);
3229}
3230
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003231TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003232 Decl *ToF1;
3233 {
3234 Decl *FromTU = getTuDecl(
3235 "struct A { int x; };", Lang_CXX, "input0.cc");
3236 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3237 FromTU, fieldDecl(hasName("x")));
3238 ToF1 = Import(FromF, Lang_CXX);
3239 }
3240 Decl *ToF2;
3241 {
3242 Decl *FromTU = getTuDecl(
3243 "struct A { int x; };", Lang_CXX, "input1.cc");
3244 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3245 FromTU, fieldDecl(hasName("x")));
3246 ToF2 = Import(FromF, Lang_CXX);
3247 }
3248 EXPECT_EQ(ToF1, ToF2);
3249}
3250
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003251TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003252 Decl *ToF1;
3253 {
3254 Decl *FromTU = getTuDecl(
3255 "struct A { int x; };", Lang_CXX, "input0.cc");
3256 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3257 FromTU, fieldDecl(hasName("x")));
3258 ToF1 = Import(FromF, Lang_CXX);
3259 }
3260 Decl *ToF2;
3261 {
3262 Decl *FromTU = getTuDecl(
3263 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3264 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3265 FromTU, fieldDecl(hasName("x")));
3266 ToF2 = Import(FromF, Lang_CXX);
3267 }
3268 EXPECT_NE(ToF1, ToF2);
3269}
3270
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003271TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003272 Decl *ToM1;
3273 {
3274 Decl *FromTU = getTuDecl(
3275 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3276 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3277 FromTU, functionDecl(hasName("x"), isDefinition()));
3278 ToM1 = Import(FromM, Lang_CXX);
3279 }
3280 Decl *ToM2;
3281 {
3282 Decl *FromTU = getTuDecl(
3283 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3284 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3285 FromTU, functionDecl(hasName("x"), isDefinition()));
3286 ToM2 = Import(FromM, Lang_CXX);
3287 }
3288 EXPECT_EQ(ToM1, ToM2);
3289}
3290
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003291TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003292 Decl *ToM1;
3293 {
3294 Decl *FromTU = getTuDecl(
3295 "struct A { void x(); }; void A::x() { }",
3296 Lang_CXX, "input0.cc");
3297 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3298 FromTU, functionDecl(hasName("x"), isDefinition()));
3299 ToM1 = Import(FromM, Lang_CXX);
3300 }
3301 Decl *ToM2;
3302 {
3303 Decl *FromTU = getTuDecl(
3304 "struct A { void x() const; }; void A::x() const { }",
3305 Lang_CXX, "input1.cc");
3306 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3307 FromTU, functionDecl(hasName("x"), isDefinition()));
3308 ToM2 = Import(FromM, Lang_CXX);
3309 }
3310 EXPECT_NE(ToM1, ToM2);
3311}
3312
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003313TEST_P(ASTImporterOptionSpecificTestBase,
3314 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003315 Decl *FromTU = getTuDecl(
3316 R"(
3317 struct A {
3318 struct {
3319 struct A *next;
3320 } entry0;
3321 struct {
3322 struct A *next;
3323 } entry1;
3324 };
3325 )",
3326 Lang_C, "input0.cc");
3327 auto *From =
3328 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3329
3330 Import(From, Lang_C);
3331
3332 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3333 auto *Entry0 =
3334 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3335 auto *Entry1 =
3336 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3337 auto *R0 = getRecordDecl(Entry0);
3338 auto *R1 = getRecordDecl(Entry1);
3339 EXPECT_NE(R0, R1);
3340 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3341 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3342 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3343 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3344}
3345
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003346TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003347 Decl *FromTU = getTuDecl(
3348 R"(
3349 void f(int X, int Y, bool Z) {
3350 (void)[X, Y, Z] { (void)Z; };
3351 }
3352 )",
3353 Lang_CXX11, "input0.cc");
3354 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3355 FromTU, functionDecl(hasName("f")));
3356 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3357 EXPECT_TRUE(ToF);
3358
3359 CXXRecordDecl *FromLambda =
3360 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3361 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3362
3363 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3364 EXPECT_TRUE(ToLambda);
3365
3366 // Check if the fields of the lambda class are imported in correct order.
3367 unsigned FromIndex = 0u;
3368 for (auto *FromField : FromLambda->fields()) {
3369 ASSERT_FALSE(FromField->getDeclName());
3370 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3371 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003372 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3373 EXPECT_TRUE(ToIndex);
3374 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003375 ++FromIndex;
3376 }
3377
3378 EXPECT_EQ(FromIndex, 3u);
3379}
3380
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003381TEST_P(ASTImporterOptionSpecificTestBase,
3382 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003383 std::string ClassTemplate =
3384 R"(
3385 template <typename T>
3386 struct X {
3387 int a{0}; // FieldDecl with InitListExpr
3388 X(char) : a(3) {} // (1)
3389 X(int) {} // (2)
3390 };
3391 )";
3392 Decl *ToTU = getToTuDecl(ClassTemplate +
3393 R"(
3394 void foo() {
3395 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3396 X<char> xc('c');
3397 }
3398 )", Lang_CXX11);
3399 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3400 ToTU, classTemplateSpecializationDecl(hasName("X")));
3401 // FieldDecl without InitlistExpr:
3402 auto *ToField = *ToSpec->field_begin();
3403 ASSERT_TRUE(ToField);
3404 ASSERT_FALSE(ToField->getInClassInitializer());
3405 Decl *FromTU = getTuDecl(ClassTemplate +
3406 R"(
3407 void bar() {
3408 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3409 X<char> xc(1);
3410 }
3411 )", Lang_CXX11);
3412 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3413 FromTU, classTemplateSpecializationDecl(hasName("X")));
3414 // FieldDecl with InitlistExpr:
3415 auto *FromField = *FromSpec->field_begin();
3416 ASSERT_TRUE(FromField);
3417 ASSERT_TRUE(FromField->getInClassInitializer());
3418
3419 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3420 ASSERT_TRUE(ImportedSpec);
3421 EXPECT_EQ(ImportedSpec, ToSpec);
3422 // After the import, the FieldDecl has to be merged, thus it should have the
3423 // InitListExpr.
3424 EXPECT_TRUE(ToField->getInClassInitializer());
3425}
3426
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003427TEST_P(ASTImporterOptionSpecificTestBase,
3428 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003429 std::string ClassTemplate =
3430 R"(
3431 template <typename T>
3432 struct X {
3433 void f() {}
3434 void g() {}
3435 };
3436 )";
3437 Decl *ToTU = getToTuDecl(ClassTemplate +
3438 R"(
3439 void foo() {
3440 X<char> x;
3441 x.f();
3442 }
3443 )", Lang_CXX11);
3444 Decl *FromTU = getTuDecl(ClassTemplate +
3445 R"(
3446 void bar() {
3447 X<char> x;
3448 x.g();
3449 }
3450 )", Lang_CXX11);
3451 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3452 FromTU, classTemplateSpecializationDecl(hasName("X")));
3453 auto FunPattern = functionDecl(hasName("g"),
3454 hasParent(classTemplateSpecializationDecl()));
3455 auto *FromFun =
3456 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3457 auto *ToFun =
3458 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3459 ASSERT_TRUE(FromFun->hasBody());
3460 ASSERT_FALSE(ToFun->hasBody());
3461 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3462 ASSERT_TRUE(ImportedSpec);
3463 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3464 ToTU, classTemplateSpecializationDecl(hasName("X")));
3465 EXPECT_EQ(ImportedSpec, ToSpec);
3466 EXPECT_TRUE(ToFun->hasBody());
3467}
3468
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003469TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003470 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3471 std::string ClassTemplate =
3472 R"(
3473 template <typename T>
3474 struct X {};
3475 )";
3476 Decl *ToTU = getToTuDecl(ClassTemplate +
3477 R"(
3478 template <>
3479 struct X<char> {
3480 int a;
3481 };
3482 void foo() {
3483 X<char> x;
3484 }
3485 )",
3486 Lang_CXX11);
3487 Decl *FromTU = getTuDecl(ClassTemplate +
3488 R"(
3489 template <>
3490 struct X<char> {
3491 int b;
3492 };
3493 void foo() {
3494 X<char> x;
3495 }
3496 )",
3497 Lang_CXX11);
3498 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3499 FromTU, classTemplateSpecializationDecl(hasName("X")));
3500 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3501
3502 // We expect one (ODR) warning during the import.
3503 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3504
3505 // The second specialization is different from the first, thus it violates
3506 // ODR, consequently we expect to keep the first specialization only, which is
3507 // already in the "To" context.
3508 EXPECT_TRUE(ImportedSpec);
3509 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3510 ToTU, classTemplateSpecializationDecl(hasName("X")));
3511 EXPECT_EQ(ImportedSpec, ToSpec);
3512 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3513 ToTU, classTemplateSpecializationDecl()));
3514}
3515
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003516TEST_P(ASTImporterOptionSpecificTestBase,
3517 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003518 std::string ClassTemplate =
3519 R"(
3520 template <typename T>
3521 struct X {
3522 X(char) {}
3523 X(int) {}
3524 };
3525 )";
3526 Decl *ToTU = getToTuDecl(ClassTemplate +
3527 R"(
3528 void foo() {
3529 X<char> x('c');
3530 }
3531 )", Lang_CXX11);
3532 Decl *FromTU = getTuDecl(ClassTemplate +
3533 R"(
3534 void bar() {
3535 X<char> x(1);
3536 }
3537 )", Lang_CXX11);
3538 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3539 FromTU, classTemplateSpecializationDecl(hasName("X")));
3540 // Match the void(int) ctor.
3541 auto CtorPattern =
3542 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3543 hasParent(classTemplateSpecializationDecl()));
3544 auto *FromCtor =
3545 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3546 auto *ToCtor =
3547 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3548 ASSERT_TRUE(FromCtor->hasBody());
3549 ASSERT_FALSE(ToCtor->hasBody());
3550 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3551 ASSERT_TRUE(ImportedSpec);
3552 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3553 ToTU, classTemplateSpecializationDecl(hasName("X")));
3554 EXPECT_EQ(ImportedSpec, ToSpec);
3555 EXPECT_TRUE(ToCtor->hasBody());
3556}
3557
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003558TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003559 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3560 auto Code =
3561 R"(
3562 // primary template
3563 template<class T1, class T2, int I>
3564 class A {};
3565
3566 // partial specialization
3567 template<class T, int I>
3568 class A<T, T*, I> {};
3569 )";
3570 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3571 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3572 auto *FromSpec =
3573 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3574 FromTU, classTemplatePartialSpecializationDecl());
3575 auto *ToSpec =
3576 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3577 ToTU, classTemplatePartialSpecializationDecl());
3578
3579 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3580 EXPECT_EQ(ImportedSpec, ToSpec);
3581 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3582 ToTU, classTemplatePartialSpecializationDecl()));
3583}
3584
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003585TEST_P(ASTImporterOptionSpecificTestBase,
3586 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003587 auto Code =
3588 R"(
3589 // primary template
3590 template<class T1, class T2, int I>
3591 class A {};
3592
3593 // full specialization
3594 template<>
3595 class A<int, int, 1> {};
3596 )";
3597 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3598 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3599 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3600 FromTU, classTemplateSpecializationDecl());
3601 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3602 ToTU, classTemplateSpecializationDecl());
3603
3604 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3605 EXPECT_EQ(ImportedSpec, ToSpec);
3606 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3607 ToTU, classTemplateSpecializationDecl()));
3608}
3609
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003610TEST_P(ASTImporterOptionSpecificTestBase,
3611 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003612 std::string PrimaryTemplate =
3613 R"(
3614 template<class T1, class T2, int I>
3615 class A {};
3616 )";
3617 auto PartialSpec =
3618 R"(
3619 template<class T, int I>
3620 class A<T, T*, I> {};
3621 )";
3622 auto FullSpec =
3623 R"(
3624 template<>
3625 class A<int, int, 1> {};
3626 )";
3627 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3628 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3629 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3630 FromTU, classTemplateSpecializationDecl());
3631
3632 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3633 EXPECT_TRUE(ImportedSpec);
3634 // Check the number of partial specializations.
3635 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3636 ToTU, classTemplatePartialSpecializationDecl()));
3637 // Check the number of full specializations.
3638 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3639 ToTU, classTemplateSpecializationDecl(
3640 unless(classTemplatePartialSpecializationDecl()))));
3641}
3642
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003643TEST_P(ASTImporterOptionSpecificTestBase,
3644 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003645 Decl *TU = getTuDecl(
3646 R"(
3647 const int &init();
3648 void foo() { const int &a{init()}; }
3649 )", Lang_CXX11, "input0.cc");
3650 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3651 ASSERT_TRUE(FromD->getAnyInitializer());
3652 auto *InitExpr = FromD->getAnyInitializer();
3653 ASSERT_TRUE(InitExpr);
3654 ASSERT_TRUE(InitExpr->isGLValue());
3655
3656 auto *ToD = Import(FromD, Lang_CXX11);
3657 EXPECT_TRUE(ToD);
3658 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3659 EXPECT_TRUE(ToInitExpr);
3660 EXPECT_TRUE(ToInitExpr->isGLValue());
3661}
3662
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003663struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003664
3665TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3666 Decl *FromTU = getTuDecl(
3667 R"(
3668 struct A {
3669 static const int a = 1 + 2;
3670 };
3671 const int A::a;
3672 )", Lang_CXX, "input1.cc");
3673
3674 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3675 FromTU, varDecl(hasName("a"))); // Decl with init
3676 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3677 FromTU, varDecl(hasName("a"))); // Decl with definition
3678 ASSERT_NE(FromDWithInit, FromDWithDef);
3679 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3680
3681 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3682 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3683 ASSERT_TRUE(ToD0);
3684 ASSERT_TRUE(ToD1);
3685 EXPECT_NE(ToD0, ToD1);
3686 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3687}
3688
3689TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3690 auto StructA =
3691 R"(
3692 struct A {
3693 static const int a = 1 + 2;
3694 };
3695 )";
3696 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3697 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3698 "input1.cc");
3699
3700 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3701 FromTU, varDecl(hasName("a"))); // Decl with init
3702 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3703 FromTU, varDecl(hasName("a"))); // Decl with definition
3704 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3705 ASSERT_TRUE(FromDWithInit->getInit());
3706 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3707 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3708 ASSERT_FALSE(FromDWithDef->getInit());
3709
3710 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3711 ToTU, varDecl(hasName("a"))); // Decl with init
3712 ASSERT_TRUE(ToD->getInit());
3713 ASSERT_FALSE(ToD->getDefinition());
3714
3715 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3716 EXPECT_TRUE(ImportedD->getAnyInitializer());
3717 EXPECT_TRUE(ImportedD->getDefinition());
3718}
3719
3720TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3721 auto StructA =
3722 R"(
3723 struct A {
3724 static const int a;
3725 };
3726 )";
3727 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3728 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3729 Lang_CXX, "input1.cc");
3730
3731 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3732 FromTU, varDecl(hasName("a")));
3733 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3734 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3735 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3736 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3737 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3738 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3739 ASSERT_TRUE(FromDWithDef->getInit());
3740
3741 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3742 ToTU, varDecl(hasName("a")));
3743 ASSERT_FALSE(ToD->getInit());
3744 ASSERT_FALSE(ToD->getDefinition());
3745
3746 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3747 EXPECT_TRUE(ImportedD->getAnyInitializer());
3748 EXPECT_TRUE(ImportedD->getDefinition());
3749}
3750
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003751struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003752
Gabor Marton54058b52018-12-17 13:53:12 +00003753TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3754 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3755 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3756 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3757 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3758 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3759
3760 Decl *ImportedDef = Import(FromDef, Lang_C);
3761
3762 EXPECT_NE(ImportedDef, ToProto);
3763 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3764 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3765 EXPECT_TRUE(ImportedDef == ToDef);
3766 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3767 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3768 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3769}
3770
3771TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3772 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3773 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3774 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3775 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3776 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3777
3778 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3779
3780 EXPECT_NE(ImportedDef, ToProto);
3781 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3782 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3783 EXPECT_TRUE(ImportedDef == ToDef);
3784 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3785 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3786 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3787}
3788
3789TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3790 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3791 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3792 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3793 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3794 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3795
3796 Decl *ImportedProto = Import(FromProto, Lang_C);
3797 Decl *ImportedDef = Import(FromDef, Lang_C);
3798 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3799
3800 EXPECT_NE(ImportedDef, ImportedProto);
3801 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3802 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3803 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3804 EXPECT_TRUE(ImportedDef == ToDef);
3805 EXPECT_TRUE(ImportedProto == ToProto);
3806 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3807 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3808 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3809}
3810
Gabor Martonfc03fc62019-02-18 11:09:56 +00003811// FIXME put these structs and the tests rely on them into their own separate
3812// test file!
3813struct Function {
3814 using DeclTy = FunctionDecl;
3815 static constexpr auto *Prototype = "void X();";
3816 static constexpr auto *Definition = "void X() {}";
3817 BindableMatcher<Decl> getPattern() {
3818 return functionDecl(hasName("X"), unless(isImplicit()));
3819 }
3820};
Gabor Marton7df342a2018-12-17 12:42:12 +00003821
Gabor Martonfc03fc62019-02-18 11:09:56 +00003822struct Class {
3823 using DeclTy = CXXRecordDecl;
3824 static constexpr auto *Prototype = "class X;";
3825 static constexpr auto *Definition = "class X {};";
3826 BindableMatcher<Decl> getPattern() {
3827 return cxxRecordDecl(hasName("X"), unless(isImplicit()));
3828 }
3829};
Gabor Marton7df342a2018-12-17 12:42:12 +00003830
Gabor Martonfc03fc62019-02-18 11:09:56 +00003831struct Variable {
3832 using DeclTy = VarDecl;
3833 static constexpr auto *Prototype = "extern int X;";
3834 static constexpr auto *Definition = "int X;";
3835 BindableMatcher<Decl> getPattern() {
3836 return varDecl(hasName("X"));
3837 }
3838};
Gabor Marton7df342a2018-12-17 12:42:12 +00003839
Gabor Martonfc03fc62019-02-18 11:09:56 +00003840struct FunctionTemplate {
3841 using DeclTy = FunctionTemplateDecl;
3842 static constexpr auto *Prototype = "template <class T> void X();";
3843 static constexpr auto *Definition =
3844 R"(
3845 template <class T> void X() {};
3846 // Explicit instantiation is a must because of -fdelayed-template-parsing:
3847 template void X<int>();
3848 )";
3849 BindableMatcher<Decl> getPattern() {
3850 return functionTemplateDecl(hasName("X"), unless(isImplicit()));
3851 }
3852};
Gabor Marton7df342a2018-12-17 12:42:12 +00003853
Gabor Martonfc03fc62019-02-18 11:09:56 +00003854struct ClassTemplate {
3855 using DeclTy = ClassTemplateDecl;
3856 static constexpr auto *Prototype = "template <class T> class X;";
3857 static constexpr auto *Definition = "template <class T> class X {};";
3858 BindableMatcher<Decl> getPattern() {
3859 return classTemplateDecl(hasName("X"), unless(isImplicit()));
3860 }
3861};
Gabor Marton7df342a2018-12-17 12:42:12 +00003862
Gabor Martonfc03fc62019-02-18 11:09:56 +00003863struct FunctionTemplateSpec {
3864 using DeclTy = FunctionDecl;
3865 static constexpr auto *Prototype =
3866 R"(
3867 // Proto of the primary template.
3868 template <class T>
3869 void X();
3870 // Proto of the specialization.
3871 template <>
3872 void X<int>();
3873 )";
3874 static constexpr auto *Definition =
3875 R"(
3876 // Proto of the primary template.
3877 template <class T>
3878 void X();
3879 // Specialization and definition.
3880 template <>
3881 void X<int>() {}
3882 )";
3883 BindableMatcher<Decl> getPattern() {
3884 return functionDecl(hasName("X"), isExplicitTemplateSpecialization());
3885 }
3886};
Gabor Marton7df342a2018-12-17 12:42:12 +00003887
Gabor Martonfc03fc62019-02-18 11:09:56 +00003888template <typename TypeParam>
3889struct RedeclChain : ASTImporterOptionSpecificTestBase {
Gabor Marton7df342a2018-12-17 12:42:12 +00003890
Gabor Martonfc03fc62019-02-18 11:09:56 +00003891 using DeclTy = typename TypeParam::DeclTy;
3892 std::string getPrototype() { return TypeParam::Prototype; }
3893 std::string getDefinition() { return TypeParam::Definition; }
3894 BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); }
Gabor Marton7df342a2018-12-17 12:42:12 +00003895
Gabor Martonfc03fc62019-02-18 11:09:56 +00003896 void
3897 TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() {
3898 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX);
3899 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3900 ASSERT_FALSE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003901
Gabor Martonfc03fc62019-02-18 11:09:56 +00003902 Decl *ImportedD = Import(FromD, Lang_CXX);
3903 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003904
Gabor Martonfc03fc62019-02-18 11:09:56 +00003905 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
3906 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3907 EXPECT_TRUE(ImportedD == ToD);
3908 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
3909 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
3910 EXPECT_TRUE(ToT->getTemplatedDecl());
3911 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003912
Gabor Martonfc03fc62019-02-18 11:09:56 +00003913 void TypedTest_DefinitionShouldBeImportedAsADefinition() {
3914 Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
3915 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3916 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003917
Gabor Martonfc03fc62019-02-18 11:09:56 +00003918 Decl *ImportedD = Import(FromD, Lang_CXX);
3919 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003920
Gabor Martonfc03fc62019-02-18 11:09:56 +00003921 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
3922 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3923 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
3924 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
3925 EXPECT_TRUE(ToT->getTemplatedDecl());
3926 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003927
Gabor Martonfc03fc62019-02-18 11:09:56 +00003928 void TypedTest_ImportPrototypeAfterImportedPrototype() {
3929 Decl *FromTU = getTuDecl(
3930 getPrototype() + getPrototype(), Lang_CXX);
3931 auto *From0 =
3932 FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3933 auto *From1 = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
3934 ASSERT_FALSE(From0->isThisDeclarationADefinition());
3935 ASSERT_FALSE(From1->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003936
Gabor Martonfc03fc62019-02-18 11:09:56 +00003937 Decl *Imported0 = Import(From0, Lang_CXX);
3938 Decl *Imported1 = Import(From1, Lang_CXX);
3939 Decl *ToTU = Imported0->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003940
Gabor Martonfc03fc62019-02-18 11:09:56 +00003941 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
3942 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
3943 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3944 EXPECT_TRUE(Imported0 == To0);
3945 EXPECT_TRUE(Imported1 == To1);
3946 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3947 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3948 EXPECT_EQ(To1->getPreviousDecl(), To0);
3949 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0)) {
3950 auto *ToT1 = cast<TemplateDecl>(To1);
3951 ASSERT_TRUE(ToT0->getTemplatedDecl());
3952 ASSERT_TRUE(ToT1->getTemplatedDecl());
3953 EXPECT_EQ(ToT1->getTemplatedDecl()->getPreviousDecl(),
3954 ToT0->getTemplatedDecl());
3955 }
3956 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003957
Gabor Martonfc03fc62019-02-18 11:09:56 +00003958 void TypedTest_ImportDefinitionAfterImportedPrototype() {
3959 Decl *FromTU = getTuDecl(
3960 getPrototype() + getDefinition(), Lang_CXX);
3961 auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3962 auto *FromDef = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
3963 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
3964 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003965
Gabor Martonfc03fc62019-02-18 11:09:56 +00003966 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3967 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3968 Decl *ToTU = ImportedProto->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003969
Gabor Martonfc03fc62019-02-18 11:09:56 +00003970 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
3971 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
3972 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3973 EXPECT_TRUE(ImportedProto == ToProto);
3974 EXPECT_TRUE(ImportedDef == ToDef);
3975 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3976 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3977 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3978 if (auto *ToProtoT = dyn_cast<TemplateDecl>(ToProto)) {
3979 auto *ToDefT = cast<TemplateDecl>(ToDef);
3980 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
3981 ASSERT_TRUE(ToDefT->getTemplatedDecl());
3982 EXPECT_EQ(ToDefT->getTemplatedDecl()->getPreviousDecl(),
3983 ToProtoT->getTemplatedDecl());
3984 }
3985 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003986
Gabor Martonfc03fc62019-02-18 11:09:56 +00003987 void TypedTest_ImportPrototypeAfterImportedDefinition() {
3988 Decl *FromTU = getTuDecl(
3989 getDefinition() + getPrototype(), Lang_CXX);
3990 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3991 auto *FromProto = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
3992 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
3993 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003994
Gabor Martonfc03fc62019-02-18 11:09:56 +00003995 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3996 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3997 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3998
3999 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4000 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4001 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4002 EXPECT_TRUE(ImportedDef == ToDef);
4003 EXPECT_TRUE(ImportedProto == ToProto);
4004 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4005 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4006 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
4007 if (auto *ToDefT = dyn_cast<TemplateDecl>(ToDef)) {
4008 auto *ToProtoT = cast<TemplateDecl>(ToProto);
4009 ASSERT_TRUE(ToDefT->getTemplatedDecl());
4010 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
4011 EXPECT_EQ(ToProtoT->getTemplatedDecl()->getPreviousDecl(),
4012 ToDefT->getTemplatedDecl());
4013 }
4014 }
4015
4016 void TypedTest_ImportPrototypes() {
4017 Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4018 Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4019 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4020 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4021 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4022 ASSERT_FALSE(From1->isThisDeclarationADefinition());
4023
4024 Decl *Imported0 = Import(From0, Lang_CXX);
4025 Decl *Imported1 = Import(From1, Lang_CXX);
4026 Decl *ToTU = Imported0->getTranslationUnitDecl();
4027
4028 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4029 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4030 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4031 EXPECT_TRUE(Imported0 == To0);
4032 EXPECT_TRUE(Imported1 == To1);
4033 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4034 EXPECT_FALSE(To1->isThisDeclarationADefinition());
4035 EXPECT_EQ(To1->getPreviousDecl(), To0);
4036 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0)) {
4037 auto *ToT1 = cast<TemplateDecl>(To1);
4038 ASSERT_TRUE(ToT0->getTemplatedDecl());
4039 ASSERT_TRUE(ToT1->getTemplatedDecl());
4040 EXPECT_EQ(ToT1->getTemplatedDecl()->getPreviousDecl(),
4041 ToT0->getTemplatedDecl());
4042 }
4043 // Extra check for specializations.
4044 // FIXME Add this check to other tests too (possibly factor out into a
4045 // function), when they start to pass.
4046 if (auto *From0F = dyn_cast<FunctionDecl>(From0)) {
4047 auto *To0F = cast<FunctionDecl>(To0);
4048 if (From0F->getTemplatedKind() ==
4049 FunctionDecl::TK_FunctionTemplateSpecialization) {
4050 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4051 ToTU, functionTemplateDecl());
4052 auto *FirstSpecD = *(TemplateD->spec_begin());
4053 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0F->getCanonicalDecl());
4054 }
4055 }
4056 }
4057
4058 void TypedTest_ImportDefinitions() {
4059 Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4060 Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4061 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4062 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4063 ASSERT_TRUE(From0->isThisDeclarationADefinition());
4064 ASSERT_TRUE(From1->isThisDeclarationADefinition());
4065
4066 Decl *Imported0 = Import(From0, Lang_CXX);
4067 Decl *Imported1 = Import(From1, Lang_CXX);
4068 Decl *ToTU = Imported0->getTranslationUnitDecl();
4069
4070 EXPECT_EQ(Imported0, Imported1);
4071 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4072 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4073 EXPECT_TRUE(Imported0 == To0);
4074 EXPECT_TRUE(To0->isThisDeclarationADefinition());
4075 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0))
4076 EXPECT_TRUE(ToT0->getTemplatedDecl());
4077 }
4078
4079 void TypedTest_ImportDefinitionThenPrototype() {
4080 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4081 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4082 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4083 auto *FromProto =
4084 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4085 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4086 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4087
4088 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4089 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4090 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4091
4092 EXPECT_NE(ImportedDef, ImportedProto);
4093 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4094 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4095 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4096 EXPECT_TRUE(ImportedDef == ToDef);
4097 EXPECT_TRUE(ImportedProto == ToProto);
4098 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4099 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4100 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
4101 if (auto *ToDefT = dyn_cast<TemplateDecl>(ToDef)) {
4102 auto *ToProtoT = cast<TemplateDecl>(ToProto);
4103 ASSERT_TRUE(ToDefT->getTemplatedDecl());
4104 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
4105 EXPECT_EQ(ToProtoT->getTemplatedDecl()->getPreviousDecl(),
4106 ToDefT->getTemplatedDecl());
4107 }
4108 }
4109
4110 void TypedTest_ImportPrototypeThenDefinition() {
4111 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4112 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4113 auto *FromProto =
4114 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4115 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4116 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4117 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4118
4119 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4120 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4121 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4122
4123 EXPECT_NE(ImportedDef, ImportedProto);
4124 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4125 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4126 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4127 EXPECT_TRUE(ImportedDef == ToDef);
4128 EXPECT_TRUE(ImportedProto == ToProto);
4129 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4130 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4131 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4132 if (auto *ToDefT = dyn_cast<TemplateDecl>(ToDef)) {
4133 auto *ToProtoT = cast<TemplateDecl>(ToProto);
4134 ASSERT_TRUE(ToDefT->getTemplatedDecl());
4135 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
4136 EXPECT_EQ(ToDefT->getTemplatedDecl()->getPreviousDecl(),
4137 ToProtoT->getTemplatedDecl());
4138 }
4139 }
4140
4141 void TypedTest_WholeRedeclChainIsImportedAtOnce() {
4142 Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
4143 auto *FromD = // Definition
4144 LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4145 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
4146
4147 Decl *ImportedD = Import(FromD, Lang_CXX);
4148 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4149
4150 // The whole redecl chain is imported at once.
4151 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4152 EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition());
4153 }
4154
4155 void TypedTest_ImportPrototypeThenProtoAndDefinition() {
4156 {
4157 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4158 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4159 Import(FromD, Lang_CXX);
4160 }
4161 {
4162 Decl *FromTU =
4163 getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc");
4164 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4165 Import(FromD, Lang_CXX);
4166 }
4167
4168 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4169
4170 ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u);
4171 DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4172 EXPECT_FALSE(ProtoD->isThisDeclarationADefinition());
4173
4174 DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4175 EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition());
4176
4177 EXPECT_TRUE(DefinitionD->getPreviousDecl());
4178 EXPECT_FALSE(
4179 DefinitionD->getPreviousDecl()->isThisDeclarationADefinition());
4180 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
4181 }
4182};
4183
4184#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \
4185 NamePrefix, TestCase) \
4186 using BaseTemplate##TypeParam = BaseTemplate<TypeParam>; \
4187 TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \
4188 TypedTest_##TestCase(); \
4189 }
4190
4191ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4192 RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004193 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004194ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4195 RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004196 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004197ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4198 RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004199 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004200ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004201 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004202 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004203ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4204 RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004205 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004206ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4207 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004208 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004209
4210ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004211 RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004212ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004213 RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004214ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004215 RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004216ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton16d98c22019-03-07 13:01:51 +00004217 RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004218 DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004219ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004220 RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004221ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4222 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004223 DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004224
4225ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004226 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004227ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004228 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004229ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004230 ImportPrototypeAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004231ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004232 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004233ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004234 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004235ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004236 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004237
4238ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004239 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004240ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004241 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004242ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004243 ImportDefinitionAfterImportedPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004244ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004245 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004246ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004247 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004248ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004249 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004250
4251ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004252 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004253ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004254 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004255ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004256 ImportPrototypeAfterImportedDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004257ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004258 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004259ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004260 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004261ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004262 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004263
4264ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004265 ImportPrototypes)
Gabor Marton038100a2019-02-20 16:57:41 +00004266ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004267ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004268 ImportPrototypes)
Gabor Marton16d98c22019-03-07 13:01:51 +00004269ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4270 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004271ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004272 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004273// FIXME This does not pass, possible error with Spec import.
4274ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
Gabor Marton038100a2019-02-20 16:57:41 +00004275 DISABLED_, ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004276
4277ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004278 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004279ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004280 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004281ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004282 ImportDefinitions)
Gabor Marton16d98c22019-03-07 13:01:51 +00004283ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
4284 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004285ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004286 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004287// FIXME This does not pass, possible error with Spec import.
4288ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
Gabor Marton038100a2019-02-20 16:57:41 +00004289 DISABLED_, ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004290
4291ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004292 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004293ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004294 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004295ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004296 ImportDefinitionThenPrototype)
Gabor Marton16d98c22019-03-07 13:01:51 +00004297ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004298 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004299ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004300 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004301// FIXME This does not pass, possible error with Spec import.
4302ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4303 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004304 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004305
4306ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004307 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004308ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004309 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004310ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004311 ImportPrototypeThenDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004312ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004313 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004314ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004315 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004316// FIXME This does not pass, possible error with Spec import.
4317ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4318 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004319 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004320
4321ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004322 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004323ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004324 WholeRedeclChainIsImportedAtOnce)
Gabor Marton16d98c22019-03-07 13:01:51 +00004325ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004326 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004327ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004328 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004329
4330ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004331 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004332ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004333 ImportPrototypeThenProtoAndDefinition)
Gabor Marton16d98c22019-03-07 13:01:51 +00004334ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004335 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004336// FIXME This does not pass, possible error with Spec import.
4337ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4338 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004339 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004340
4341INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction,
4342 DefaultTestValuesForRunOptions, );
4343INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass,
4344 DefaultTestValuesForRunOptions, );
4345INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable,
4346 DefaultTestValuesForRunOptions, );
4347INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
4348 DefaultTestValuesForRunOptions, );
4349INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
4350 DefaultTestValuesForRunOptions, );
4351INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
4352 DefaultTestValuesForRunOptions, );
4353
4354
Gabor Marton7df342a2018-12-17 12:42:12 +00004355
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004356struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00004357
4358TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4359 Decl *FromTU = getTuDecl(
4360 R"(
4361 class A {
4362 template <int I> class F {};
4363 class X {
4364 template <int I> friend class F;
4365 };
4366 };
4367 )",
4368 Lang_CXX, "input0.cc");
4369
4370 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4371 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4372 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4373 FromTU, cxxRecordDecl(hasName("F")));
4374
4375 ASSERT_TRUE(FromClass);
4376 ASSERT_TRUE(FromFriendClass);
4377 ASSERT_NE(FromClass, FromFriendClass);
4378 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4379 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4380 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4381 FromClass->getDescribedClassTemplate());
4382
4383 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
4384 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
4385
4386 EXPECT_TRUE(ToClass);
4387 EXPECT_TRUE(ToFriendClass);
4388 EXPECT_NE(ToClass, ToFriendClass);
4389 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4390 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4391 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4392 ToClass->getDescribedClassTemplate());
4393}
4394
4395TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4396 Decl *FromTu = getTuDecl(
4397 R"(
4398 class declToImport {
4399 friend class declToImport;
4400 };
4401 )",
4402 Lang_CXX, "input.cc");
4403
4404 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4405 FromTu, cxxRecordDecl(hasName("declToImport")));
4406 auto *ToD = Import(FromD, Lang_CXX);
4407 auto Pattern = cxxRecordDecl(has(friendDecl()));
4408 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4409 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4410}
4411
4412TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4413 Decl *FromTu = getTuDecl(
4414 R"(
4415 template<class A> class declToImport {
4416 template<class A1> friend class declToImport;
4417 };
4418 )",
4419 Lang_CXX, "input.cc");
4420
4421 auto *FromD =
4422 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
4423 auto *ToD = Import(FromD, Lang_CXX);
4424
4425 auto Pattern = classTemplateDecl(
4426 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4427 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4428 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4429
4430 auto *Class =
4431 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
4432 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4433 EXPECT_NE(Friend->getFriendDecl(), Class);
4434 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
4435}
4436
4437TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4438 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
4439
4440 ClassTemplateSpecializationDecl *Imported1;
4441 {
4442 Decl *FromTU = getTuDecl("template<class T> class X;"
4443 "struct Y { friend class X<int>; };",
4444 Lang_CXX, "input0.cc");
4445 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4446 FromTU, Pattern);
4447
4448 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4449 }
4450 ClassTemplateSpecializationDecl *Imported2;
4451 {
4452 Decl *FromTU = getTuDecl("template<class T> class X;"
4453 "template<> class X<int>{};"
4454 "struct Z { friend class X<int>; };",
4455 Lang_CXX, "input1.cc");
4456 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4457 FromTU, Pattern);
4458
4459 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4460 }
4461
4462 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4463 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4464 2u);
4465 ASSERT_TRUE(Imported2->getPreviousDecl());
4466 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4467}
4468
4469TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4470 Decl *FromTU0 = getTuDecl(
4471 R"(
4472 class X {
4473 class Y;
4474 };
4475 class X::Y {
4476 template <typename T>
4477 friend class F; // The decl context of F is the global namespace.
4478 };
4479 )",
4480 Lang_CXX, "input0.cc");
4481 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4482 FromTU0, classTemplateDecl(hasName("F")));
4483 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4484 Decl *FromTU1 = getTuDecl(
4485 R"(
4486 template <typename T>
4487 class F {};
4488 )",
4489 Lang_CXX, "input1.cc");
4490 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4491 FromTU1, classTemplateDecl(hasName("F")));
4492 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4493 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4494 Imported1->getTemplatedDecl()->getTypeForDecl());
4495}
4496
4497TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4498 Decl *From, *To;
4499 std::tie(From, To) =
4500 getImportedDecl("class declToImport {};", Lang_CXX,
4501 "class Y { friend class declToImport; };", Lang_CXX);
4502 auto *Imported = cast<CXXRecordDecl>(To);
4503
4504 EXPECT_TRUE(Imported->getPreviousDecl());
4505}
4506
4507TEST_P(ImportFriendClasses,
4508 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4509 Decl *ToTU = getToTuDecl(
4510 R"(
4511 class X {
4512 class Y;
4513 };
4514 class X::Y {
4515 template <typename T>
4516 friend class F; // The decl context of F is the global namespace.
4517 };
4518 )",
4519 Lang_CXX);
4520 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4521 ToTU, classTemplateDecl(hasName("F")));
4522 Decl *FromTU = getTuDecl(
4523 R"(
4524 template <typename T>
4525 class F {};
4526 )",
4527 Lang_CXX, "input0.cc");
4528 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4529 FromTU, classTemplateDecl(hasName("F")));
4530 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4531 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4532 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4533 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4534 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4535}
4536
4537TEST_P(ImportFriendClasses,
4538 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4539 Decl *FromTU0 = getTuDecl(
4540 R"(
4541 class X {
4542 class Y;
4543 };
4544 class X::Y {
4545 template <typename T>
4546 friend class F; // The decl context of F is the global namespace.
4547 };
4548 )",
4549 Lang_CXX, "input0.cc");
4550 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4551 FromTU0, classTemplateDecl(hasName("F")));
4552 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4553 Decl *FromTU1 = getTuDecl(
4554 R"(
4555 template <typename T>
4556 class F {};
4557 )",
4558 Lang_CXX, "input1.cc");
4559 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4560 FromTU1, classTemplateDecl(hasName("F")));
4561 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4562 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4563 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4564 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4565 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4566}
4567
4568TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4569 Decl *FromTU0 = getTuDecl(
4570 R"(
4571 class X {
4572 class Y;
4573 };
4574 class X::Y {
4575 friend class F; // The decl context of F is the global namespace.
4576 };
4577 )",
4578 Lang_CXX, "input0.cc");
4579 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4580 QualType FT = Friend->getFriendType()->getType();
4581 FT = FromTU0->getASTContext().getCanonicalType(FT);
4582 auto *Fwd = cast<TagType>(FT)->getDecl();
4583 auto *ImportedFwd = Import(Fwd, Lang_CXX);
4584 Decl *FromTU1 = getTuDecl(
4585 R"(
4586 class F {};
4587 )",
4588 Lang_CXX, "input1.cc");
4589 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4590 FromTU1, cxxRecordDecl(hasName("F")));
4591 auto *ImportedDef = Import(Definition, Lang_CXX);
4592 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4593 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4594}
4595
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004596TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00004597 auto *Code = R"(
4598 template <class T>
4599 struct X {
4600 friend void foo(){}
4601 };
4602 )";
4603 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4604 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4605 ToTU, functionDecl(hasName("foo")));
4606
4607 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4608 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4609 FromTU, functionDecl(hasName("foo")));
4610 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4611 EXPECT_EQ(ImportedFoo, ToFoo);
4612}
4613
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004614struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00004615
4616TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4617 Decl *TU = getTuDecl(
4618 R"(
4619 namespace NS {
4620
4621 template <typename T>
4622 struct S {};
4623 template struct S<int>;
4624
4625 inline namespace INS {
4626 template <typename T>
4627 struct S {};
4628 template struct S<int>;
4629 }
4630
4631 }
4632 )", Lang_CXX11, "input0.cc");
4633 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4634 TU, namespaceDecl());
4635 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4636 TU, classTemplateSpecializationDecl());
4637 ASSERT_TRUE(NS->containsDecl(Spec));
4638
4639 NS->removeDecl(Spec);
4640 EXPECT_FALSE(NS->containsDecl(Spec));
4641}
4642
Gabor Marton7df342a2018-12-17 12:42:12 +00004643TEST_P(DeclContextTest,
4644 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4645 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4646 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4647 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4648
4649 // Investigate the list.
4650 auto *DC = A0->getDeclContext();
4651 ASSERT_TRUE(DC->containsDecl(A0));
4652 ASSERT_TRUE(DC->containsDecl(A1));
4653
4654 // Investigate the lookup table.
4655 auto *Map = DC->getLookupPtr();
4656 ASSERT_TRUE(Map);
4657 auto I = Map->find(A0->getDeclName());
4658 ASSERT_NE(I, Map->end());
4659 StoredDeclsList &L = I->second;
4660 // The lookup table contains the most recent decl of A.
4661 ASSERT_NE(L.getAsDecl(), A0);
4662 ASSERT_EQ(L.getAsDecl(), A1);
4663
4664 ASSERT_TRUE(L.getAsDecl());
4665 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4666 // The point here is to have a Vec with only one element, which is not the
4667 // one we are going to delete from the DC later.
4668 L.setHasExternalDecls();
4669 ASSERT_TRUE(L.getAsVector());
4670 ASSERT_EQ(1u, L.getAsVector()->size());
4671
4672 // This asserts in the old implementation.
4673 DC->removeDecl(A0);
4674 EXPECT_FALSE(DC->containsDecl(A0));
4675}
4676
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004677struct ImportFunctionTemplateSpecializations
4678 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004679
4680TEST_P(ImportFunctionTemplateSpecializations,
4681 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4682
4683 Decl *FromTU = getTuDecl(
4684 R"(
4685 template<class T>
4686 int f() { return 0; }
4687 void foo() { f<int>(); }
4688 )",
4689 Lang_CXX, "input0.cc");
4690
4691 // Check that the function template instantiation is NOT the child of the TU.
4692 auto Pattern = translationUnitDecl(
4693 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4694 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4695
4696 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4697 FromTU, functionDecl(hasName("foo")));
4698 ASSERT_TRUE(Import(Foo, Lang_CXX));
4699
4700 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4701 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4702}
4703
4704TEST_P(ImportFunctionTemplateSpecializations,
4705 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4706
4707 Decl *FromTU = getTuDecl(
4708 R"(
4709 template<class T>
4710 int f() { return 0; }
4711 template int f<int>();
4712 )",
4713 Lang_CXX, "input0.cc");
4714
4715 // Check that the function template instantiation is NOT the child of the TU.
4716 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4717 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4718 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4719
4720 ASSERT_TRUE(
4721 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4722
4723 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4724 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4725}
4726
4727TEST_P(ImportFunctionTemplateSpecializations,
4728 TUshouldContainFunctionTemplateSpecialization) {
4729
4730 Decl *FromTU = getTuDecl(
4731 R"(
4732 template<class T>
4733 int f() { return 0; }
4734 template <> int f<int>() { return 4; }
4735 )",
4736 Lang_CXX, "input0.cc");
4737
4738 // Check that the function template specialization is the child of the TU.
4739 auto Specialization =
4740 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4741 auto Pattern = translationUnitDecl(has(Specialization));
4742 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4743
4744 ASSERT_TRUE(
4745 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4746
4747 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4748 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4749}
4750
4751TEST_P(ImportFunctionTemplateSpecializations,
4752 FunctionTemplateSpecializationRedeclChain) {
4753
4754 Decl *FromTU = getTuDecl(
4755 R"(
4756 template<class T>
4757 int f() { return 0; }
4758 template <> int f<int>() { return 4; }
4759 )",
4760 Lang_CXX, "input0.cc");
4761
4762 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4763 hasParent(translationUnitDecl()));
4764 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4765 {
4766 auto *TU = FromTU;
4767 auto *SpecD = FromSpecD;
4768 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4769 TU, functionTemplateDecl());
4770 auto *FirstSpecD = *(TemplateD->spec_begin());
4771 ASSERT_EQ(SpecD, FirstSpecD);
4772 ASSERT_TRUE(SpecD->getPreviousDecl());
4773 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4774 ->doesThisDeclarationHaveABody());
4775 }
4776
4777 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4778
4779 {
4780 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4781 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4782 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4783 TU, functionTemplateDecl());
4784 auto *FirstSpecD = *(TemplateD->spec_begin());
4785 EXPECT_EQ(SpecD, FirstSpecD);
4786 ASSERT_TRUE(SpecD->getPreviousDecl());
4787 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4788 ->doesThisDeclarationHaveABody());
4789 }
4790}
4791
4792TEST_P(ImportFunctionTemplateSpecializations,
4793 MatchNumberOfFunctionTemplateSpecializations) {
4794
4795 Decl *FromTU = getTuDecl(
4796 R"(
4797 template <typename T> constexpr int f() { return 0; }
4798 template <> constexpr int f<int>() { return 4; }
4799 void foo() {
4800 static_assert(f<char>() == 0, "");
4801 static_assert(f<int>() == 4, "");
4802 }
4803 )",
4804 Lang_CXX11, "input0.cc");
4805 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4806 FromTU, functionDecl(hasName("foo")));
4807
4808 Import(FromD, Lang_CXX11);
4809 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4810 EXPECT_EQ(
4811 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4812 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4813}
4814
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004815TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004816 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4817 {
4818 Decl *FromTU = getTuDecl(
4819 R"(
4820 template <typename T>
4821 struct B;
4822 )",
4823 Lang_CXX, "input0.cc");
4824 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4825 FromTU, classTemplateDecl(hasName("B")));
4826
4827 Import(FromD, Lang_CXX);
4828 }
4829
4830 {
4831 Decl *FromTU = getTuDecl(
4832 R"(
4833 template <typename T>
4834 struct B {
4835 void f();
4836 B* b;
4837 };
4838 )",
4839 Lang_CXX, "input1.cc");
4840 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4841 FromTU, functionDecl(hasName("f")));
4842 Import(FromD, Lang_CXX);
4843 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4844 FromTU, classTemplateDecl(hasName("B")));
4845 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4846 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4847
4848 // We expect no (ODR) warning during the import.
4849 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4850 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4851 }
4852}
4853
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004854TEST_P(ASTImporterOptionSpecificTestBase,
4855 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004856 // We already have an incomplete underlying type in the "To" context.
4857 auto Code =
4858 R"(
4859 template <typename T>
4860 struct S {
4861 void foo();
4862 };
4863 using U = S<int>;
4864 )";
4865 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4866 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4867 typedefNameDecl(hasName("U")));
4868 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4869
4870 // The "From" context has the same typedef, but the underlying type is
4871 // complete this time.
4872 Decl *FromTU = getTuDecl(std::string(Code) +
4873 R"(
4874 void foo(U* u) {
4875 u->foo();
4876 }
4877 )", Lang_CXX11);
4878 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4879 typedefNameDecl(hasName("U")));
4880 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4881
4882 // The imported type should be complete.
4883 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4884 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4885}
4886
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004887struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004888
4889TEST_P(ASTImporterLookupTableTest, OneDecl) {
4890 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4891 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4892 ASTImporterLookupTable LT(*ToTU);
4893 auto Res = LT.lookup(ToTU, D->getDeclName());
4894 ASSERT_EQ(Res.size(), 1u);
4895 EXPECT_EQ(*Res.begin(), D);
4896}
4897
4898static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4899 for (Decl *D : DC->decls()) {
4900 if (auto *ND = dyn_cast<NamedDecl>(D))
4901 if (ND->getDeclName() == Name)
4902 return ND;
4903 }
4904 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004905}
Gabor Marton54058b52018-12-17 13:53:12 +00004906
4907TEST_P(ASTImporterLookupTableTest,
4908 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4909 auto *Code = R"(
4910 template <class T>
4911 struct X {
4912 friend void foo(){}
4913 };
4914 )";
4915 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4916 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4917 ToTU, classTemplateDecl(hasName("X")));
4918 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4919 ToTU, functionDecl(hasName("foo")));
4920 DeclContext *FooDC = Foo->getDeclContext();
4921 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4922 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4923 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4924 DeclarationName FooName = Foo->getDeclName();
4925
4926 // Cannot find in the LookupTable of its DC (TUDecl)
4927 SmallVector<NamedDecl *, 2> FoundDecls;
4928 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4929 EXPECT_EQ(FoundDecls.size(), 0u);
4930
4931 // Cannot find in the LookupTable of its LexicalDC (X)
4932 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4933 EXPECT_EQ(FoundDecls.size(), 0u);
4934
4935 // Can't find in the list of Decls of the DC.
4936 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4937
4938 // Can't find in the list of Decls of the LexicalDC
4939 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4940
4941 // ASTImporter specific lookup finds it.
4942 ASTImporterLookupTable LT(*ToTU);
4943 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4944 ASSERT_EQ(Res.size(), 1u);
4945 EXPECT_EQ(*Res.begin(), Foo);
4946}
4947
4948TEST_P(ASTImporterLookupTableTest,
4949 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4950 TranslationUnitDecl *ToTU =
4951 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4952 auto *Foo =
4953 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4954 auto *A =
4955 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4956 DeclContext *FooDC = Foo->getDeclContext();
4957 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4958 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4959 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4960 DeclarationName FooName = Foo->getDeclName();
4961
4962 // Cannot find in the LookupTable of its DC (TUDecl).
4963 SmallVector<NamedDecl *, 2> FoundDecls;
4964 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4965 EXPECT_EQ(FoundDecls.size(), 0u);
4966
4967 // Cannot find in the LookupTable of its LexicalDC (A).
4968 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4969 EXPECT_EQ(FoundDecls.size(), 0u);
4970
4971 // Can't find in the list of Decls of the DC.
4972 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4973
4974 // Can find in the list of Decls of the LexicalDC.
4975 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4976
4977 // ASTImporter specific lookup finds it.
4978 ASTImporterLookupTable LT(*ToTU);
4979 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4980 ASSERT_EQ(Res.size(), 1u);
4981 EXPECT_EQ(*Res.begin(), Foo);
4982}
4983
4984TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4985 TranslationUnitDecl *ToTU =
4986 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4987 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4988 .match(ToTU, varDecl(hasName("V")))
4989 ->getDeclName();
4990 auto *A =
4991 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4992 auto *B =
4993 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4994
4995 ASTImporterLookupTable LT(*ToTU);
4996
4997 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4998 ASSERT_EQ(Res.size(), 1u);
4999 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5000 ToTU, fieldDecl(hasName("V"),
5001 hasParent(recordDecl(hasName("A"))))));
5002 Res = LT.lookup(cast<DeclContext>(B), VName);
5003 ASSERT_EQ(Res.size(), 1u);
5004 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5005 ToTU, fieldDecl(hasName("V"),
5006 hasParent(recordDecl(hasName("B"))))));
5007 Res = LT.lookup(ToTU, VName);
5008 ASSERT_EQ(Res.size(), 1u);
5009 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
5010 ToTU, varDecl(hasName("V"),
5011 hasParent(translationUnitDecl()))));
5012}
5013
5014TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5015 TranslationUnitDecl *ToTU = getToTuDecl(
5016 R"(
5017 void foo();
5018 void foo(int);
5019 void foo(int, int);
5020 )",
5021 Lang_CXX);
5022
5023 ASTImporterLookupTable LT(*ToTU);
5024 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5025 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5026 DeclarationName Name = F0->getDeclName();
5027 auto Res = LT.lookup(ToTU, Name);
5028 EXPECT_EQ(Res.size(), 3u);
5029 EXPECT_EQ(Res.count(F0), 1u);
5030 EXPECT_EQ(Res.count(F2), 1u);
5031}
5032
Gabor Martona9cab312019-02-08 09:19:34 +00005033TEST_P(ASTImporterLookupTableTest,
5034 DifferentOperatorsShouldHaveDifferentResultSet) {
5035 TranslationUnitDecl *ToTU = getToTuDecl(
5036 R"(
5037 struct X{};
5038 void operator+(X, X);
5039 void operator-(X, X);
5040 )",
5041 Lang_CXX);
5042
5043 ASTImporterLookupTable LT(*ToTU);
5044 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5045 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5046 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5047 ToTU, functionDecl(hasOverloadedOperatorName("-")));
5048 DeclarationName NamePlus = FPlus->getDeclName();
5049 auto ResPlus = LT.lookup(ToTU, NamePlus);
5050 EXPECT_EQ(ResPlus.size(), 1u);
5051 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5052 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5053 DeclarationName NameMinus = FMinus->getDeclName();
5054 auto ResMinus = LT.lookup(ToTU, NameMinus);
5055 EXPECT_EQ(ResMinus.size(), 1u);
5056 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5057 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5058 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5059}
5060
5061TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5062 TranslationUnitDecl *ToTU = getToTuDecl(
5063 R"(
5064 struct X {};
5065 void operator+(X, X);
5066 )",
5067 Lang_CXX);
5068 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5069 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5070
5071 Decl *FromTU = getTuDecl(
5072 R"(
5073 struct X {};
5074 void operator+(X, X);
5075 )",
5076 Lang_CXX);
5077 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5078 FromTU, functionDecl(hasOverloadedOperatorName("+")));
5079
5080 // FromPlus have a different TU, thus its DeclarationName is different too.
5081 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5082
5083 ASTImporterLookupTable LT(*ToTU);
5084 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
5085 ASSERT_EQ(Res.size(), 1u);
5086 EXPECT_EQ(*Res.begin(), ToPlus);
5087
5088 // FromPlus have a different TU, thus its DeclarationName is different too.
5089 Res = LT.lookup(ToTU, FromPlus->getDeclName());
5090 ASSERT_EQ(Res.size(), 0u);
5091}
5092
Gabor Marton54058b52018-12-17 13:53:12 +00005093static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
5094 QualType Ty = FD->getFriendType()->getType();
5095 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
5096 return cast<RecordType>(NamedTy)->getDecl();
5097}
5098
5099TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
5100 TranslationUnitDecl *ToTU = getToTuDecl(
5101 R"(
5102 class Y { friend class F; };
5103 )",
5104 Lang_CXX);
5105
5106 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5107 // So we must dig up the underlying CXXRecordDecl.
5108 ASTImporterLookupTable LT(*ToTU);
5109 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5110 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5111 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5112 ToTU, cxxRecordDecl(hasName("Y")));
5113
5114 DeclarationName Name = RD->getDeclName();
5115 auto Res = LT.lookup(ToTU, Name);
5116 EXPECT_EQ(Res.size(), 1u);
5117 EXPECT_EQ(*Res.begin(), RD);
5118
5119 Res = LT.lookup(Y, Name);
5120 EXPECT_EQ(Res.size(), 0u);
5121}
5122
5123TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5124 TranslationUnitDecl *ToTU = getToTuDecl(
5125 R"(
5126 class Y { template <class T> friend class F; };
5127 )",
5128 Lang_CXX);
5129
5130 ASTImporterLookupTable LT(*ToTU);
5131 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5132 ToTU, classTemplateDecl(hasName("F")));
5133 DeclarationName Name = F->getDeclName();
5134 auto Res = LT.lookup(ToTU, Name);
5135 EXPECT_EQ(Res.size(), 2u);
5136 EXPECT_EQ(Res.count(F), 1u);
5137 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5138}
5139
5140TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5141 TranslationUnitDecl *ToTU = getToTuDecl(
5142 R"(
5143 template <typename T>
5144 class F;
5145
5146 template <typename T>
5147 class Y {
5148 friend class F<T>;
5149 };
5150 )",
5151 Lang_CXX);
5152
5153 ASTImporterLookupTable LT(*ToTU);
5154 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5155 ToTU, classTemplateDecl(hasName("F")));
5156 DeclarationName Name = F->getDeclName();
5157 auto Res = LT.lookup(ToTU, Name);
5158 EXPECT_EQ(Res.size(), 2u);
5159 EXPECT_EQ(Res.count(F), 1u);
5160 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5161}
5162
5163TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
5164 TranslationUnitDecl *ToTU = getToTuDecl(
5165 R"(
5166 template <typename T>
5167 class F;
5168
5169 class Y {
5170 friend class F<int>;
5171 };
5172 )",
5173 Lang_CXX);
5174
5175 ASTImporterLookupTable LT(*ToTU);
5176 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5177 ToTU, classTemplateDecl(hasName("F")));
5178 DeclarationName Name = F->getDeclName();
5179 auto Res = LT.lookup(ToTU, Name);
5180 ASSERT_EQ(Res.size(), 3u);
5181 EXPECT_EQ(Res.count(F), 1u);
5182 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5183 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
5184}
5185
5186TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
5187 TranslationUnitDecl *ToTU = getToTuDecl(
5188 R"(
5189 class Y { friend void F(); };
5190 )",
5191 Lang_CXX);
5192
5193 ASTImporterLookupTable LT(*ToTU);
5194 auto *F =
5195 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
5196 DeclarationName Name = F->getDeclName();
5197 auto Res = LT.lookup(ToTU, Name);
5198 EXPECT_EQ(Res.size(), 1u);
5199 EXPECT_EQ(*Res.begin(), F);
5200}
5201
5202TEST_P(ASTImporterLookupTableTest,
5203 LookupFindsDeclsInClassTemplateSpecialization) {
5204 TranslationUnitDecl *ToTU = getToTuDecl(
5205 R"(
5206 template <typename T>
5207 struct X {
5208 int F;
5209 };
5210 void foo() {
5211 X<char> xc;
5212 }
5213 )",
5214 Lang_CXX);
5215
5216 ASTImporterLookupTable LT(*ToTU);
5217
5218 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
5219 ToTU, classTemplateDecl(hasName("X")));
5220 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
5221 ToTU,
5222 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
5223
5224 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5225 ToTU, classTemplateSpecializationDecl(hasName("X")));
5226 FieldDecl *FieldInSpec = *Spec->field_begin();
5227 ASSERT_TRUE(FieldInSpec);
5228
5229 DeclarationName Name = FieldInSpec->getDeclName();
5230 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
5231
5232 SmallVector<NamedDecl *, 2> FoundDecls;
5233 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
5234 EXPECT_EQ(FoundDecls.size(), 1u);
5235 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
5236
5237 auto Res = LT.lookup(TemplateDC, Name);
5238 ASSERT_EQ(Res.size(), 1u);
5239 EXPECT_EQ(*Res.begin(), FieldInTemplate);
5240
5241 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
5242 FoundDecls);
5243 EXPECT_EQ(FoundDecls.size(), 1u);
5244 EXPECT_EQ(FoundDecls[0], FieldInSpec);
5245
5246 Res = LT.lookup(cast<DeclContext>(Spec), Name);
5247 ASSERT_EQ(Res.size(), 1u);
5248 EXPECT_EQ(*Res.begin(), FieldInSpec);
5249}
5250
5251TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
5252 TranslationUnitDecl *ToTU = getToTuDecl(
5253 R"(
5254 class Y { template <class T> friend void F(); };
5255 )",
5256 Lang_CXX);
5257
5258 ASTImporterLookupTable LT(*ToTU);
5259 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
5260 ToTU, functionTemplateDecl(hasName("F")));
5261 DeclarationName Name = F->getDeclName();
5262 auto Res = LT.lookup(ToTU, Name);
5263 EXPECT_EQ(Res.size(), 2u);
5264 EXPECT_EQ(Res.count(F), 1u);
5265 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5266}
5267
5268TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
5269 TranslationUnitDecl *ToTU = getToTuDecl(
5270 R"(
5271 struct X;
5272 struct A {
5273 friend struct X;
5274 };
5275 struct B {
5276 friend struct X;
5277 };
5278 )",
5279 Lang_CXX);
5280
5281 ASTImporterLookupTable LT(*ToTU);
5282 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
5283 ToTU, cxxRecordDecl(hasName("X")));
5284 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5285 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5286 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
5287 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
5288 ASSERT_EQ(RD0, RD1);
5289 ASSERT_EQ(RD1, X);
5290
5291 DeclarationName Name = X->getDeclName();
5292 auto Res = LT.lookup(ToTU, Name);
5293 EXPECT_EQ(Res.size(), 1u);
5294 EXPECT_EQ(*Res.begin(), X);
5295}
5296
5297TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
5298 TranslationUnitDecl *ToTU = getToTuDecl(
5299 R"(
5300 enum E {
5301 A,
5302 B
5303 };
5304 )",
5305 Lang_C);
5306
5307 ASTImporterLookupTable LT(*ToTU);
5308 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
5309 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
5310 ToTU, enumConstantDecl(hasName("A")));
5311
5312 DeclarationName Name = A->getDeclName();
5313 // Redecl context is the TU.
5314 ASSERT_EQ(E->getRedeclContext(), ToTU);
5315
5316 SmallVector<NamedDecl *, 2> FoundDecls;
5317 // Normal lookup finds in the DC.
5318 E->localUncachedLookup(Name, FoundDecls);
5319 EXPECT_EQ(FoundDecls.size(), 1u);
5320
5321 // Normal lookup finds in the Redecl context.
5322 ToTU->localUncachedLookup(Name, FoundDecls);
5323 EXPECT_EQ(FoundDecls.size(), 1u);
5324
5325 // Import specific lookup finds in the DC.
5326 auto Res = LT.lookup(E, Name);
5327 ASSERT_EQ(Res.size(), 1u);
5328 EXPECT_EQ(*Res.begin(), A);
5329
5330 // Import specific lookup finds in the Redecl context.
5331 Res = LT.lookup(ToTU, Name);
5332 ASSERT_EQ(Res.size(), 1u);
5333 EXPECT_EQ(*Res.begin(), A);
5334}
5335
5336TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
5337 TranslationUnitDecl *ToTU = getToTuDecl(
5338 R"(
5339 namespace N {
5340 int A;
5341 }
5342 namespace N {
5343 }
5344 )",
5345 Lang_CXX);
5346 auto *N1 =
5347 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
5348 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
5349 DeclarationName Name = A->getDeclName();
5350
5351 ASTImporterLookupTable LT(*ToTU);
5352 auto Res = LT.lookup(N1, Name);
5353 ASSERT_EQ(Res.size(), 1u);
5354 EXPECT_EQ(*Res.begin(), A);
5355}
5356
Gabor Marton19f4f392018-06-25 13:04:37 +00005357INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5358 ::testing::Values(ArgVector()), );
5359
Gabor Marton5254e642018-06-27 13:32:50 +00005360INSTANTIATE_TEST_CASE_P(
5361 ParameterizedTests, CanonicalRedeclChain,
5362 ::testing::Values(ArgVector()),);
5363
Gabor Marton0e04ebd2019-02-11 10:27:58 +00005364// FIXME This test is disabled currently, upcoming patches will make it
5365// possible to enable.
5366TEST_P(ASTImporterOptionSpecificTestBase,
5367 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
5368 Decl *FromTU = getTuDecl(
5369 R"(
5370 namespace NS {
5371 struct X;
5372 struct Y {
5373 static const int I = 3;
5374 };
5375 }
5376 namespace NS {
5377 struct X { // <--- To be imported
5378 void method(int i = Y::I) {}
5379 int f;
5380 };
5381 }
5382 )",
5383 Lang_CXX);
5384 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5385 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5386 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
5387 FromTU,
5388 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
5389 ASSERT_NE(FromFwd, FromDef);
5390 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
5391 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
5392 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
5393
5394 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
5395 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
5396 EXPECT_NE(ToFwd, ToDef);
5397 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
5398 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
5399 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
5400 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5401 // We expect no (ODR) warning during the import.
5402 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5403}
5404
Gabor Martone331e632019-02-18 13:09:27 +00005405struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
5406
5407TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
5408 Decl *ToTU = getToTuDecl(
5409 R"(
5410 class X {
5411 template <typename T> friend void foo();
5412 };
5413 )",
5414 Lang_CXX);
5415 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
5416 ToTU, functionTemplateDecl(hasName("foo")));
5417
5418 Decl *FromTU = getTuDecl(
5419 R"(
5420 template <typename T> void foo();
5421 )",
5422 Lang_CXX);
5423 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
5424 FromTU, functionTemplateDecl(hasName("foo")));
5425 auto *Imported = Import(FromFoo, Lang_CXX);
5426
Gabor Marton16d98c22019-03-07 13:01:51 +00005427 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00005428}
5429
Gabor Marton54058b52018-12-17 13:53:12 +00005430INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5431 DefaultTestValuesForRunOptions, );
5432
Gabor Marton19f4f392018-06-25 13:04:37 +00005433INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5434 DefaultTestValuesForRunOptions, );
5435
5436INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5437 DefaultTestValuesForRunOptions, );
5438
5439INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5440 DefaultTestValuesForRunOptions, );
5441
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005442INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005443 DefaultTestValuesForRunOptions, );
5444
5445INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5446 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005447
Gabor Martone331e632019-02-18 13:09:27 +00005448INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5449 DefaultTestValuesForRunOptions, );
5450
Gabor Marton54058b52018-12-17 13:53:12 +00005451INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005452 DefaultTestValuesForRunOptions, );
5453
Gabor Marton54058b52018-12-17 13:53:12 +00005454INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005455 DefaultTestValuesForRunOptions, );
5456
Gabor Marton7df342a2018-12-17 12:42:12 +00005457INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5458 DefaultTestValuesForRunOptions, );
5459
Gabor Marton5254e642018-06-27 13:32:50 +00005460INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5461 ImportFunctionTemplateSpecializations,
5462 DefaultTestValuesForRunOptions, );
5463
Gabor Martonac3a5d62018-09-17 12:04:52 +00005464INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5465 DefaultTestValuesForRunOptions, );
5466
5467INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5468 DefaultTestValuesForRunOptions, );
5469
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005470} // end namespace ast_matchers
5471} // end namespace clang