blob: fa5384503df5469631481eb4f85ebdf05852fc9a [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
Gabor Marton19f4f392018-06-25 13:04:37 +0000566TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000567 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000568 testImport(
569 "void declToImport() { (void)__null; }",
570 Lang_CXX, "", Lang_CXX, Verifier,
571 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000572}
573
Gabor Marton19f4f392018-06-25 13:04:37 +0000574TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000575 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000576 testImport(
577 "void declToImport() { (void)nullptr; }",
578 Lang_CXX11, "", Lang_CXX11, Verifier,
579 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000580}
581
582
Gabor Marton19f4f392018-06-25 13:04:37 +0000583TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000584 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000585 testImport(
586 "void declToImport() { (void)1.0; }",
587 Lang_C, "", Lang_C, Verifier,
588 functionDecl(hasDescendant(
589 floatLiteral(equals(1.0), hasType(asString("double"))))));
590 testImport(
591 "void declToImport() { (void)1.0e-5f; }",
592 Lang_C, "", Lang_C, Verifier,
593 functionDecl(hasDescendant(
594 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000595}
596
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000597TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
598 MatchVerifier<Decl> Verifier;
599 testImport(
600 "void declToImport() { (void)1.0i; }",
601 Lang_CXX14, "", Lang_CXX14, Verifier,
602 functionDecl(hasDescendant(imaginaryLiteral())));
603}
604
Gabor Marton19f4f392018-06-25 13:04:37 +0000605TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000606 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000607 testImport(
608 "void declToImport() {"
609 " struct s { int x; long y; unsigned z; }; "
610 " (void)(struct s){ 42, 0L, 1U }; }",
611 Lang_CXX, "", Lang_CXX, Verifier,
612 functionDecl(hasDescendant(
613 compoundLiteralExpr(
614 hasType(asString("struct s")),
615 has(initListExpr(
616 hasType(asString("struct s")),
617 has(integerLiteral(
618 equals(42), hasType(asString("int")))),
619 has(integerLiteral(
620 equals(0), hasType(asString("long")))),
621 has(integerLiteral(
622 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000623}
624
Gabor Marton19f4f392018-06-25 13:04:37 +0000625TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000626 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000627 testImport(
628 "class declToImport { void f() { (void)this; } };",
629 Lang_CXX, "", Lang_CXX, Verifier,
630 cxxRecordDecl(
631 hasMethod(
632 hasDescendant(
633 cxxThisExpr(
634 hasType(
635 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000636}
637
Gabor Marton19f4f392018-06-25 13:04:37 +0000638TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000639 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000640 testImport(
641 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
642 Lang_C, "", Lang_C, Verifier,
643 functionDecl(hasDescendant(
644 atomicExpr(
645 has(ignoringParenImpCasts(
646 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
647 hasType(asString("int *"))))),
648 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000649}
650
Gabor Marton19f4f392018-06-25 13:04:37 +0000651TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000652 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000653 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000654 "void declToImport() { loop: goto loop; (void)&&loop; }",
655 Lang_C, "", Lang_C, Verifier,
656 functionDecl(
657 hasDescendant(
658 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
659 hasDescendant(
660 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000661}
662
663AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
664 internal::Matcher<NamedDecl>, InnerMatcher) {
665 const NamedDecl *Template = Node.getTemplatedDecl();
666 return Template && InnerMatcher.matches(*Template, Finder, Builder);
667}
668
Gabor Marton19f4f392018-06-25 13:04:37 +0000669TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000670 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000671 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000672 "template<typename T> class dummy { void f() { dummy X(*this); } };"
673 "typedef dummy<int> declToImport;"
674 "template class dummy<int>;",
675 Lang_CXX, "", Lang_CXX, Verifier,
676 typedefDecl(hasType(templateSpecializationType(
677 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
678 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
679 hasName("f"),
680 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
681 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
682 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000683 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000684}
685
Gabor Marton19f4f392018-06-25 13:04:37 +0000686TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000687 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000688 testImport(
689 "void declToImport() { int b; switch (b) { case 1: break; } }",
690 Lang_C, "", Lang_C, Verifier,
691 functionDecl(hasDescendant(
692 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000693}
694
Gabor Marton19f4f392018-06-25 13:04:37 +0000695TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000696 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000697 testImport(
698 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
699 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000700 functionDecl(hasDescendant(
701 varDecl(
702 hasName("C"),
703 hasType(asString("int")),
704 hasInitializer(
705 stmtExpr(
706 hasAnySubstatement(declStmt(hasSingleDecl(
707 varDecl(
708 hasName("X"),
709 hasType(asString("int")),
710 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000711 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000712 hasDescendant(
713 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000714}
715
Gabor Marton19f4f392018-06-25 13:04:37 +0000716TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000717 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000718 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000719 "void declToImport() { (void)(true ? 1 : -5); }",
720 Lang_CXX, "", Lang_CXX, Verifier,
721 functionDecl(hasDescendant(
722 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000723 hasCondition(cxxBoolLiteral(equals(true))),
724 hasTrueExpression(integerLiteral(equals(1))),
725 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000726 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
727 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000728}
729
Gabor Marton19f4f392018-06-25 13:04:37 +0000730TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000731 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000732 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000733 "void declToImport() { (void)(1 ?: -5); }",
734 Lang_CXX, "", Lang_CXX, Verifier,
735 functionDecl(hasDescendant(
736 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000737 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000738 implicitCastExpr(
739 hasSourceExpression(opaqueValueExpr(
740 hasSourceExpression(integerLiteral(equals(1))))),
741 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000742 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000743 opaqueValueExpr(
744 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000745 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000746 unaryOperator(
747 hasOperatorName("-"),
748 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000749}
750
Gabor Marton19f4f392018-06-25 13:04:37 +0000751TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000752 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000753 testImport(
754 "void declToImport() {"
755 " struct point { double x; double y; };"
756 " struct point ptarray[10] = "
757 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
758 Lang_C, "", Lang_C, Verifier,
759 functionDecl(hasDescendant(
760 initListExpr(
761 has(designatedInitExpr(
762 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000763 hasDescendant(floatLiteral(equals(1.0))),
764 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000765 has(designatedInitExpr(
766 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000767 hasDescendant(floatLiteral(equals(2.0))),
768 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000769 has(designatedInitExpr(
770 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000771 hasDescendant(floatLiteral(equals(1.0))),
772 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000773}
774
Gabor Marton19f4f392018-06-25 13:04:37 +0000775TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000776 MatchVerifier<Decl> Verifier;
777 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000778 testImport(
779 "void declToImport() { (void)__func__; }",
780 Lang_CXX, "", Lang_CXX, Verifier,
781 functionDecl(hasDescendant(
782 predefinedExpr(
783 hasType(
784 asString("const char [13]")),
785 has(stringLiteral(hasType(
786 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000787}
788
Gabor Marton19f4f392018-06-25 13:04:37 +0000789TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000790 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000791 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000792 "void declToImport() {"
793 " struct point { double x; double y; };"
794 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
795 " [0].x = 1.0 }; }",
796 Lang_CXX, "", Lang_CXX, Verifier,
797 functionDecl(hasDescendant(
798 initListExpr(
799 has(
800 cxxConstructExpr(
801 requiresZeroInitialization())),
802 has(
803 initListExpr(
804 hasType(asString("struct point")),
805 has(floatLiteral(equals(1.0))),
806 has(implicitValueInitExpr(
807 hasType(asString("double")))))),
808 has(
809 initListExpr(
810 hasType(asString("struct point")),
811 has(floatLiteral(equals(2.0))),
812 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000813}
814
815
Aleksei Sidorina693b372016-09-28 10:16:56 +0000816const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
817
Gabor Marton19f4f392018-06-25 13:04:37 +0000818TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000819 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000820 testImport(
821 "void declToImport(__builtin_va_list list, ...) {"
822 " (void)__builtin_va_arg(list, int); }",
823 Lang_CXX, "", Lang_CXX, Verifier,
824 functionDecl(hasDescendant(
825 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000826}
827
Gabor Marton19f4f392018-06-25 13:04:37 +0000828TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000829 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000830 testImport(
831 "struct C {};"
832 "void declToImport() { C c = C(); }",
833 Lang_CXX, "", Lang_CXX, Verifier,
834 functionDecl(hasDescendant(
835 exprWithCleanups(has(cxxConstructExpr(
836 has(materializeTemporaryExpr(has(implicitCastExpr(
837 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000838}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000839
Gabor Marton19f4f392018-06-25 13:04:37 +0000840TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000841 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000842 testImport(
843 "void declToImport() { typedef _Atomic(int) a_int; }",
844 Lang_CXX11, "", Lang_CXX11, Verifier,
845 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000846}
847
Gabor Marton19f4f392018-06-25 13:04:37 +0000848TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000849 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000850 testImport(
851 "template <typename T> void declToImport() { };",
852 Lang_CXX, "", Lang_CXX, Verifier,
853 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000854}
855
Gabor Marton19f4f392018-06-25 13:04:37 +0000856TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000857 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000858 testImport(
859 "template <typename T> struct C { T t; };"
860 "template <typename T> void declToImport() {"
861 " C<T> d;"
862 " (void)d.t;"
863 "}"
864 "void instantiate() { declToImport<int>(); }",
865 Lang_CXX, "", Lang_CXX, Verifier,
866 functionTemplateDecl(hasDescendant(
867 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
868 testImport(
869 "template <typename T> struct C { T t; };"
870 "template <typename T> void declToImport() {"
871 " C<T> d;"
872 " (void)(&d)->t;"
873 "}"
874 "void instantiate() { declToImport<int>(); }",
875 Lang_CXX, "", Lang_CXX, Verifier,
876 functionTemplateDecl(hasDescendant(
877 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000878}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000879
Gabor Marton19f4f392018-06-25 13:04:37 +0000880TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000881 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000882 testImport(
883 "template <int K>"
884 "struct dummy { static const int i = K; };"
885 "template <int K> using dummy2 = dummy<K>;"
886 "int declToImport() { return dummy2<3>::i; }",
887 Lang_CXX11, "", Lang_CXX11, Verifier,
888 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000889 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000890 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
891}
892
893const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
894 varTemplateSpecializationDecl;
895
Gabor Marton19f4f392018-06-25 13:04:37 +0000896TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000897 MatchVerifier<Decl> Verifier;
898 testImport(
899 "template <typename T>"
900 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000901 "void declToImport() { (void)pi<int>; }",
902 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000903 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000904 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000905 unless(hasAncestor(translationUnitDecl(has(varDecl(
906 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000907}
908
Gabor Marton19f4f392018-06-25 13:04:37 +0000909TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000910 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000911 testImport(
912 "template <typename... Args>"
913 "struct dummy {"
914 " dummy(Args... args) {}"
915 " static const int i = 4;"
916 "};"
917 "int declToImport() { return dummy<int>::i; }",
918 Lang_CXX11, "", Lang_CXX11, Verifier,
919 functionDecl(hasDescendant(
920 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000921}
922
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000923const internal::VariadicDynCastAllOfMatcher<Type,
924 DependentTemplateSpecializationType>
925 dependentTemplateSpecializationType;
926
Gabor Marton19f4f392018-06-25 13:04:37 +0000927TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000928 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000929 testImport(
930 "template<typename T>"
931 "struct A;"
932 "template<typename T>"
933 "struct declToImport {"
934 " typename A<T>::template B<T> a;"
935 "};",
936 Lang_CXX, "", Lang_CXX, Verifier,
937 classTemplateDecl(has(cxxRecordDecl(has(
938 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000939}
940
941const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
942 sizeOfPackExpr;
943
Gabor Marton19f4f392018-06-25 13:04:37 +0000944TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000945 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000946 testImport(
947 "template <typename... Ts>"
948 "void declToImport() {"
949 " const int i = sizeof...(Ts);"
950 "};"
951 "void g() { declToImport<int>(); }",
952 Lang_CXX11, "", Lang_CXX11, Verifier,
953 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000954 testImport(
955 "template <typename... Ts>"
956 "using X = int[sizeof...(Ts)];"
957 "template <typename... Us>"
958 "struct Y {"
959 " X<Us..., int, double, int, Us...> f;"
960 "};"
961 "Y<float, int> declToImport;",
962 Lang_CXX11, "", Lang_CXX11, Verifier,
963 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
964 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
965}
966
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000967/// \brief Matches __builtin_types_compatible_p:
968/// GNU extension to check equivalent types
969/// Given
970/// \code
971/// __builtin_types_compatible_p(int, int)
972/// \endcode
973// will generate TypeTraitExpr <...> 'int'
974const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
975
Gabor Marton19f4f392018-06-25 13:04:37 +0000976TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000977 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000978 testImport(
979 "void declToImport() { "
980 " (void)__builtin_types_compatible_p(int, int);"
981 "}",
982 Lang_C, "", Lang_C, Verifier,
983 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000984}
985
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000986const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
987
Gabor Marton19f4f392018-06-25 13:04:37 +0000988TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000989 MatchVerifier<Decl> Verifier;
990 testImport(
991 "namespace std { class type_info {}; }"
992 "void declToImport() {"
993 " int x;"
994 " auto a = typeid(int); auto b = typeid(x);"
995 "}",
996 Lang_CXX11, "", Lang_CXX11, Verifier,
997 functionDecl(
998 hasDescendant(varDecl(
999 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
1000 hasDescendant(varDecl(
1001 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
1002}
1003
Gabor Marton19f4f392018-06-25 13:04:37 +00001004TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001005 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001006 testImport(
1007 "template<typename T> struct declToImport {"
1008 " void m() { (void)__is_pod(T); }"
1009 "};"
1010 "void f() { declToImport<int>().m(); }",
1011 Lang_CXX11, "", Lang_CXX11, Verifier,
1012 classTemplateDecl(has(cxxRecordDecl(has(
1013 functionDecl(hasDescendant(
1014 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001015}
Gabor Horvath7a91c082017-11-14 11:30:38 +00001016
Gabor Marton6e1510c2018-07-12 11:50:21 +00001017TEST_P(ImportDecl, ImportRecordDeclInFunc) {
1018 MatchVerifier<Decl> Verifier;
1019 testImport("int declToImport() { "
1020 " struct data_t {int a;int b;};"
1021 " struct data_t d;"
1022 " return 0;"
1023 "}",
1024 Lang_C, "", Lang_C, Verifier,
1025 functionDecl(hasBody(compoundStmt(
1026 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
1027}
1028
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001029TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001030 Decl *FromTU = getTuDecl("int declToImport() { "
1031 " struct data_t {int a;int b;};"
1032 " struct data_t d;"
1033 " return 0;"
1034 "}",
1035 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +00001036 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +00001037 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
1038 ASSERT_TRUE(FromVar);
1039 auto ToType =
1040 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
1041 EXPECT_FALSE(ToType.isNull());
1042}
1043
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001044TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001045 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +00001046 Decl *FromTU = getTuDecl(
1047 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1048 Lang_C, "input.c");
1049 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1050 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001051 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001052 auto *To = Import(From, Lang_C);
1053 EXPECT_EQ(To, nullptr);
1054}
1055
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001056TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001057 Decl *FromTU = getTuDecl(
1058 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1059 "int declToImport(){ return NONAME_SIZEOF(int); }",
1060 Lang_C, "input.c");
1061 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1062 FromTU, functionDecl(hasName("declToImport")));
1063 ASSERT_TRUE(From);
1064 auto *To = Import(From, Lang_C);
1065 ASSERT_TRUE(To);
1066 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1067 To, functionDecl(hasName("declToImport"),
1068 hasDescendant(unaryExprOrTypeTraitExpr()))));
1069}
1070
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001071TEST_P(ASTImporterOptionSpecificTestBase,
1072 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001073 // This construct is not supported by ASTImporter.
1074 Decl *FromTU = getTuDecl(
1075 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1076 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1077 Lang_C, "input.c");
1078 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1079 FromTU, functionDecl(hasName("declToImport")));
1080 ASSERT_TRUE(From);
1081 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001082 EXPECT_EQ(To, nullptr);
1083}
1084
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001085const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1086 cxxPseudoDestructorExpr;
1087
Gabor Marton19f4f392018-06-25 13:04:37 +00001088TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001089 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001090 testImport(
1091 "typedef int T;"
1092 "void declToImport(int *p) {"
1093 " T t;"
1094 " p->T::~T();"
1095 "}",
1096 Lang_CXX, "", Lang_CXX, Verifier,
1097 functionDecl(hasDescendant(
1098 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001099}
1100
Gabor Marton19f4f392018-06-25 13:04:37 +00001101TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001102 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001103 testImport(
1104 "namespace foo { int bar; }"
1105 "void declToImport() { using foo::bar; }",
1106 Lang_CXX, "", Lang_CXX, Verifier,
1107 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001108}
1109
1110/// \brief Matches shadow declarations introduced into a scope by a
1111/// (resolved) using declaration.
1112///
1113/// Given
1114/// \code
1115/// namespace n { int f; }
1116/// namespace declToImport { using n::f; }
1117/// \endcode
1118/// usingShadowDecl()
1119/// matches \code f \endcode
1120const internal::VariadicDynCastAllOfMatcher<Decl,
1121 UsingShadowDecl> usingShadowDecl;
1122
Gabor Marton19f4f392018-06-25 13:04:37 +00001123TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001124 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001125 testImport(
1126 "namespace foo { int bar; }"
1127 "namespace declToImport { using foo::bar; }",
1128 Lang_CXX, "", Lang_CXX, Verifier,
1129 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001130}
1131
Gabor Marton19f4f392018-06-25 13:04:37 +00001132TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001133 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001134 testImport(
1135 "template<typename T> int foo();"
1136 "template <typename T> void declToImport() {"
1137 " (void)::foo<T>;"
1138 " (void)::template foo<T>;"
1139 "}"
1140 "void instantiate() { declToImport<int>(); }",
1141 Lang_CXX, "", Lang_CXX, Verifier,
1142 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001143}
1144
Gabor Marton19f4f392018-06-25 13:04:37 +00001145TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001146 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001147 testImport(
1148 "template <typename T> struct C { T t; };"
1149 "template <typename T> void declToImport() {"
1150 " C<T> d;"
1151 " d.t = T();"
1152 "}"
1153 "void instantiate() { declToImport<int>(); }",
1154 Lang_CXX, "", Lang_CXX, Verifier,
1155 functionTemplateDecl(hasDescendant(
1156 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1157 testImport(
1158 "template <typename T> struct C { T t; };"
1159 "template <typename T> void declToImport() {"
1160 " C<T> d;"
1161 " (&d)->t = T();"
1162 "}"
1163 "void instantiate() { declToImport<int>(); }",
1164 Lang_CXX, "", Lang_CXX, Verifier,
1165 functionTemplateDecl(hasDescendant(
1166 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001167}
1168
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001169/// Check that function "declToImport()" (which is the templated function
1170/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1171/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001172TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001173 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001174 testImport(
1175 "template <typename T> void declToImport() { T a = 1; }"
1176 "void instantiate() { declToImport<int>(); }",
1177 Lang_CXX, "", Lang_CXX, Verifier,
1178 functionTemplateDecl(hasAncestor(translationUnitDecl(
1179 unless(has(functionDecl(hasName("declToImport"))))))));
1180 testImport(
1181 "template <typename T> struct declToImport { T t; };"
1182 "void instantiate() { declToImport<int>(); }",
1183 Lang_CXX, "", Lang_CXX, Verifier,
1184 classTemplateDecl(hasAncestor(translationUnitDecl(
1185 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001186}
1187
Gabor Marton19f4f392018-06-25 13:04:37 +00001188TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001189 MatchVerifier<Decl> Verifier;
1190 auto Code =
1191 R"s(
1192 struct declToImport {
1193 template <typename T0> struct X;
1194 template <typename T0> struct X<T0 *> {};
1195 };
1196 )s";
1197 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1198 recordDecl(has(classTemplateDecl()),
1199 has(classTemplateSpecializationDecl())));
1200}
1201
Gabor Marton19f4f392018-06-25 13:04:37 +00001202TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001203 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001204 testImport(
1205 "class declToImport {"
1206 " void f() { *this = declToImport(); }"
1207 "};",
1208 Lang_CXX, "", Lang_CXX, Verifier,
1209 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1210 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001211}
1212
Gabor Marton19f4f392018-06-25 13:04:37 +00001213TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001214 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001215 testImport(
1216 "template<typename T, int Size> class declToImport {"
1217 " T data[Size];"
1218 "};",
1219 Lang_CXX, "", Lang_CXX, Verifier,
1220 classTemplateDecl(has(cxxRecordDecl(
1221 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001222}
1223
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001224TEST_P(ASTImporterOptionSpecificTestBase,
1225 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001226 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1227 auto From =
1228 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1229 ASSERT_TRUE(From);
1230 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1231 ASSERT_TRUE(To);
1232 Decl *ToTemplated = To->getTemplatedDecl();
1233 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1234 EXPECT_TRUE(ToTemplated1);
1235 EXPECT_EQ(ToTemplated1, ToTemplated);
1236}
1237
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001238TEST_P(ASTImporterOptionSpecificTestBase,
1239 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001240 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1241 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1242 FromTU, functionTemplateDecl());
1243 ASSERT_TRUE(From);
1244 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1245 ASSERT_TRUE(To);
1246 Decl *ToTemplated = To->getTemplatedDecl();
1247 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1248 EXPECT_TRUE(ToTemplated1);
1249 EXPECT_EQ(ToTemplated1, ToTemplated);
1250}
1251
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001252TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001253 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1254 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1255 auto FromFT =
1256 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1257 ASSERT_TRUE(FromFT);
1258
1259 auto ToTemplated =
1260 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1261 EXPECT_TRUE(ToTemplated);
1262 auto ToTU = ToTemplated->getTranslationUnitDecl();
1263 auto ToFT =
1264 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1265 EXPECT_TRUE(ToFT);
1266}
1267
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001268TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001269 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001270 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1271 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1272 FromTU, functionTemplateDecl());
1273 ASSERT_TRUE(FromFT);
1274
1275 auto ToTemplated =
1276 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1277 EXPECT_TRUE(ToTemplated);
1278 auto ToTU = ToTemplated->getTranslationUnitDecl();
1279 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1280 ToTU, functionTemplateDecl());
1281 EXPECT_TRUE(ToFT);
1282}
1283
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001284TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001285 auto Code =
1286 R"(
1287 namespace x {
1288 template<class X> struct S1{};
1289 template<class X> struct S2{};
1290 template<class X> struct S3{};
1291 }
1292 )";
1293 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1294 auto FromNs =
1295 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1296 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1297 ASSERT_TRUE(ToNs);
1298 auto From =
1299 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1300 classTemplateDecl(
1301 hasName("S2")));
1302 auto To =
1303 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1304 classTemplateDecl(
1305 hasName("S2")));
1306 ASSERT_TRUE(From);
1307 ASSERT_TRUE(To);
1308 auto ToTemplated = To->getTemplatedDecl();
1309 auto ToTemplated1 =
1310 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1311 EXPECT_TRUE(ToTemplated1);
1312 ASSERT_EQ(ToTemplated1, ToTemplated);
1313}
1314
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001315TEST_P(ASTImporterOptionSpecificTestBase,
1316 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001317 Decl *From, *To;
1318 std::tie(From, To) = getImportedDecl(
1319 R"(
1320 template <typename T> struct X {};
1321
1322 void declToImport(int y, X<int> &x) {}
1323
1324 template <> struct X<int> {
1325 void g() {
1326 X<int> x;
1327 declToImport(0, x);
1328 }
1329 };
1330 )",
1331 Lang_CXX, "", Lang_CXX);
1332
1333 MatchVerifier<Decl> Verifier;
1334 auto Matcher = functionDecl(hasName("declToImport"),
1335 parameterCountIs(2),
1336 hasParameter(0, hasName("y")),
1337 hasParameter(1, hasName("x")),
1338 hasParameter(1, hasType(asString("X<int> &"))));
1339 ASSERT_TRUE(Verifier.match(From, Matcher));
1340 EXPECT_TRUE(Verifier.match(To, Matcher));
1341}
1342
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001343TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001344 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1345 Decl *From, *To;
1346 std::tie(From, To) =
1347 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1348 "void instantiate() { declToImport<int>(); }",
1349 Lang_CXX, "", Lang_CXX);
1350
1351 auto Check = [](Decl *D) -> bool {
1352 auto TU = D->getTranslationUnitDecl();
1353 for (auto Child : TU->decls()) {
1354 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1355 if (FD->getNameAsString() == "declToImport") {
1356 GTEST_NONFATAL_FAILURE_(
1357 "TU should not contain any FunctionDecl with name declToImport");
1358 return false;
1359 }
1360 }
1361 }
1362 return true;
1363 };
1364
1365 ASSERT_TRUE(Check(From));
1366 EXPECT_TRUE(Check(To));
1367}
1368
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001369TEST_P(ASTImporterOptionSpecificTestBase,
1370 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001371 Decl *From, *To;
1372 std::tie(From, To) =
1373 getImportedDecl("template <typename T> struct declToImport { T t; };"
1374 "void instantiate() { declToImport<int>(); }",
1375 Lang_CXX, "", Lang_CXX);
1376
1377 auto Check = [](Decl *D) -> bool {
1378 auto TU = D->getTranslationUnitDecl();
1379 for (auto Child : TU->decls()) {
1380 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1381 if (RD->getNameAsString() == "declToImport") {
1382 GTEST_NONFATAL_FAILURE_(
1383 "TU should not contain any CXXRecordDecl with name declToImport");
1384 return false;
1385 }
1386 }
1387 }
1388 return true;
1389 };
1390
1391 ASSERT_TRUE(Check(From));
1392 EXPECT_TRUE(Check(To));
1393}
1394
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001395TEST_P(ASTImporterOptionSpecificTestBase,
1396 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001397 Decl *From, *To;
1398 std::tie(From, To) =
1399 getImportedDecl(
1400 "template <typename T> struct X {};"
1401 "template <typename T> using declToImport = X<T>;"
1402 "void instantiate() { declToImport<int> a; }",
1403 Lang_CXX11, "", Lang_CXX11);
1404
1405 auto Check = [](Decl *D) -> bool {
1406 auto TU = D->getTranslationUnitDecl();
1407 for (auto Child : TU->decls()) {
1408 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1409 if (AD->getNameAsString() == "declToImport") {
1410 GTEST_NONFATAL_FAILURE_(
1411 "TU should not contain any TypeAliasDecl with name declToImport");
1412 return false;
1413 }
1414 }
1415 }
1416 return true;
1417 };
1418
1419 ASSERT_TRUE(Check(From));
1420 EXPECT_TRUE(Check(To));
1421}
1422
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001423TEST_P(ASTImporterOptionSpecificTestBase,
1424 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001425
1426 Decl *From, *To;
1427 std::tie(From, To) = getImportedDecl(
1428 R"(
1429 template<class T>
1430 class Base {};
1431 class declToImport : public Base<declToImport> {};
1432 )",
1433 Lang_CXX, "", Lang_CXX);
1434
1435 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1436 auto Pattern =
1437 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1438 ASSERT_TRUE(
1439 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1440 EXPECT_TRUE(
1441 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1442
1443 // Check that the ClassTemplateSpecializationDecl is the child of the
1444 // ClassTemplateDecl.
1445 Pattern = translationUnitDecl(has(classTemplateDecl(
1446 hasName("Base"), has(classTemplateSpecializationDecl()))));
1447 ASSERT_TRUE(
1448 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1449 EXPECT_TRUE(
1450 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1451}
1452
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001453AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1454 size_t Index = 0;
1455 for (FieldDecl *Field : Node.fields()) {
1456 if (Index == Order.size())
1457 return false;
1458 if (Field->getName() != Order[Index])
1459 return false;
1460 ++Index;
1461 }
1462 return Index == Order.size();
1463}
1464
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001465TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001466 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1467 Decl *From, *To;
1468 std::tie(From, To) = getImportedDecl(
1469 R"(
1470 namespace NS {
1471 template<class T>
1472 class X {};
1473 template class X<int>;
1474 }
1475 )",
1476 Lang_CXX, "", Lang_CXX, "NS");
1477
1478 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1479 // ClassTemplateDecl.
1480 auto Pattern = namespaceDecl(has(classTemplateDecl(
1481 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1482 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1483 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1484
1485 // Check that the ClassTemplateSpecializationDecl is the child of the
1486 // NamespaceDecl.
1487 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1488 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1489 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1490}
1491
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001492TEST_P(ASTImporterOptionSpecificTestBase,
1493 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001494 Decl *From, *To;
1495 std::tie(From, To) =
1496 getImportedDecl(
1497 "struct declToImport { int a; int b; };",
1498 Lang_CXX11, "", Lang_CXX11);
1499
1500 MatchVerifier<Decl> Verifier;
1501 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1502 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1503}
1504
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001505TEST_P(ASTImporterOptionSpecificTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001506 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001507 Decl *From, *To;
1508 std::tie(From, To) = getImportedDecl(
1509 // The original recursive algorithm of ASTImporter first imports 'c' then
1510 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1511 R"s(
1512 struct declToImport {
1513 int a = c + b;
1514 int b = 1;
1515 int c = 2;
1516 };
1517 )s",
1518 Lang_CXX11, "", Lang_CXX11);
1519
1520 MatchVerifier<Decl> Verifier;
1521 ASSERT_TRUE(
1522 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1523 EXPECT_TRUE(
1524 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1525}
1526
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001527TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001528 Decl *From, *To;
1529 std::tie(From, To) = getImportedDecl(
1530 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001531 struct declToImport {
1532 };
1533 )",
1534 Lang_CXX, "", Lang_CXX);
1535
1536 MatchVerifier<Decl> Verifier;
1537 // Match the implicit Decl.
1538 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1539 ASSERT_TRUE(Verifier.match(From, Matcher));
1540 EXPECT_TRUE(Verifier.match(To, Matcher));
1541}
1542
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001543TEST_P(ASTImporterOptionSpecificTestBase,
1544 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001545 Decl *From, *To;
1546 std::tie(From, To) = getImportedDecl(
1547 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001548 template <typename U>
1549 struct declToImport {
1550 };
1551 )",
1552 Lang_CXX, "", Lang_CXX);
1553
1554 MatchVerifier<Decl> Verifier;
1555 // Match the implicit Decl.
1556 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1557 ASSERT_TRUE(Verifier.match(From, Matcher));
1558 EXPECT_TRUE(Verifier.match(To, Matcher));
1559}
1560
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001561TEST_P(ASTImporterOptionSpecificTestBase,
1562 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001563 Decl *From, *To;
1564 std::tie(From, To) = getImportedDecl(
1565 R"(
1566 template<class T>
1567 class Base {};
1568 class declToImport : public Base<declToImport> {};
1569 )",
1570 Lang_CXX, "", Lang_CXX);
1571
1572 auto hasImplicitClass = has(cxxRecordDecl());
1573 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1574 hasName("Base"),
1575 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1576 ASSERT_TRUE(
1577 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1578 EXPECT_TRUE(
1579 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1580}
1581
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001582TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001583 Decl *From, *To;
1584 std::tie(From, To) =
1585 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1586
1587 MatchVerifier<Decl> Verifier;
1588 auto Matcher = functionDecl();
1589 ASSERT_TRUE(Verifier.match(From, Matcher));
1590 EXPECT_TRUE(Verifier.match(To, Matcher));
1591 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1592}
1593
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001594TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001595 Decl *FromTU = getTuDecl(
1596 R"(
1597 struct X {};
1598 void operator<<(int, X);
1599 )",
1600 Lang_CXX);
1601 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1602 const Decl *To = Import(From, Lang_CXX);
1603 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1604}
1605
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001606TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001607 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1608 Decl *From, *To;
1609 std::tie(From, To) = getImportedDecl(
1610 R"(
1611 template<class T>
1612 class Base { int a; };
1613 class declToImport : Base<declToImport> {};
1614 )",
1615 Lang_CXX, "", Lang_CXX);
1616
1617 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1618 hasName("Base"),
1619 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1620 ASSERT_TRUE(
1621 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1622 EXPECT_TRUE(
1623 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1624}
1625
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001626TEST_P(ASTImporterOptionSpecificTestBase,
1627 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001628 {
1629 Decl *FromTU = getTuDecl(
1630 R"(
1631 template <typename T>
1632 struct B;
1633 )",
1634 Lang_CXX, "input0.cc");
1635 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1636 FromTU, classTemplateDecl(hasName("B")));
1637
1638 Import(FromD, Lang_CXX);
1639 }
1640
1641 {
1642 Decl *FromTU = getTuDecl(
1643 R"(
1644 template <typename T>
1645 struct B {
1646 void f();
1647 };
1648 )",
1649 Lang_CXX, "input1.cc");
1650 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1651 FromTU, functionDecl(hasName("f")));
1652 Import(FromD, Lang_CXX);
1653 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1654 FromTU, classTemplateDecl(hasName("B")));
1655 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1656 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1657 }
1658}
1659
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001660TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001661 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1662 Decl *ToTU = getToTuDecl(
1663 R"(
1664 template <typename T>
1665 struct B {
1666 void f();
1667 };
1668
1669 template <typename T>
1670 struct B;
1671 )",
1672 Lang_CXX);
1673 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1674 [](const ClassTemplateDecl *T) {
1675 return T->isThisDeclarationADefinition();
1676 })
1677 .match(ToTU, classTemplateDecl()));
1678
1679 Decl *FromTU = getTuDecl(
1680 R"(
1681 template <typename T>
1682 struct B {
1683 void f();
1684 };
1685 )",
1686 Lang_CXX, "input1.cc");
1687 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1688 FromTU, classTemplateDecl(hasName("B")));
1689
1690 Import(FromD, Lang_CXX);
1691
1692 // We should have only one definition.
1693 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1694 [](const ClassTemplateDecl *T) {
1695 return T->isThisDeclarationADefinition();
1696 })
1697 .match(ToTU, classTemplateDecl()));
1698}
1699
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001700TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001701 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1702 Decl *ToTU = getToTuDecl(
1703 R"(
1704 struct B {
1705 void f();
1706 };
1707
1708 struct B;
1709 )",
1710 Lang_CXX);
1711 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001712 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001713
1714 Decl *FromTU = getTuDecl(
1715 R"(
1716 struct B {
1717 void f();
1718 };
1719 )",
1720 Lang_CXX, "input1.cc");
1721 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1722 FromTU, cxxRecordDecl(hasName("B")));
1723
1724 Import(FromD, Lang_CXX);
1725
1726 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001727 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001728}
1729
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001730static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1731 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1732 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1733 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1734 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1735}
1736static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1737 SourceManager &SM1, SourceManager &SM2) {
1738 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1739 FullSourceLoc{ Range2.getBegin(), SM2 });
1740 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1741 FullSourceLoc{ Range2.getEnd(), SM2 });
1742}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001743TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001744 Decl *FromTU = getTuDecl(
1745 R"(
1746 #define MFOO(arg) arg = arg + 1
1747
1748 void foo() {
1749 int a = 5;
1750 MFOO(a);
1751 }
1752 )",
1753 Lang_CXX);
1754 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1755 auto ToD = Import(FromD, Lang_CXX);
1756
1757 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1758 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1759 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1760 auto FromRHS =
1761 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1762
1763 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1764 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1765 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1766 FromSM);
1767 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1768 FromSM);
1769 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1770 FromSM);
1771}
1772
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001773TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001774 Decl *FromTU = getTuDecl(
1775 R"(
1776 #define FUNC_INT void declToImport
1777 #define FUNC FUNC_INT
1778 FUNC(int a);
1779 )",
1780 Lang_CXX);
1781 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1782 auto ToD = Import(FromD, Lang_CXX);
1783
1784 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1785 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1786 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1787 FromSM);
1788}
1789
Gabor Marton9581c332018-05-23 13:53:36 +00001790TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001791 ASTImporterOptionSpecificTestBase,
1792 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001793 Decl *ToTU = getToTuDecl(
1794 R"(
1795 template <typename T>
1796 struct B;
1797
1798 template <>
1799 struct B<int> {};
1800
1801 template <>
1802 struct B<int>;
1803 )",
1804 Lang_CXX);
1805 // We should have only one definition.
1806 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1807 [](const ClassTemplateSpecializationDecl *T) {
1808 return T->isThisDeclarationADefinition();
1809 })
1810 .match(ToTU, classTemplateSpecializationDecl()));
1811
1812 Decl *FromTU = getTuDecl(
1813 R"(
1814 template <typename T>
1815 struct B;
1816
1817 template <>
1818 struct B<int> {};
1819 )",
1820 Lang_CXX, "input1.cc");
1821 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1822 FromTU, classTemplateSpecializationDecl(hasName("B")));
1823
1824 Import(FromD, Lang_CXX);
1825
1826 // We should have only one definition.
1827 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1828 [](const ClassTemplateSpecializationDecl *T) {
1829 return T->isThisDeclarationADefinition();
1830 })
1831 .match(ToTU, classTemplateSpecializationDecl()));
1832}
1833
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001834TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001835 Decl *FromTU = getTuDecl(
1836 R"(
1837 struct { int a; int b; } object0 = { 2, 3 };
1838 struct { int x; int y; int z; } object1;
1839 )",
1840 Lang_CXX, "input0.cc");
1841
Gabor Marton0bebf952018-07-05 09:51:13 +00001842 auto *Obj0 =
1843 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1844 auto *From0 = getRecordDecl(Obj0);
1845 auto *Obj1 =
1846 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1847 auto *From1 = getRecordDecl(Obj1);
1848
1849 auto *To0 = Import(From0, Lang_CXX);
1850 auto *To1 = Import(From1, Lang_CXX);
1851
1852 EXPECT_TRUE(To0);
1853 EXPECT_TRUE(To1);
1854 EXPECT_NE(To0, To1);
1855 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1856}
1857
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001858TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001859 auto *Code =
1860 R"(
1861 struct X {
1862 struct { int a; };
1863 struct { int b; };
1864 };
1865 )";
1866 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1867
1868 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1869
1870 auto *X0 =
1871 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1872 auto *X1 =
1873 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1874 Import(X0, Lang_C);
1875 Import(X1, Lang_C);
1876
1877 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1878 // We expect no (ODR) warning during the import.
1879 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1880 EXPECT_EQ(1u,
1881 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1882}
1883
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001884TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001885 Decl *FromTU0 = getTuDecl(
1886 R"(
1887 struct X {
1888 struct { int a; };
1889 struct { int b; };
1890 };
1891 )",
1892 Lang_C, "input0.c");
1893
1894 Decl *FromTU1 = getTuDecl(
1895 R"(
1896 struct X { // reversed order
1897 struct { int b; };
1898 struct { int a; };
1899 };
1900 )",
1901 Lang_C, "input1.c");
1902
1903 auto *X0 =
1904 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1905 auto *X1 =
1906 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1907 Import(X0, Lang_C);
1908 Import(X1, Lang_C);
1909
1910 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1911 // We expect one (ODR) warning during the import.
1912 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1913 EXPECT_EQ(2u,
1914 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1915}
1916
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001917TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001918 auto Pattern = varDecl(hasName("x"));
1919 VarDecl *Imported1;
1920 {
1921 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1922 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1923 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1924 }
1925 VarDecl *Imported2;
1926 {
1927 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1928 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1929 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1930 }
1931 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1932 EXPECT_FALSE(Imported2->isUsed(false));
1933 {
1934 Decl *FromTU =
1935 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001936 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1937 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001938 Import(FromD, Lang_CXX);
1939 }
1940 EXPECT_TRUE(Imported2->isUsed(false));
1941}
1942
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001943TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001944 auto Pattern = varDecl(hasName("x"));
1945 VarDecl *ExistingD;
1946 {
1947 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1948 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1949 }
1950 EXPECT_FALSE(ExistingD->isUsed(false));
1951 {
1952 Decl *FromTU = getTuDecl(
1953 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1954 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1955 FromTU, functionDecl(hasName("f")));
1956 Import(FromD, Lang_CXX);
1957 }
1958 EXPECT_TRUE(ExistingD->isUsed(false));
1959}
1960
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001961TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001962 auto Pattern = varDecl(hasName("a"));
1963 VarDecl *ExistingD;
1964 {
1965 Decl *ToTU = getToTuDecl(
1966 R"(
1967 struct A {
1968 static const int a = 1;
1969 };
1970 )", Lang_CXX);
1971 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1972 }
1973 EXPECT_FALSE(ExistingD->isUsed(false));
1974 {
1975 Decl *FromTU = getTuDecl(
1976 R"(
1977 struct A {
1978 static const int a = 1;
1979 };
1980 const int *f() { return &A::a; } // requires storage,
1981 // thus used flag will be set
1982 )", Lang_CXX, "input1.cc");
1983 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1984 FromTU, functionDecl(hasName("f")));
1985 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1986 ASSERT_TRUE(FromD->isUsed(false));
1987 Import(FromFunD, Lang_CXX);
1988 }
1989 EXPECT_TRUE(ExistingD->isUsed(false));
1990}
1991
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001992TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001993 auto Pattern = varDecl(hasName("x"));
1994
1995 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1996 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1997
1998 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1999
2000 ASSERT_FALSE(Imported1->isUsed(false));
2001
2002 FromD->setIsUsed();
2003 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2004
2005 EXPECT_EQ(Imported1, Imported2);
2006 EXPECT_TRUE(Imported2->isUsed(false));
2007}
2008
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002009struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00002010
Gabor Marton5254e642018-06-27 13:32:50 +00002011TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002012 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2013 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002014 auto *From =
2015 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002016
Gabor Marton5254e642018-06-27 13:32:50 +00002017 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002018 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2019
Gabor Marton5254e642018-06-27 13:32:50 +00002020 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2021 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2022 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2023 EXPECT_TRUE(ImportedD == To0);
2024 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2025 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2026 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002027}
2028
2029TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2030 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2031 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002032 auto *From =
2033 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002034
Gabor Marton5254e642018-06-27 13:32:50 +00002035 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002036 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2037
Gabor Marton5254e642018-06-27 13:32:50 +00002038 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2039 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2040 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2041 EXPECT_TRUE(ImportedD == To1);
2042 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2043 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2044 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002045}
2046
Peter Szecsidedda6f2018-03-30 22:03:29 +00002047TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2048 auto Code =
2049 R"(
2050 struct B { virtual void f(); };
2051 void B::f() {}
2052 struct D : B { void f(); };
2053 )";
2054 auto Pattern =
2055 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2056 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2057 CXXMethodDecl *Proto =
2058 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2059
2060 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2061 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2062 EXPECT_EQ(To->size_overridden_methods(), 1u);
2063}
2064
2065TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2066 auto Code =
2067 R"(
2068 struct B { virtual void f(); };
2069 void B::f() {}
2070 )";
2071 auto Pattern =
2072 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2073 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2074 CXXMethodDecl *Proto =
2075 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2076 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2077
2078 ASSERT_TRUE(Proto->isVirtual());
2079 ASSERT_TRUE(Def->isVirtual());
2080 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2081 EXPECT_TRUE(To->isVirtual());
2082}
2083
Gabor Marton5254e642018-06-27 13:32:50 +00002084TEST_P(ImportFunctions,
2085 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2086 Decl *ToTU = getToTuDecl(
2087 R"(
2088 void f() {}
2089 void f();
2090 )",
2091 Lang_CXX);
2092 ASSERT_EQ(1u,
2093 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2094 return FD->doesThisDeclarationHaveABody();
2095 }).match(ToTU, functionDecl()));
2096
2097 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2098 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2099
2100 Import(FromD, Lang_CXX);
2101
2102 EXPECT_EQ(1u,
2103 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2104 return FD->doesThisDeclarationHaveABody();
2105 }).match(ToTU, functionDecl()));
2106}
2107
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002108TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2109 auto Code =
2110 R"(
2111 struct B { virtual void f(); };
2112 struct D:B { void f(); };
2113 )";
2114 auto BFP =
2115 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2116 auto DFP =
2117 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2118
2119 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2120 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2121 Import(DF, Lang_CXX);
2122
2123 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2124 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2125 Import(BF, Lang_CXX);
2126
2127 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2128
2129 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2130 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2131}
2132
2133TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2134 auto CodeWithoutDef =
2135 R"(
2136 struct B { virtual void f(); };
2137 struct D:B { void f(); };
2138 )";
2139 auto CodeWithDef =
2140 R"(
2141 struct B { virtual void f(){}; };
2142 struct D:B { void f(){}; };
2143 )";
2144 auto BFP =
2145 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2146 auto DFP =
2147 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2148 auto BFDefP = cxxMethodDecl(
2149 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2150 auto DFDefP = cxxMethodDecl(
2151 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2152 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2153
2154 {
2155 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2156 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2157 Import(FromD, Lang_CXX);
2158 }
2159 {
2160 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2161 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2162 Import(FromB, Lang_CXX);
2163 }
2164
2165 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2166
2167 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2168 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2169 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2170 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2171 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2172}
2173
2174TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2175 auto Code =
2176 R"(
2177 struct B { virtual void f(); };
2178 struct D:B { void f(); };
2179 void B::f(){};
2180 )";
2181
2182 auto BFP =
2183 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2184 auto BFDefP = cxxMethodDecl(
2185 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2186 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2187 unless(isDefinition()));
2188
2189 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2190 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2191 Import(D, Lang_CXX);
2192
2193 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2194 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2195 Import(B, Lang_CXX);
2196
2197 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2198
2199 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2200 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2201
2202 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2203 ToTU, cxxRecordDecl(hasName("B")));
2204 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2205 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2206 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2207
2208 // The definition should be out-of-class.
2209 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2210 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2211 ToBFOutOfClass->getLexicalDeclContext());
2212 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2213 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2214
2215 // Check that the redecl chain is intact.
2216 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2217}
2218
2219TEST_P(ImportFunctions,
2220 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2221 auto CodeTU0 =
2222 R"(
2223 struct B { virtual void f(); };
2224 struct D:B { void f(); };
2225 )";
2226 auto CodeTU1 =
2227 R"(
2228 struct B { virtual void f(); };
2229 struct D:B { void f(); };
2230 void B::f(){}
2231 void D::f(){}
2232 void foo(B &b, D &d) { b.f(); d.f(); }
2233 )";
2234
2235 auto BFP =
2236 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2237 auto BFDefP = cxxMethodDecl(
2238 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2239 auto DFP =
2240 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2241 auto DFDefP = cxxMethodDecl(
2242 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2243 auto FooDef = functionDecl(hasName("foo"));
2244
2245 {
2246 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2247 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2248 Import(D, Lang_CXX);
2249 }
2250
2251 {
2252 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2253 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2254 Import(Foo, Lang_CXX);
2255 }
2256
2257 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2258
2259 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2260 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2261 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2262 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2263
2264 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2265 ToTU, cxxRecordDecl(hasName("B")));
2266 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2267 ToTU, cxxRecordDecl(hasName("D")));
2268 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2269 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2270 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2271 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2272 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2273 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2274
2275 // The definition should be out-of-class.
2276 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2277 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2278 ToBFOutOfClass->getLexicalDeclContext());
2279 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2280 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2281
2282 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2283 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2284 ToDFOutOfClass->getLexicalDeclContext());
2285 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2286 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2287
2288 // Check that the redecl chain is intact.
2289 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2290 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2291}
2292
Gabor Marton458d1452019-02-14 13:07:03 +00002293//FIXME Move these tests to a separate test file.
2294namespace TypeAndValueParameterizedTests {
2295
2296// Type parameters for type-parameterized test fixtures.
2297struct GetFunPattern {
2298 using DeclTy = FunctionDecl;
2299 BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
2300};
2301struct GetVarPattern {
2302 using DeclTy = VarDecl;
2303 BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
2304};
2305
2306// Values for the value-parameterized test fixtures.
2307// FunctionDecl:
2308auto *ExternF = "void f();";
2309auto *StaticF = "static void f();";
2310auto *AnonF = "namespace { void f(); }";
2311// VarDecl:
2312auto *ExternV = "extern int v;";
2313auto *StaticV = "static int v;";
2314auto *AnonV = "namespace { extern int v; }";
2315
2316// First value in tuple: Compile options.
2317// Second value in tuple: Source code to be used in the test.
2318using ImportVisibilityChainParams =
2319 ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
2320// Fixture to test the redecl chain of Decls with the same visibility. Gtest
2321// makes it possible to have either value-parameterized or type-parameterized
2322// fixtures. However, we cannot have both value- and type-parameterized test
2323// fixtures. This is a value-parameterized test fixture in the gtest sense. We
2324// intend to mimic gtest's type-parameters via the PatternFactory template
2325// parameter. We manually instantiate the different tests with the each types.
2326template <typename PatternFactory>
2327class ImportVisibilityChain
2328 : public ASTImporterTestBase, public ImportVisibilityChainParams {
2329protected:
2330 using DeclTy = typename PatternFactory::DeclTy;
2331 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2332 std::string getCode() const { return std::get<1>(GetParam()); }
2333 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2334
2335 // Type-parameterized test.
2336 void TypedTest_ImportChain() {
2337 std::string Code = getCode() + getCode();
2338 auto Pattern = getPattern();
2339
2340 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
2341
2342 auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
2343 auto *FromF1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
2344
2345 auto *ToF0 = Import(FromF0, Lang_CXX);
2346 auto *ToF1 = Import(FromF1, Lang_CXX);
2347
2348 EXPECT_TRUE(ToF0);
2349 ASSERT_TRUE(ToF1);
2350 EXPECT_NE(ToF0, ToF1);
2351 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2352 }
2353};
2354
2355// Manual instantiation of the fixture with each type.
2356using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
2357using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
2358// Value-parameterized test for the first type.
2359TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
2360 TypedTest_ImportChain();
2361}
2362// Value-parameterized test for the second type.
2363TEST_P(ImportVariablesVisibilityChain, ImportChain) {
2364 TypedTest_ImportChain();
2365}
2366
2367// Automatic instantiation of the value-parameterized tests.
2368INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
2369 ::testing::Combine(
2370 DefaultTestValuesForRunOptions,
2371 ::testing::Values(ExternF, StaticF, AnonF)), );
2372INSTANTIATE_TEST_CASE_P(
2373 ParameterizedTests, ImportVariablesVisibilityChain,
2374 ::testing::Combine(
2375 DefaultTestValuesForRunOptions,
2376 // There is no point to instantiate with StaticV, because in C++ we can
2377 // forward declare a variable only with the 'extern' keyword.
2378 // Consequently, each fwd declared variable has external linkage. This
2379 // is different in the C language where any declaration without an
2380 // initializer is a tentative definition, subsequent definitions may be
2381 // provided but they must have the same linkage. See also the test
2382 // ImportVariableChainInC which test for this special C Lang case.
2383 ::testing::Values(ExternV, AnonV)), );
2384
2385// First value in tuple: Compile options.
2386// Second value in tuple: Tuple with informations for the test.
2387// Code for first import (or initial code), code to import, whether the `f`
2388// functions are expected to be linked in a declaration chain.
2389// One value of this tuple is combined with every value of compile options.
2390// The test can have a single tuple as parameter only.
2391using ImportVisibilityParams = ::testing::WithParamInterface<
2392 std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
2393
2394template <typename PatternFactory>
2395class ImportVisibility
2396 : public ASTImporterTestBase,
2397 public ImportVisibilityParams {
2398protected:
2399 using DeclTy = typename PatternFactory::DeclTy;
2400 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2401 std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
2402 std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
2403 bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
2404 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2405
2406 void TypedTest_ImportAfter() {
2407 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
2408 TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2409
2410 auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
2411 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
2412
2413 auto *ToF1 = Import(FromF1, Lang_CXX);
2414
2415 ASSERT_TRUE(ToF0);
2416 ASSERT_TRUE(ToF1);
2417 EXPECT_NE(ToF0, ToF1);
2418
2419 if (shouldBeLinked())
2420 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2421 else
2422 EXPECT_FALSE(ToF1->getPreviousDecl());
2423 }
2424
2425 void TypedTest_ImportAfterImport() {
2426 TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
2427 TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2428 auto *FromF0 =
2429 FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
2430 auto *FromF1 =
2431 FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
2432 auto *ToF0 = Import(FromF0, Lang_CXX);
2433 auto *ToF1 = Import(FromF1, Lang_CXX);
2434 ASSERT_TRUE(ToF0);
2435 ASSERT_TRUE(ToF1);
2436 EXPECT_NE(ToF0, ToF1);
2437 if (shouldBeLinked())
2438 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2439 else
2440 EXPECT_FALSE(ToF1->getPreviousDecl());
2441 }
2442};
2443using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
2444using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
2445
2446// FunctionDecl.
2447TEST_P(ImportFunctionsVisibility, ImportAfter) {
2448 TypedTest_ImportAfter();
2449}
2450TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
2451 TypedTest_ImportAfterImport();
2452}
2453// VarDecl.
2454TEST_P(ImportVariablesVisibility, ImportAfter) {
2455 TypedTest_ImportAfter();
2456}
2457TEST_P(ImportVariablesVisibility, ImportAfterImport) {
2458 TypedTest_ImportAfterImport();
2459}
2460
2461bool ExpectLink = true;
2462bool ExpectNotLink = false;
2463
2464INSTANTIATE_TEST_CASE_P(
2465 ParameterizedTests, ImportFunctionsVisibility,
2466 ::testing::Combine(
2467 DefaultTestValuesForRunOptions,
2468 ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
2469 std::make_tuple(ExternF, StaticF, ExpectNotLink),
2470 std::make_tuple(ExternF, AnonF, ExpectNotLink),
2471 std::make_tuple(StaticF, ExternF, ExpectNotLink),
2472 std::make_tuple(StaticF, StaticF, ExpectNotLink),
2473 std::make_tuple(StaticF, AnonF, ExpectNotLink),
2474 std::make_tuple(AnonF, ExternF, ExpectNotLink),
2475 std::make_tuple(AnonF, StaticF, ExpectNotLink),
2476 std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
2477INSTANTIATE_TEST_CASE_P(
2478 ParameterizedTests, ImportVariablesVisibility,
2479 ::testing::Combine(
2480 DefaultTestValuesForRunOptions,
2481 ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
2482 std::make_tuple(ExternV, StaticV, ExpectNotLink),
2483 std::make_tuple(ExternV, AnonV, ExpectNotLink),
2484 std::make_tuple(StaticV, ExternV, ExpectNotLink),
2485 std::make_tuple(StaticV, StaticV, ExpectNotLink),
2486 std::make_tuple(StaticV, AnonV, ExpectNotLink),
2487 std::make_tuple(AnonV, ExternV, ExpectNotLink),
2488 std::make_tuple(AnonV, StaticV, ExpectNotLink),
2489 std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
2490
2491} // namespace TypeAndValueParameterizedTests
2492
2493TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2494 std::string Code = "static int v; static int v = 0;";
2495 auto Pattern = varDecl(hasName("v"));
2496
2497 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2498
2499 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2500 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2501
2502 auto *To0 = Import(From0, Lang_C);
2503 auto *To1 = Import(From1, Lang_C);
2504
2505 EXPECT_TRUE(To0);
2506 ASSERT_TRUE(To1);
2507 EXPECT_NE(To0, To1);
2508 EXPECT_EQ(To1->getPreviousDecl(), To0);
2509}
2510
2511TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2512 TranslationUnitDecl *FromTu = getTuDecl(
2513 "namespace NS0 { namespace { void f(); } }"
2514 "namespace NS1 { namespace { void f(); } }",
2515 Lang_CXX, "input0.cc");
2516 auto Pattern = functionDecl(hasName("f"));
2517
2518 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2519 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2520
2521 auto *ToF0 = Import(FromF0, Lang_CXX);
2522 auto *ToF1 = Import(FromF1, Lang_CXX);
2523
2524 EXPECT_TRUE(ToF0);
2525 ASSERT_TRUE(ToF1);
2526 EXPECT_NE(ToF0, ToF1);
2527 EXPECT_FALSE(ToF1->getPreviousDecl());
2528}
2529
2530TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2531 {
2532 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2533 Lang_CXX, "input0.cc");
2534 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2535 FromTU, functionDecl(hasName("g0")));
2536
2537 Import(FromD, Lang_CXX);
2538 }
2539 {
2540 Decl *FromTU =
2541 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2542 Lang_CXX, "input1.cc");
2543 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2544 FromTU, functionDecl(hasName("g1")));
2545 Import(FromD, Lang_CXX);
2546 }
2547
2548 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2549 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2550 2u);
2551}
2552
Gabor Marton302f3002019-02-15 12:04:05 +00002553TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2554 Decl *FromTU = getTuDecl(
2555 R"(
2556 void foo() {
2557 (void)[]() { ; };
2558 }
2559 )",
2560 Lang_CXX11);
2561 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2562 FromTU, functionDecl(hasName("foo")));
2563 auto *ToD = Import(FromD, Lang_CXX);
2564 EXPECT_TRUE(ToD);
2565 CXXRecordDecl *LambdaRec =
2566 cast<LambdaExpr>(cast<CStyleCastExpr>(
2567 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2568 ->getSubExpr())
2569 ->getLambdaClass();
2570 EXPECT_TRUE(LambdaRec->getDestructor());
2571}
2572
Gabor Marton5254e642018-06-27 13:32:50 +00002573struct ImportFriendFunctions : ImportFunctions {};
2574
2575TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2576 auto Pattern = functionDecl(hasName("f"));
2577
2578 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2579 "void f();",
2580 Lang_CXX,
2581 "input0.cc");
2582 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2583
2584 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2585 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2586 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2587 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2588 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2589 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2590 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2591}
2592
2593TEST_P(ImportFriendFunctions,
2594 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2595 auto Pattern = functionDecl(hasName("f"));
2596
2597 Decl *FromTU = getTuDecl("void f();"
2598 "struct X { friend void f(); };",
2599 Lang_CXX, "input0.cc");
2600 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2601
2602 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2603 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2604 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2605 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2606 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2607 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2608 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2609}
2610
2611TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2612 auto Pattern = functionDecl(hasName("f"));
2613
2614 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2615 "void f();",
2616 Lang_CXX,
2617 "input0.cc");
2618 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2619
2620 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2621 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2622 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2623 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2624 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2625 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2626 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2627}
2628
2629TEST_P(ImportFriendFunctions,
2630 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2631 auto Pattern = functionDecl(hasName("f"));
2632
2633 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2634 "void f(){}",
2635 Lang_CXX, "input0.cc");
2636 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2637
2638 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2639 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2640 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2641 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2642 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2643 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2644 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2645}
2646
Gabor Marton26f72a92018-07-12 09:42:05 +00002647// Disabled temporarily, because the new structural equivalence check
2648// (https://reviews.llvm.org/D48628) breaks it.
2649// PreviousDecl is not set because there is no structural match.
2650// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002651TEST_P(ImportFriendFunctions,
2652 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2653 auto Pattern = functionDecl(hasName("f"));
2654
2655 Decl *FromTU = getTuDecl(
2656 R"(
2657 class X;
2658 void f(X *x){}
2659 class X{
2660 friend void f(X *x);
2661 };
2662 )",
2663 Lang_CXX, "input0.cc");
2664 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2665
2666 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2667 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2668 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2669 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2670 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2671 .match(ToTU, friendDecl())
2672 ->getFriendDecl());
2673 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2674 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2675 // The parameters must refer the same type
2676 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2677 (*ImportedD->param_begin())->getOriginalType());
2678}
2679
Gabor Marton26f72a92018-07-12 09:42:05 +00002680// Disabled temporarily, because the new structural equivalence check
2681// (https://reviews.llvm.org/D48628) breaks it.
2682// PreviousDecl is not set because there is no structural match.
2683// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002684TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002685 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002686 auto Pattern = functionDecl(hasName("f"));
2687
2688 Decl *FromTU = getTuDecl(
2689 R"(
2690 class X;
2691 void f(X *x){}
2692 class X{
2693 friend void f(X *x);
2694 };
2695 )",
2696 Lang_CXX, "input0.cc");
2697 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2698
2699 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2700 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2701 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2702 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2703 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2704 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2705
2706 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2707 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2708 // The parameters must refer the same type
2709 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2710 (*ImportedD->param_begin())->getOriginalType());
2711}
2712
2713TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2714 auto Pattern = functionDecl(hasName("f"));
2715
2716 FunctionDecl *ImportedD;
2717 {
2718 Decl *FromTU =
2719 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2720 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2721 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2722 }
2723 FunctionDecl *ImportedD1;
2724 {
2725 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2726 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2727 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2728 }
2729
2730 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2731 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2732 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2733 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2734 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2735}
2736
Balazs Keri89632b82018-08-21 14:32:21 +00002737TEST_P(ImportFriendFunctions, Lookup) {
2738 auto FunctionPattern = functionDecl(hasName("f"));
2739 auto ClassPattern = cxxRecordDecl(hasName("X"));
2740
2741 TranslationUnitDecl *FromTU =
2742 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2743 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2744 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2745 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2746 {
2747 auto FromName = FromD->getDeclName();
2748 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2749 auto LookupRes = Class->noload_lookup(FromName);
2750 ASSERT_EQ(LookupRes.size(), 0u);
2751 LookupRes = FromTU->noload_lookup(FromName);
2752 ASSERT_EQ(LookupRes.size(), 1u);
2753 }
2754
2755 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2756 auto ToName = ToD->getDeclName();
2757
2758 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2759 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2760 auto LookupRes = Class->noload_lookup(ToName);
2761 EXPECT_EQ(LookupRes.size(), 0u);
2762 LookupRes = ToTU->noload_lookup(ToName);
2763 EXPECT_EQ(LookupRes.size(), 1u);
2764
2765 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2766 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2767 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2768 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2769}
2770
2771TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2772 auto FunctionPattern = functionDecl(hasName("f"));
2773 auto ClassPattern = cxxRecordDecl(hasName("X"));
2774
2775 TranslationUnitDecl *FromTU = getTuDecl(
2776 "struct X { friend void f(); };"
2777 // This proto decl makes f available to normal
2778 // lookup, otherwise it is hidden.
2779 // Normal C++ lookup (implemented in
2780 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2781 // returns the found `NamedDecl` only if the set IDNS is matched
2782 "void f();",
2783 Lang_CXX, "input0.cc");
2784 auto *FromFriend =
2785 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2786 auto *FromNormal =
2787 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2788 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2789 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2790 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2791 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2792
2793 auto FromName = FromFriend->getDeclName();
2794 auto *FromClass =
2795 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2796 auto LookupRes = FromClass->noload_lookup(FromName);
2797 ASSERT_EQ(LookupRes.size(), 0u);
2798 LookupRes = FromTU->noload_lookup(FromName);
2799 ASSERT_EQ(LookupRes.size(), 1u);
2800
2801 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2802 auto ToName = ToFriend->getDeclName();
2803
2804 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2805 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2806 LookupRes = ToClass->noload_lookup(ToName);
2807 EXPECT_EQ(LookupRes.size(), 0u);
2808 LookupRes = ToTU->noload_lookup(ToName);
2809 // Test is disabled because this result is 2.
2810 EXPECT_EQ(LookupRes.size(), 1u);
2811
2812 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2813 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2814 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2815 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2816 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2817 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2818 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2819}
2820
2821TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2822 auto FunctionPattern = functionDecl(hasName("f"));
2823 auto ClassPattern = cxxRecordDecl(hasName("X"));
2824
2825 TranslationUnitDecl *FromTU = getTuDecl(
2826 "void f();"
2827 "struct X { friend void f(); };",
2828 Lang_CXX, "input0.cc");
2829 auto *FromNormal =
2830 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2831 auto *FromFriend =
2832 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2833 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2834 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2835 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2836 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2837
2838 auto FromName = FromNormal->getDeclName();
2839 auto *FromClass =
2840 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2841 auto LookupRes = FromClass->noload_lookup(FromName);
2842 ASSERT_EQ(LookupRes.size(), 0u);
2843 LookupRes = FromTU->noload_lookup(FromName);
2844 ASSERT_EQ(LookupRes.size(), 1u);
2845
2846 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2847 auto ToName = ToNormal->getDeclName();
2848 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2849
2850 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2851 LookupRes = ToClass->noload_lookup(ToName);
2852 EXPECT_EQ(LookupRes.size(), 0u);
2853 LookupRes = ToTU->noload_lookup(ToName);
2854 EXPECT_EQ(LookupRes.size(), 1u);
2855
2856 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2857 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2858 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2859 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2860 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2861 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2862 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2863}
2864
2865TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2866 auto Pattern = functionDecl(hasName("f"));
2867
2868 TranslationUnitDecl *FromNormalTU =
2869 getTuDecl("void f();", Lang_CXX, "input0.cc");
2870 auto *FromNormalF =
2871 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2872 TranslationUnitDecl *FromFriendTU =
2873 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2874 auto *FromFriendF =
2875 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2876 auto FromNormalName = FromNormalF->getDeclName();
2877 auto FromFriendName = FromFriendF->getDeclName();
2878
2879 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2880 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2881 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2882 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2883 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2884 ASSERT_EQ(LookupRes.size(), 1u);
2885 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2886 ASSERT_EQ(LookupRes.size(), 1u);
2887
2888 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2889 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2890 auto ToName = ToNormalF->getDeclName();
2891 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2892 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2893 LookupRes = ToTU->noload_lookup(ToName);
2894 EXPECT_EQ(LookupRes.size(), 1u);
2895 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002896
Balazs Keri89632b82018-08-21 14:32:21 +00002897 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2898 LookupRes = ToTU->noload_lookup(ToName);
2899 EXPECT_EQ(LookupRes.size(), 1u);
2900 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2901
2902 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2903 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2904
2905 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2906 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2907}
2908
2909TEST_P(ImportFriendFunctions, ImportFriendList) {
2910 TranslationUnitDecl *FromTU = getTuDecl(
2911 "struct X { friend void f(); };"
2912 "void f();",
2913 Lang_CXX, "input0.cc");
2914 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2915 FromTU, functionDecl(hasName("f")));
2916
2917 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2918 FromTU, cxxRecordDecl(hasName("X")));
2919 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2920 auto FromFriends = FromClass->friends();
2921 unsigned int FrN = 0;
2922 for (auto Fr : FromFriends) {
2923 ASSERT_EQ(Fr, FromFriend);
2924 ++FrN;
2925 }
2926 ASSERT_EQ(FrN, 1u);
2927
2928 Import(FromFriendF, Lang_CXX);
2929 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2930 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2931 ToTU, cxxRecordDecl(hasName("X")));
2932 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2933 auto ToFriends = ToClass->friends();
2934 FrN = 0;
2935 for (auto Fr : ToFriends) {
2936 EXPECT_EQ(Fr, ToFriend);
2937 ++FrN;
2938 }
2939 EXPECT_EQ(FrN, 1u);
2940}
2941
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002942AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2943 InnerMatcher) {
2944 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2945 return InnerMatcher.matches(*Typedef, Finder, Builder);
2946 return false;
2947}
2948
Gabor Marton19f4f392018-06-25 13:04:37 +00002949TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002950 CodeFiles Samples{{"main.c",
2951 {"void foo();"
2952 "void moo();"
2953 "int main() { foo(); moo(); }",
2954 Lang_C}},
2955
2956 {"foo.c",
2957 {"typedef enum { THING_VALUE } thing_t;"
2958 "void conflict(thing_t type);"
2959 "void foo() { (void)THING_VALUE; }"
2960 "void conflict(thing_t type) {}",
2961 Lang_C}},
2962
2963 {"moo.c",
2964 {"typedef enum { THING_VALUE } thing_t;"
2965 "void conflict(thing_t type);"
2966 "void moo() { conflict(THING_VALUE); }",
2967 Lang_C}}};
2968
2969 auto VerificationMatcher =
2970 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2971 hasTypedefForAnonDecl(hasName("thing_t")));
2972
2973 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2974 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2975
2976 testImportSequence(
2977 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2978 // Just check that there is only one enum decl in the result AST.
2979 "main.c", enumDecl(), VerificationMatcher);
2980
2981 // For different import order, result should be the same.
2982 testImportSequence(
2983 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2984 // Check that there is only one enum decl in the result AST.
2985 "main.c", enumDecl(), VerificationMatcher);
2986}
2987
Peter Szecsice7f3182018-05-07 12:08:27 +00002988const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2989 dependentScopeDeclRefExpr;
2990
Gabor Marton19f4f392018-06-25 13:04:37 +00002991TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002992 MatchVerifier<Decl> Verifier;
2993 testImport("template <typename T> struct S { static T foo; };"
2994 "template <typename T> void declToImport() {"
2995 " (void) S<T>::foo;"
2996 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002997 "void instantiate() { declToImport<int>(); }"
2998 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002999 Lang_CXX11, "", Lang_CXX11, Verifier,
3000 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3001 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
3002
3003 testImport("template <typename T> struct S {"
3004 "template<typename S> static void foo(){};"
3005 "};"
3006 "template <typename T> void declToImport() {"
3007 " S<T>::template foo<T>();"
3008 "}"
3009 "void instantiate() { declToImport<int>(); }",
3010 Lang_CXX11, "", Lang_CXX11, Verifier,
3011 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3012 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
3013}
3014
3015const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
3016 dependentNameType;
3017
Gabor Marton19f4f392018-06-25 13:04:37 +00003018TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003019 MatchVerifier<Decl> Verifier;
3020 testImport("template <typename T> struct declToImport {"
3021 " typedef typename T::type dependent_name;"
3022 "};",
3023 Lang_CXX11, "", Lang_CXX11, Verifier,
3024 classTemplateDecl(has(
3025 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
3026}
3027
Gabor Marton19f4f392018-06-25 13:04:37 +00003028TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003029 MatchVerifier<Decl> Verifier;
3030 testImport("struct S { template <typename T> void mem(); };"
3031 "template <typename U> void declToImport() {"
3032 " S s;"
3033 " s.mem<U>();"
3034 "}"
3035 "void instantiate() { declToImport<int>(); }",
3036 Lang_CXX11, "", Lang_CXX11, Verifier,
3037 functionTemplateDecl(has(functionDecl(has(
3038 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3039}
3040
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003041class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00003042public:
3043 static constexpr auto DefaultCode = R"(
3044 struct A { int x; };
3045 void f() {
3046 A a;
3047 A a1(a);
3048 A a2(A{});
3049 a = a1;
3050 a = A{};
3051 a.~A();
3052 })";
3053
3054 template <typename MatcherType>
3055 void testImportOf(
3056 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3057 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3058 }
3059
3060 template <typename MatcherType>
3061 void testNoImportOf(
3062 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3063 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3064 }
3065
3066private:
3067 template <typename MatcherType>
3068 void test(const MatcherType &MethodMatcher,
3069 const char *Code, unsigned int ExpectedCount) {
3070 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3071
3072 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3073 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3074 ToTU, ClassMatcher);
3075
Balazs Keri2f752ba2018-07-16 14:05:18 +00003076 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003077
3078 {
3079 CXXMethodDecl *Method =
3080 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3081 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00003082 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003083 }
3084
Balazs Keri2f752ba2018-07-16 14:05:18 +00003085 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003086
3087 Decl *ImportedClass = nullptr;
3088 {
3089 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3090 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3091 FromTU, ClassMatcher);
3092 ImportedClass = Import(FromClass, Lang_CXX11);
3093 }
3094
3095 EXPECT_EQ(ToClass, ImportedClass);
3096 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3097 ExpectedCount);
3098 }
3099};
3100
3101TEST_P(ImportImplicitMethods, DefaultConstructor) {
3102 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3103}
3104
3105TEST_P(ImportImplicitMethods, CopyConstructor) {
3106 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3107}
3108
3109TEST_P(ImportImplicitMethods, MoveConstructor) {
3110 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3111}
3112
3113TEST_P(ImportImplicitMethods, Destructor) {
3114 testImportOf(cxxDestructorDecl());
3115}
3116
3117TEST_P(ImportImplicitMethods, CopyAssignment) {
3118 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3119}
3120
3121TEST_P(ImportImplicitMethods, MoveAssignment) {
3122 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3123}
3124
3125TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3126 auto Code = R"(
3127 struct A { A() { int x; } };
3128 )";
3129 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3130}
3131
3132TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3133 auto Code = R"(
3134 struct A { A() = default; };
3135 )";
3136 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3137}
3138
3139TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3140 auto Code = R"(
3141 struct A { A() = delete; };
3142 )";
3143 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3144}
3145
3146TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3147 auto Code = R"(
3148 struct A { void f() { } };
3149 )";
3150 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3151}
3152
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003153TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003154 Decl *ToR1;
3155 {
3156 Decl *FromTU = getTuDecl(
3157 "struct A { };", Lang_CXX, "input0.cc");
3158 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3159 FromTU, cxxRecordDecl(hasName("A")));
3160
3161 ToR1 = Import(FromR, Lang_CXX);
3162 }
3163
3164 Decl *ToR2;
3165 {
3166 Decl *FromTU = getTuDecl(
3167 "struct A { };", Lang_CXX, "input1.cc");
3168 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3169 FromTU, cxxRecordDecl(hasName("A")));
3170
3171 ToR2 = Import(FromR, Lang_CXX);
3172 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003173
Balazs Keric7797c42018-07-11 09:37:24 +00003174 EXPECT_EQ(ToR1, ToR2);
3175}
3176
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003177TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003178 Decl *ToR1;
3179 {
3180 Decl *FromTU = getTuDecl(
3181 "struct A { int x; };", Lang_CXX, "input0.cc");
3182 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3183 FromTU, cxxRecordDecl(hasName("A")));
3184 ToR1 = Import(FromR, Lang_CXX);
3185 }
3186 Decl *ToR2;
3187 {
3188 Decl *FromTU = getTuDecl(
3189 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3190 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3191 FromTU, cxxRecordDecl(hasName("A")));
3192 ToR2 = Import(FromR, Lang_CXX);
3193 }
3194 EXPECT_NE(ToR1, ToR2);
3195}
3196
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003197TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003198 Decl *ToF1;
3199 {
3200 Decl *FromTU = getTuDecl(
3201 "struct A { int x; };", Lang_CXX, "input0.cc");
3202 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3203 FromTU, fieldDecl(hasName("x")));
3204 ToF1 = Import(FromF, Lang_CXX);
3205 }
3206 Decl *ToF2;
3207 {
3208 Decl *FromTU = getTuDecl(
3209 "struct A { int x; };", Lang_CXX, "input1.cc");
3210 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3211 FromTU, fieldDecl(hasName("x")));
3212 ToF2 = Import(FromF, Lang_CXX);
3213 }
3214 EXPECT_EQ(ToF1, ToF2);
3215}
3216
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003217TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003218 Decl *ToF1;
3219 {
3220 Decl *FromTU = getTuDecl(
3221 "struct A { int x; };", Lang_CXX, "input0.cc");
3222 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3223 FromTU, fieldDecl(hasName("x")));
3224 ToF1 = Import(FromF, Lang_CXX);
3225 }
3226 Decl *ToF2;
3227 {
3228 Decl *FromTU = getTuDecl(
3229 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3230 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3231 FromTU, fieldDecl(hasName("x")));
3232 ToF2 = Import(FromF, Lang_CXX);
3233 }
3234 EXPECT_NE(ToF1, ToF2);
3235}
3236
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003237TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003238 Decl *ToM1;
3239 {
3240 Decl *FromTU = getTuDecl(
3241 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3242 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3243 FromTU, functionDecl(hasName("x"), isDefinition()));
3244 ToM1 = Import(FromM, Lang_CXX);
3245 }
3246 Decl *ToM2;
3247 {
3248 Decl *FromTU = getTuDecl(
3249 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3250 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3251 FromTU, functionDecl(hasName("x"), isDefinition()));
3252 ToM2 = Import(FromM, Lang_CXX);
3253 }
3254 EXPECT_EQ(ToM1, ToM2);
3255}
3256
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003257TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003258 Decl *ToM1;
3259 {
3260 Decl *FromTU = getTuDecl(
3261 "struct A { void x(); }; void A::x() { }",
3262 Lang_CXX, "input0.cc");
3263 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3264 FromTU, functionDecl(hasName("x"), isDefinition()));
3265 ToM1 = Import(FromM, Lang_CXX);
3266 }
3267 Decl *ToM2;
3268 {
3269 Decl *FromTU = getTuDecl(
3270 "struct A { void x() const; }; void A::x() const { }",
3271 Lang_CXX, "input1.cc");
3272 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3273 FromTU, functionDecl(hasName("x"), isDefinition()));
3274 ToM2 = Import(FromM, Lang_CXX);
3275 }
3276 EXPECT_NE(ToM1, ToM2);
3277}
3278
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003279TEST_P(ASTImporterOptionSpecificTestBase,
3280 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003281 Decl *FromTU = getTuDecl(
3282 R"(
3283 struct A {
3284 struct {
3285 struct A *next;
3286 } entry0;
3287 struct {
3288 struct A *next;
3289 } entry1;
3290 };
3291 )",
3292 Lang_C, "input0.cc");
3293 auto *From =
3294 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3295
3296 Import(From, Lang_C);
3297
3298 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3299 auto *Entry0 =
3300 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3301 auto *Entry1 =
3302 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3303 auto *R0 = getRecordDecl(Entry0);
3304 auto *R1 = getRecordDecl(Entry1);
3305 EXPECT_NE(R0, R1);
3306 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3307 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3308 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3309 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3310}
3311
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003312TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003313 Decl *FromTU = getTuDecl(
3314 R"(
3315 void f(int X, int Y, bool Z) {
3316 (void)[X, Y, Z] { (void)Z; };
3317 }
3318 )",
3319 Lang_CXX11, "input0.cc");
3320 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3321 FromTU, functionDecl(hasName("f")));
3322 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3323 EXPECT_TRUE(ToF);
3324
3325 CXXRecordDecl *FromLambda =
3326 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3327 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3328
3329 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3330 EXPECT_TRUE(ToLambda);
3331
3332 // Check if the fields of the lambda class are imported in correct order.
3333 unsigned FromIndex = 0u;
3334 for (auto *FromField : FromLambda->fields()) {
3335 ASSERT_FALSE(FromField->getDeclName());
3336 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3337 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003338 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3339 EXPECT_TRUE(ToIndex);
3340 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003341 ++FromIndex;
3342 }
3343
3344 EXPECT_EQ(FromIndex, 3u);
3345}
3346
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003347TEST_P(ASTImporterOptionSpecificTestBase,
3348 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003349 std::string ClassTemplate =
3350 R"(
3351 template <typename T>
3352 struct X {
3353 int a{0}; // FieldDecl with InitListExpr
3354 X(char) : a(3) {} // (1)
3355 X(int) {} // (2)
3356 };
3357 )";
3358 Decl *ToTU = getToTuDecl(ClassTemplate +
3359 R"(
3360 void foo() {
3361 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3362 X<char> xc('c');
3363 }
3364 )", Lang_CXX11);
3365 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3366 ToTU, classTemplateSpecializationDecl(hasName("X")));
3367 // FieldDecl without InitlistExpr:
3368 auto *ToField = *ToSpec->field_begin();
3369 ASSERT_TRUE(ToField);
3370 ASSERT_FALSE(ToField->getInClassInitializer());
3371 Decl *FromTU = getTuDecl(ClassTemplate +
3372 R"(
3373 void bar() {
3374 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3375 X<char> xc(1);
3376 }
3377 )", Lang_CXX11);
3378 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3379 FromTU, classTemplateSpecializationDecl(hasName("X")));
3380 // FieldDecl with InitlistExpr:
3381 auto *FromField = *FromSpec->field_begin();
3382 ASSERT_TRUE(FromField);
3383 ASSERT_TRUE(FromField->getInClassInitializer());
3384
3385 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3386 ASSERT_TRUE(ImportedSpec);
3387 EXPECT_EQ(ImportedSpec, ToSpec);
3388 // After the import, the FieldDecl has to be merged, thus it should have the
3389 // InitListExpr.
3390 EXPECT_TRUE(ToField->getInClassInitializer());
3391}
3392
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003393TEST_P(ASTImporterOptionSpecificTestBase,
3394 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003395 std::string ClassTemplate =
3396 R"(
3397 template <typename T>
3398 struct X {
3399 void f() {}
3400 void g() {}
3401 };
3402 )";
3403 Decl *ToTU = getToTuDecl(ClassTemplate +
3404 R"(
3405 void foo() {
3406 X<char> x;
3407 x.f();
3408 }
3409 )", Lang_CXX11);
3410 Decl *FromTU = getTuDecl(ClassTemplate +
3411 R"(
3412 void bar() {
3413 X<char> x;
3414 x.g();
3415 }
3416 )", Lang_CXX11);
3417 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3418 FromTU, classTemplateSpecializationDecl(hasName("X")));
3419 auto FunPattern = functionDecl(hasName("g"),
3420 hasParent(classTemplateSpecializationDecl()));
3421 auto *FromFun =
3422 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3423 auto *ToFun =
3424 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3425 ASSERT_TRUE(FromFun->hasBody());
3426 ASSERT_FALSE(ToFun->hasBody());
3427 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3428 ASSERT_TRUE(ImportedSpec);
3429 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3430 ToTU, classTemplateSpecializationDecl(hasName("X")));
3431 EXPECT_EQ(ImportedSpec, ToSpec);
3432 EXPECT_TRUE(ToFun->hasBody());
3433}
3434
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003435TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003436 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3437 std::string ClassTemplate =
3438 R"(
3439 template <typename T>
3440 struct X {};
3441 )";
3442 Decl *ToTU = getToTuDecl(ClassTemplate +
3443 R"(
3444 template <>
3445 struct X<char> {
3446 int a;
3447 };
3448 void foo() {
3449 X<char> x;
3450 }
3451 )",
3452 Lang_CXX11);
3453 Decl *FromTU = getTuDecl(ClassTemplate +
3454 R"(
3455 template <>
3456 struct X<char> {
3457 int b;
3458 };
3459 void foo() {
3460 X<char> x;
3461 }
3462 )",
3463 Lang_CXX11);
3464 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3465 FromTU, classTemplateSpecializationDecl(hasName("X")));
3466 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3467
3468 // We expect one (ODR) warning during the import.
3469 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3470
3471 // The second specialization is different from the first, thus it violates
3472 // ODR, consequently we expect to keep the first specialization only, which is
3473 // already in the "To" context.
3474 EXPECT_TRUE(ImportedSpec);
3475 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3476 ToTU, classTemplateSpecializationDecl(hasName("X")));
3477 EXPECT_EQ(ImportedSpec, ToSpec);
3478 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3479 ToTU, classTemplateSpecializationDecl()));
3480}
3481
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003482TEST_P(ASTImporterOptionSpecificTestBase,
3483 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003484 std::string ClassTemplate =
3485 R"(
3486 template <typename T>
3487 struct X {
3488 X(char) {}
3489 X(int) {}
3490 };
3491 )";
3492 Decl *ToTU = getToTuDecl(ClassTemplate +
3493 R"(
3494 void foo() {
3495 X<char> x('c');
3496 }
3497 )", Lang_CXX11);
3498 Decl *FromTU = getTuDecl(ClassTemplate +
3499 R"(
3500 void bar() {
3501 X<char> x(1);
3502 }
3503 )", Lang_CXX11);
3504 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3505 FromTU, classTemplateSpecializationDecl(hasName("X")));
3506 // Match the void(int) ctor.
3507 auto CtorPattern =
3508 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3509 hasParent(classTemplateSpecializationDecl()));
3510 auto *FromCtor =
3511 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3512 auto *ToCtor =
3513 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3514 ASSERT_TRUE(FromCtor->hasBody());
3515 ASSERT_FALSE(ToCtor->hasBody());
3516 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3517 ASSERT_TRUE(ImportedSpec);
3518 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3519 ToTU, classTemplateSpecializationDecl(hasName("X")));
3520 EXPECT_EQ(ImportedSpec, ToSpec);
3521 EXPECT_TRUE(ToCtor->hasBody());
3522}
3523
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003524TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003525 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3526 auto Code =
3527 R"(
3528 // primary template
3529 template<class T1, class T2, int I>
3530 class A {};
3531
3532 // partial specialization
3533 template<class T, int I>
3534 class A<T, T*, I> {};
3535 )";
3536 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3537 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3538 auto *FromSpec =
3539 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3540 FromTU, classTemplatePartialSpecializationDecl());
3541 auto *ToSpec =
3542 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3543 ToTU, classTemplatePartialSpecializationDecl());
3544
3545 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3546 EXPECT_EQ(ImportedSpec, ToSpec);
3547 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3548 ToTU, classTemplatePartialSpecializationDecl()));
3549}
3550
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003551TEST_P(ASTImporterOptionSpecificTestBase,
3552 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003553 auto Code =
3554 R"(
3555 // primary template
3556 template<class T1, class T2, int I>
3557 class A {};
3558
3559 // full specialization
3560 template<>
3561 class A<int, int, 1> {};
3562 )";
3563 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3564 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3565 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3566 FromTU, classTemplateSpecializationDecl());
3567 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3568 ToTU, classTemplateSpecializationDecl());
3569
3570 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3571 EXPECT_EQ(ImportedSpec, ToSpec);
3572 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3573 ToTU, classTemplateSpecializationDecl()));
3574}
3575
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003576TEST_P(ASTImporterOptionSpecificTestBase,
3577 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003578 std::string PrimaryTemplate =
3579 R"(
3580 template<class T1, class T2, int I>
3581 class A {};
3582 )";
3583 auto PartialSpec =
3584 R"(
3585 template<class T, int I>
3586 class A<T, T*, I> {};
3587 )";
3588 auto FullSpec =
3589 R"(
3590 template<>
3591 class A<int, int, 1> {};
3592 )";
3593 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3594 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3595 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3596 FromTU, classTemplateSpecializationDecl());
3597
3598 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3599 EXPECT_TRUE(ImportedSpec);
3600 // Check the number of partial specializations.
3601 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3602 ToTU, classTemplatePartialSpecializationDecl()));
3603 // Check the number of full specializations.
3604 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3605 ToTU, classTemplateSpecializationDecl(
3606 unless(classTemplatePartialSpecializationDecl()))));
3607}
3608
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003609TEST_P(ASTImporterOptionSpecificTestBase,
3610 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003611 Decl *TU = getTuDecl(
3612 R"(
3613 const int &init();
3614 void foo() { const int &a{init()}; }
3615 )", Lang_CXX11, "input0.cc");
3616 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3617 ASSERT_TRUE(FromD->getAnyInitializer());
3618 auto *InitExpr = FromD->getAnyInitializer();
3619 ASSERT_TRUE(InitExpr);
3620 ASSERT_TRUE(InitExpr->isGLValue());
3621
3622 auto *ToD = Import(FromD, Lang_CXX11);
3623 EXPECT_TRUE(ToD);
3624 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3625 EXPECT_TRUE(ToInitExpr);
3626 EXPECT_TRUE(ToInitExpr->isGLValue());
3627}
3628
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003629struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003630
3631TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3632 Decl *FromTU = getTuDecl(
3633 R"(
3634 struct A {
3635 static const int a = 1 + 2;
3636 };
3637 const int A::a;
3638 )", Lang_CXX, "input1.cc");
3639
3640 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3641 FromTU, varDecl(hasName("a"))); // Decl with init
3642 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3643 FromTU, varDecl(hasName("a"))); // Decl with definition
3644 ASSERT_NE(FromDWithInit, FromDWithDef);
3645 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3646
3647 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3648 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3649 ASSERT_TRUE(ToD0);
3650 ASSERT_TRUE(ToD1);
3651 EXPECT_NE(ToD0, ToD1);
3652 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3653}
3654
3655TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3656 auto StructA =
3657 R"(
3658 struct A {
3659 static const int a = 1 + 2;
3660 };
3661 )";
3662 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3663 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3664 "input1.cc");
3665
3666 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3667 FromTU, varDecl(hasName("a"))); // Decl with init
3668 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3669 FromTU, varDecl(hasName("a"))); // Decl with definition
3670 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3671 ASSERT_TRUE(FromDWithInit->getInit());
3672 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3673 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3674 ASSERT_FALSE(FromDWithDef->getInit());
3675
3676 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3677 ToTU, varDecl(hasName("a"))); // Decl with init
3678 ASSERT_TRUE(ToD->getInit());
3679 ASSERT_FALSE(ToD->getDefinition());
3680
3681 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3682 EXPECT_TRUE(ImportedD->getAnyInitializer());
3683 EXPECT_TRUE(ImportedD->getDefinition());
3684}
3685
3686TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3687 auto StructA =
3688 R"(
3689 struct A {
3690 static const int a;
3691 };
3692 )";
3693 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3694 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3695 Lang_CXX, "input1.cc");
3696
3697 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3698 FromTU, varDecl(hasName("a")));
3699 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3700 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3701 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3702 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3703 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3704 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3705 ASSERT_TRUE(FromDWithDef->getInit());
3706
3707 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3708 ToTU, varDecl(hasName("a")));
3709 ASSERT_FALSE(ToD->getInit());
3710 ASSERT_FALSE(ToD->getDefinition());
3711
3712 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3713 EXPECT_TRUE(ImportedD->getAnyInitializer());
3714 EXPECT_TRUE(ImportedD->getDefinition());
3715}
3716
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003717struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003718
Gabor Marton54058b52018-12-17 13:53:12 +00003719TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3720 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3721 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3722 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3723 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3724 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3725
3726 Decl *ImportedDef = Import(FromDef, Lang_C);
3727
3728 EXPECT_NE(ImportedDef, ToProto);
3729 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3730 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3731 EXPECT_TRUE(ImportedDef == ToDef);
3732 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3733 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3734 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3735}
3736
3737TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3738 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3739 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3740 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3741 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3742 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3743
3744 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3745
3746 EXPECT_NE(ImportedDef, ToProto);
3747 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3748 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3749 EXPECT_TRUE(ImportedDef == ToDef);
3750 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3751 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3752 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3753}
3754
3755TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3756 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3757 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3758 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3759 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3760 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3761
3762 Decl *ImportedProto = Import(FromProto, Lang_C);
3763 Decl *ImportedDef = Import(FromDef, Lang_C);
3764 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3765
3766 EXPECT_NE(ImportedDef, ImportedProto);
3767 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3768 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3769 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3770 EXPECT_TRUE(ImportedDef == ToDef);
3771 EXPECT_TRUE(ImportedProto == ToProto);
3772 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3773 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3774 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3775}
3776
Gabor Martonfc03fc62019-02-18 11:09:56 +00003777// FIXME put these structs and the tests rely on them into their own separate
3778// test file!
3779struct Function {
3780 using DeclTy = FunctionDecl;
3781 static constexpr auto *Prototype = "void X();";
3782 static constexpr auto *Definition = "void X() {}";
3783 BindableMatcher<Decl> getPattern() {
3784 return functionDecl(hasName("X"), unless(isImplicit()));
3785 }
3786};
Gabor Marton7df342a2018-12-17 12:42:12 +00003787
Gabor Martonfc03fc62019-02-18 11:09:56 +00003788struct Class {
3789 using DeclTy = CXXRecordDecl;
3790 static constexpr auto *Prototype = "class X;";
3791 static constexpr auto *Definition = "class X {};";
3792 BindableMatcher<Decl> getPattern() {
3793 return cxxRecordDecl(hasName("X"), unless(isImplicit()));
3794 }
3795};
Gabor Marton7df342a2018-12-17 12:42:12 +00003796
Gabor Martonfc03fc62019-02-18 11:09:56 +00003797struct Variable {
3798 using DeclTy = VarDecl;
3799 static constexpr auto *Prototype = "extern int X;";
3800 static constexpr auto *Definition = "int X;";
3801 BindableMatcher<Decl> getPattern() {
3802 return varDecl(hasName("X"));
3803 }
3804};
Gabor Marton7df342a2018-12-17 12:42:12 +00003805
Gabor Martonfc03fc62019-02-18 11:09:56 +00003806struct FunctionTemplate {
3807 using DeclTy = FunctionTemplateDecl;
3808 static constexpr auto *Prototype = "template <class T> void X();";
3809 static constexpr auto *Definition =
3810 R"(
3811 template <class T> void X() {};
3812 // Explicit instantiation is a must because of -fdelayed-template-parsing:
3813 template void X<int>();
3814 )";
3815 BindableMatcher<Decl> getPattern() {
3816 return functionTemplateDecl(hasName("X"), unless(isImplicit()));
3817 }
3818};
Gabor Marton7df342a2018-12-17 12:42:12 +00003819
Gabor Martonfc03fc62019-02-18 11:09:56 +00003820struct ClassTemplate {
3821 using DeclTy = ClassTemplateDecl;
3822 static constexpr auto *Prototype = "template <class T> class X;";
3823 static constexpr auto *Definition = "template <class T> class X {};";
3824 BindableMatcher<Decl> getPattern() {
3825 return classTemplateDecl(hasName("X"), unless(isImplicit()));
3826 }
3827};
Gabor Marton7df342a2018-12-17 12:42:12 +00003828
Gabor Martonfc03fc62019-02-18 11:09:56 +00003829struct FunctionTemplateSpec {
3830 using DeclTy = FunctionDecl;
3831 static constexpr auto *Prototype =
3832 R"(
3833 // Proto of the primary template.
3834 template <class T>
3835 void X();
3836 // Proto of the specialization.
3837 template <>
3838 void X<int>();
3839 )";
3840 static constexpr auto *Definition =
3841 R"(
3842 // Proto of the primary template.
3843 template <class T>
3844 void X();
3845 // Specialization and definition.
3846 template <>
3847 void X<int>() {}
3848 )";
3849 BindableMatcher<Decl> getPattern() {
3850 return functionDecl(hasName("X"), isExplicitTemplateSpecialization());
3851 }
3852};
Gabor Marton7df342a2018-12-17 12:42:12 +00003853
Gabor Martonfc03fc62019-02-18 11:09:56 +00003854template <typename TypeParam>
3855struct RedeclChain : ASTImporterOptionSpecificTestBase {
Gabor Marton7df342a2018-12-17 12:42:12 +00003856
Gabor Martonfc03fc62019-02-18 11:09:56 +00003857 using DeclTy = typename TypeParam::DeclTy;
3858 std::string getPrototype() { return TypeParam::Prototype; }
3859 std::string getDefinition() { return TypeParam::Definition; }
3860 BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); }
Gabor Marton7df342a2018-12-17 12:42:12 +00003861
Gabor Martonfc03fc62019-02-18 11:09:56 +00003862 void
3863 TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() {
3864 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX);
3865 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3866 ASSERT_FALSE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003867
Gabor Martonfc03fc62019-02-18 11:09:56 +00003868 Decl *ImportedD = Import(FromD, Lang_CXX);
3869 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003870
Gabor Martonfc03fc62019-02-18 11:09:56 +00003871 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
3872 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3873 EXPECT_TRUE(ImportedD == ToD);
3874 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
3875 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
3876 EXPECT_TRUE(ToT->getTemplatedDecl());
3877 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003878
Gabor Martonfc03fc62019-02-18 11:09:56 +00003879 void TypedTest_DefinitionShouldBeImportedAsADefinition() {
3880 Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
3881 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3882 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003883
Gabor Martonfc03fc62019-02-18 11:09:56 +00003884 Decl *ImportedD = Import(FromD, Lang_CXX);
3885 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003886
Gabor Martonfc03fc62019-02-18 11:09:56 +00003887 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
3888 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3889 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
3890 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
3891 EXPECT_TRUE(ToT->getTemplatedDecl());
3892 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003893
Gabor Martonfc03fc62019-02-18 11:09:56 +00003894 void TypedTest_ImportPrototypeAfterImportedPrototype() {
3895 Decl *FromTU = getTuDecl(
3896 getPrototype() + getPrototype(), Lang_CXX);
3897 auto *From0 =
3898 FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3899 auto *From1 = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
3900 ASSERT_FALSE(From0->isThisDeclarationADefinition());
3901 ASSERT_FALSE(From1->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003902
Gabor Martonfc03fc62019-02-18 11:09:56 +00003903 Decl *Imported0 = Import(From0, Lang_CXX);
3904 Decl *Imported1 = Import(From1, Lang_CXX);
3905 Decl *ToTU = Imported0->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003906
Gabor Martonfc03fc62019-02-18 11:09:56 +00003907 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
3908 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
3909 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3910 EXPECT_TRUE(Imported0 == To0);
3911 EXPECT_TRUE(Imported1 == To1);
3912 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3913 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3914 EXPECT_EQ(To1->getPreviousDecl(), To0);
3915 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0)) {
3916 auto *ToT1 = cast<TemplateDecl>(To1);
3917 ASSERT_TRUE(ToT0->getTemplatedDecl());
3918 ASSERT_TRUE(ToT1->getTemplatedDecl());
3919 EXPECT_EQ(ToT1->getTemplatedDecl()->getPreviousDecl(),
3920 ToT0->getTemplatedDecl());
3921 }
3922 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003923
Gabor Martonfc03fc62019-02-18 11:09:56 +00003924 void TypedTest_ImportDefinitionAfterImportedPrototype() {
3925 Decl *FromTU = getTuDecl(
3926 getPrototype() + getDefinition(), Lang_CXX);
3927 auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3928 auto *FromDef = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
3929 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
3930 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003931
Gabor Martonfc03fc62019-02-18 11:09:56 +00003932 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3933 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3934 Decl *ToTU = ImportedProto->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003935
Gabor Martonfc03fc62019-02-18 11:09:56 +00003936 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
3937 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
3938 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3939 EXPECT_TRUE(ImportedProto == ToProto);
3940 EXPECT_TRUE(ImportedDef == ToDef);
3941 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3942 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3943 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3944 if (auto *ToProtoT = dyn_cast<TemplateDecl>(ToProto)) {
3945 auto *ToDefT = cast<TemplateDecl>(ToDef);
3946 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
3947 ASSERT_TRUE(ToDefT->getTemplatedDecl());
3948 EXPECT_EQ(ToDefT->getTemplatedDecl()->getPreviousDecl(),
3949 ToProtoT->getTemplatedDecl());
3950 }
3951 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003952
Gabor Martonfc03fc62019-02-18 11:09:56 +00003953 void TypedTest_ImportPrototypeAfterImportedDefinition() {
3954 Decl *FromTU = getTuDecl(
3955 getDefinition() + getPrototype(), Lang_CXX);
3956 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3957 auto *FromProto = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
3958 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
3959 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003960
Gabor Martonfc03fc62019-02-18 11:09:56 +00003961 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3962 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3963 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3964
3965 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
3966 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
3967 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3968 EXPECT_TRUE(ImportedDef == ToDef);
3969 EXPECT_TRUE(ImportedProto == ToProto);
3970 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3971 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3972 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
3973 if (auto *ToDefT = dyn_cast<TemplateDecl>(ToDef)) {
3974 auto *ToProtoT = cast<TemplateDecl>(ToProto);
3975 ASSERT_TRUE(ToDefT->getTemplatedDecl());
3976 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
3977 EXPECT_EQ(ToProtoT->getTemplatedDecl()->getPreviousDecl(),
3978 ToDefT->getTemplatedDecl());
3979 }
3980 }
3981
3982 void TypedTest_ImportPrototypes() {
3983 Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
3984 Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
3985 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
3986 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
3987 ASSERT_FALSE(From0->isThisDeclarationADefinition());
3988 ASSERT_FALSE(From1->isThisDeclarationADefinition());
3989
3990 Decl *Imported0 = Import(From0, Lang_CXX);
3991 Decl *Imported1 = Import(From1, Lang_CXX);
3992 Decl *ToTU = Imported0->getTranslationUnitDecl();
3993
3994 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
3995 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
3996 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3997 EXPECT_TRUE(Imported0 == To0);
3998 EXPECT_TRUE(Imported1 == To1);
3999 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4000 EXPECT_FALSE(To1->isThisDeclarationADefinition());
4001 EXPECT_EQ(To1->getPreviousDecl(), To0);
4002 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0)) {
4003 auto *ToT1 = cast<TemplateDecl>(To1);
4004 ASSERT_TRUE(ToT0->getTemplatedDecl());
4005 ASSERT_TRUE(ToT1->getTemplatedDecl());
4006 EXPECT_EQ(ToT1->getTemplatedDecl()->getPreviousDecl(),
4007 ToT0->getTemplatedDecl());
4008 }
4009 // Extra check for specializations.
4010 // FIXME Add this check to other tests too (possibly factor out into a
4011 // function), when they start to pass.
4012 if (auto *From0F = dyn_cast<FunctionDecl>(From0)) {
4013 auto *To0F = cast<FunctionDecl>(To0);
4014 if (From0F->getTemplatedKind() ==
4015 FunctionDecl::TK_FunctionTemplateSpecialization) {
4016 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4017 ToTU, functionTemplateDecl());
4018 auto *FirstSpecD = *(TemplateD->spec_begin());
4019 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0F->getCanonicalDecl());
4020 }
4021 }
4022 }
4023
4024 void TypedTest_ImportDefinitions() {
4025 Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4026 Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4027 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4028 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4029 ASSERT_TRUE(From0->isThisDeclarationADefinition());
4030 ASSERT_TRUE(From1->isThisDeclarationADefinition());
4031
4032 Decl *Imported0 = Import(From0, Lang_CXX);
4033 Decl *Imported1 = Import(From1, Lang_CXX);
4034 Decl *ToTU = Imported0->getTranslationUnitDecl();
4035
4036 EXPECT_EQ(Imported0, Imported1);
4037 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4038 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4039 EXPECT_TRUE(Imported0 == To0);
4040 EXPECT_TRUE(To0->isThisDeclarationADefinition());
4041 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0))
4042 EXPECT_TRUE(ToT0->getTemplatedDecl());
4043 }
4044
4045 void TypedTest_ImportDefinitionThenPrototype() {
4046 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4047 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4048 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4049 auto *FromProto =
4050 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4051 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4052 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4053
4054 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4055 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4056 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4057
4058 EXPECT_NE(ImportedDef, ImportedProto);
4059 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4060 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4061 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4062 EXPECT_TRUE(ImportedDef == ToDef);
4063 EXPECT_TRUE(ImportedProto == ToProto);
4064 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4065 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4066 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
4067 if (auto *ToDefT = dyn_cast<TemplateDecl>(ToDef)) {
4068 auto *ToProtoT = cast<TemplateDecl>(ToProto);
4069 ASSERT_TRUE(ToDefT->getTemplatedDecl());
4070 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
4071 EXPECT_EQ(ToProtoT->getTemplatedDecl()->getPreviousDecl(),
4072 ToDefT->getTemplatedDecl());
4073 }
4074 }
4075
4076 void TypedTest_ImportPrototypeThenDefinition() {
4077 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4078 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4079 auto *FromProto =
4080 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4081 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4082 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4083 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4084
4085 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4086 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4087 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4088
4089 EXPECT_NE(ImportedDef, ImportedProto);
4090 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4091 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4092 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4093 EXPECT_TRUE(ImportedDef == ToDef);
4094 EXPECT_TRUE(ImportedProto == ToProto);
4095 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4096 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4097 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4098 if (auto *ToDefT = dyn_cast<TemplateDecl>(ToDef)) {
4099 auto *ToProtoT = cast<TemplateDecl>(ToProto);
4100 ASSERT_TRUE(ToDefT->getTemplatedDecl());
4101 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
4102 EXPECT_EQ(ToDefT->getTemplatedDecl()->getPreviousDecl(),
4103 ToProtoT->getTemplatedDecl());
4104 }
4105 }
4106
4107 void TypedTest_WholeRedeclChainIsImportedAtOnce() {
4108 Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
4109 auto *FromD = // Definition
4110 LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4111 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
4112
4113 Decl *ImportedD = Import(FromD, Lang_CXX);
4114 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4115
4116 // The whole redecl chain is imported at once.
4117 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4118 EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition());
4119 }
4120
4121 void TypedTest_ImportPrototypeThenProtoAndDefinition() {
4122 {
4123 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4124 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4125 Import(FromD, Lang_CXX);
4126 }
4127 {
4128 Decl *FromTU =
4129 getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc");
4130 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4131 Import(FromD, Lang_CXX);
4132 }
4133
4134 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4135
4136 ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u);
4137 DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4138 EXPECT_FALSE(ProtoD->isThisDeclarationADefinition());
4139
4140 DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4141 EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition());
4142
4143 EXPECT_TRUE(DefinitionD->getPreviousDecl());
4144 EXPECT_FALSE(
4145 DefinitionD->getPreviousDecl()->isThisDeclarationADefinition());
4146 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
4147 }
4148};
4149
4150#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \
4151 NamePrefix, TestCase) \
4152 using BaseTemplate##TypeParam = BaseTemplate<TypeParam>; \
4153 TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \
4154 TypedTest_##TestCase(); \
4155 }
4156
4157ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4158 RedeclChain, Function, ,
4159 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition);
4160ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4161 RedeclChain, Class, ,
4162 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition);
4163ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4164 RedeclChain, Variable, ,
4165 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition);
4166// FIXME Enable this test, once we import function templates chains correctly.
4167ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4168 RedeclChain, FunctionTemplate, DISABLED_,
4169 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition);
4170ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4171 RedeclChain, ClassTemplate, ,
4172 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition);
4173ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4174 RedeclChain, FunctionTemplateSpec, ,
4175 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition);
4176
4177ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4178 RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition);
4179ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4180 RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition);
4181ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4182 RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition);
4183// FIXME Enable this test, once we import function templates chains correctly.
4184ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4185 RedeclChain, FunctionTemplate, DISABLED_,
4186 DefinitionShouldBeImportedAsADefinition);
4187ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4188 RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition);
4189ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4190 RedeclChain, FunctionTemplateSpec, ,
4191 DefinitionShouldBeImportedAsADefinition);
4192
4193ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
4194 ImportPrototypeAfterImportedPrototype);
4195ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
4196 ImportPrototypeAfterImportedPrototype);
4197ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
4198 ImportPrototypeAfterImportedPrototype);
4199// FIXME Enable this test, once we import function templates chains correctly.
4200ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4201 DISABLED_,
4202 ImportPrototypeAfterImportedPrototype);
4203ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
4204 ImportPrototypeAfterImportedPrototype);
4205ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4206 ImportPrototypeAfterImportedPrototype);
4207
4208ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
4209 ImportDefinitionAfterImportedPrototype);
4210// FIXME This does not pass, possible error with Class import.
4211ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, DISABLED_,
4212 ImportDefinitionAfterImportedPrototype);
4213ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
4214 ImportDefinitionAfterImportedPrototype);
4215// FIXME Enable this test, once we import function templates chains correctly.
4216ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4217 DISABLED_,
4218 ImportDefinitionAfterImportedPrototype);
4219// FIXME This does not pass, possible error with ClassTemplate import.
4220ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, DISABLED_,
4221 ImportDefinitionAfterImportedPrototype);
4222ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4223 ImportDefinitionAfterImportedPrototype);
4224
4225ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
4226 ImportPrototypeAfterImportedDefinition);
4227// FIXME This does not pass, possible error with Class import.
4228ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, DISABLED_,
4229 ImportPrototypeAfterImportedDefinition);
4230ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
4231 ImportPrototypeAfterImportedDefinition);
4232// FIXME Enable this test, once we import function templates chains correctly.
4233ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4234 DISABLED_,
4235 ImportPrototypeAfterImportedDefinition);
4236// FIXME This does not pass, possible error with ClassTemplate import.
4237ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, DISABLED_,
4238 ImportPrototypeAfterImportedDefinition);
4239ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4240 ImportPrototypeAfterImportedDefinition);
4241
4242ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
4243 ImportPrototypes);
4244ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes);
4245ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
4246 ImportPrototypes);
4247// FIXME Enable this test, once we import function templates chains correctly.
4248ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4249 DISABLED_, ImportPrototypes);
4250ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
4251 ImportPrototypes);
4252// FIXME This does not pass, possible error with Spec import.
4253ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4254 DISABLED_, ImportPrototypes);
4255
4256ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
4257 ImportDefinitions);
4258ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
4259 ImportDefinitions);
4260ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
4261 ImportDefinitions);
4262// FIXME Enable this test, once we import function templates chains correctly.
4263ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4264 DISABLED_, ImportDefinitions);
4265ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
4266 ImportDefinitions);
4267// FIXME This does not pass, possible error with Spec import.
4268ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4269 DISABLED_, ImportDefinitions);
4270
4271ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
4272 ImportDefinitionThenPrototype);
4273ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
4274 ImportDefinitionThenPrototype);
4275ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
4276 ImportDefinitionThenPrototype);
4277// FIXME Enable this test, once we import function templates chains correctly.
4278ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4279 DISABLED_,
4280 ImportDefinitionThenPrototype);
4281ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
4282 ImportDefinitionThenPrototype);
4283// FIXME This does not pass, possible error with Spec import.
4284ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4285 DISABLED_,
4286 ImportDefinitionThenPrototype);
4287
4288ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
4289 ImportPrototypeThenDefinition);
4290ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
4291 ImportPrototypeThenDefinition);
4292ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
4293 ImportPrototypeThenDefinition);
4294// FIXME Enable this test, once we import function templates chains correctly.
4295ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4296 DISABLED_,
4297 ImportPrototypeThenDefinition);
4298ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
4299 ImportPrototypeThenDefinition);
4300// FIXME This does not pass, possible error with Spec import.
4301ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4302 DISABLED_,
4303 ImportPrototypeThenDefinition);
4304
4305ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
4306 WholeRedeclChainIsImportedAtOnce);
4307ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
4308 WholeRedeclChainIsImportedAtOnce);
4309// FIXME Enable this test, once we import function templates chains correctly.
4310ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4311 DISABLED_,
4312 WholeRedeclChainIsImportedAtOnce);
4313ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
4314 WholeRedeclChainIsImportedAtOnce);
4315
4316ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
4317 ImportPrototypeThenProtoAndDefinition);
4318ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
4319 ImportPrototypeThenProtoAndDefinition);
4320// FIXME Enable this test, once we import function templates chains correctly.
4321ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4322 DISABLED_,
4323 ImportPrototypeThenProtoAndDefinition);
4324// FIXME This does not pass, possible error with Spec import.
4325ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4326 DISABLED_,
4327 ImportPrototypeThenProtoAndDefinition);
4328
4329INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction,
4330 DefaultTestValuesForRunOptions, );
4331INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass,
4332 DefaultTestValuesForRunOptions, );
4333INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable,
4334 DefaultTestValuesForRunOptions, );
4335INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
4336 DefaultTestValuesForRunOptions, );
4337INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
4338 DefaultTestValuesForRunOptions, );
4339INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
4340 DefaultTestValuesForRunOptions, );
4341
4342
Gabor Marton7df342a2018-12-17 12:42:12 +00004343
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004344struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00004345
4346TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4347 Decl *FromTU = getTuDecl(
4348 R"(
4349 class A {
4350 template <int I> class F {};
4351 class X {
4352 template <int I> friend class F;
4353 };
4354 };
4355 )",
4356 Lang_CXX, "input0.cc");
4357
4358 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4359 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4360 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4361 FromTU, cxxRecordDecl(hasName("F")));
4362
4363 ASSERT_TRUE(FromClass);
4364 ASSERT_TRUE(FromFriendClass);
4365 ASSERT_NE(FromClass, FromFriendClass);
4366 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4367 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4368 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4369 FromClass->getDescribedClassTemplate());
4370
4371 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
4372 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
4373
4374 EXPECT_TRUE(ToClass);
4375 EXPECT_TRUE(ToFriendClass);
4376 EXPECT_NE(ToClass, ToFriendClass);
4377 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4378 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4379 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4380 ToClass->getDescribedClassTemplate());
4381}
4382
4383TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4384 Decl *FromTu = getTuDecl(
4385 R"(
4386 class declToImport {
4387 friend class declToImport;
4388 };
4389 )",
4390 Lang_CXX, "input.cc");
4391
4392 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4393 FromTu, cxxRecordDecl(hasName("declToImport")));
4394 auto *ToD = Import(FromD, Lang_CXX);
4395 auto Pattern = cxxRecordDecl(has(friendDecl()));
4396 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4397 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4398}
4399
4400TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4401 Decl *FromTu = getTuDecl(
4402 R"(
4403 template<class A> class declToImport {
4404 template<class A1> friend class declToImport;
4405 };
4406 )",
4407 Lang_CXX, "input.cc");
4408
4409 auto *FromD =
4410 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
4411 auto *ToD = Import(FromD, Lang_CXX);
4412
4413 auto Pattern = classTemplateDecl(
4414 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4415 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4416 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4417
4418 auto *Class =
4419 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
4420 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4421 EXPECT_NE(Friend->getFriendDecl(), Class);
4422 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
4423}
4424
4425TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4426 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
4427
4428 ClassTemplateSpecializationDecl *Imported1;
4429 {
4430 Decl *FromTU = getTuDecl("template<class T> class X;"
4431 "struct Y { friend class X<int>; };",
4432 Lang_CXX, "input0.cc");
4433 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4434 FromTU, Pattern);
4435
4436 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4437 }
4438 ClassTemplateSpecializationDecl *Imported2;
4439 {
4440 Decl *FromTU = getTuDecl("template<class T> class X;"
4441 "template<> class X<int>{};"
4442 "struct Z { friend class X<int>; };",
4443 Lang_CXX, "input1.cc");
4444 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4445 FromTU, Pattern);
4446
4447 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4448 }
4449
4450 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4451 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4452 2u);
4453 ASSERT_TRUE(Imported2->getPreviousDecl());
4454 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4455}
4456
4457TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4458 Decl *FromTU0 = getTuDecl(
4459 R"(
4460 class X {
4461 class Y;
4462 };
4463 class X::Y {
4464 template <typename T>
4465 friend class F; // The decl context of F is the global namespace.
4466 };
4467 )",
4468 Lang_CXX, "input0.cc");
4469 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4470 FromTU0, classTemplateDecl(hasName("F")));
4471 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4472 Decl *FromTU1 = getTuDecl(
4473 R"(
4474 template <typename T>
4475 class F {};
4476 )",
4477 Lang_CXX, "input1.cc");
4478 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4479 FromTU1, classTemplateDecl(hasName("F")));
4480 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4481 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4482 Imported1->getTemplatedDecl()->getTypeForDecl());
4483}
4484
4485TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4486 Decl *From, *To;
4487 std::tie(From, To) =
4488 getImportedDecl("class declToImport {};", Lang_CXX,
4489 "class Y { friend class declToImport; };", Lang_CXX);
4490 auto *Imported = cast<CXXRecordDecl>(To);
4491
4492 EXPECT_TRUE(Imported->getPreviousDecl());
4493}
4494
4495TEST_P(ImportFriendClasses,
4496 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4497 Decl *ToTU = getToTuDecl(
4498 R"(
4499 class X {
4500 class Y;
4501 };
4502 class X::Y {
4503 template <typename T>
4504 friend class F; // The decl context of F is the global namespace.
4505 };
4506 )",
4507 Lang_CXX);
4508 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4509 ToTU, classTemplateDecl(hasName("F")));
4510 Decl *FromTU = getTuDecl(
4511 R"(
4512 template <typename T>
4513 class F {};
4514 )",
4515 Lang_CXX, "input0.cc");
4516 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4517 FromTU, classTemplateDecl(hasName("F")));
4518 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4519 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4520 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4521 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4522 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4523}
4524
4525TEST_P(ImportFriendClasses,
4526 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4527 Decl *FromTU0 = getTuDecl(
4528 R"(
4529 class X {
4530 class Y;
4531 };
4532 class X::Y {
4533 template <typename T>
4534 friend class F; // The decl context of F is the global namespace.
4535 };
4536 )",
4537 Lang_CXX, "input0.cc");
4538 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4539 FromTU0, classTemplateDecl(hasName("F")));
4540 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4541 Decl *FromTU1 = getTuDecl(
4542 R"(
4543 template <typename T>
4544 class F {};
4545 )",
4546 Lang_CXX, "input1.cc");
4547 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4548 FromTU1, classTemplateDecl(hasName("F")));
4549 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4550 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4551 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4552 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4553 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4554}
4555
4556TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4557 Decl *FromTU0 = getTuDecl(
4558 R"(
4559 class X {
4560 class Y;
4561 };
4562 class X::Y {
4563 friend class F; // The decl context of F is the global namespace.
4564 };
4565 )",
4566 Lang_CXX, "input0.cc");
4567 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4568 QualType FT = Friend->getFriendType()->getType();
4569 FT = FromTU0->getASTContext().getCanonicalType(FT);
4570 auto *Fwd = cast<TagType>(FT)->getDecl();
4571 auto *ImportedFwd = Import(Fwd, Lang_CXX);
4572 Decl *FromTU1 = getTuDecl(
4573 R"(
4574 class F {};
4575 )",
4576 Lang_CXX, "input1.cc");
4577 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4578 FromTU1, cxxRecordDecl(hasName("F")));
4579 auto *ImportedDef = Import(Definition, Lang_CXX);
4580 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4581 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4582}
4583
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004584TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00004585 auto *Code = R"(
4586 template <class T>
4587 struct X {
4588 friend void foo(){}
4589 };
4590 )";
4591 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4592 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4593 ToTU, functionDecl(hasName("foo")));
4594
4595 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4596 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4597 FromTU, functionDecl(hasName("foo")));
4598 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4599 EXPECT_EQ(ImportedFoo, ToFoo);
4600}
4601
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004602struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00004603
4604TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4605 Decl *TU = getTuDecl(
4606 R"(
4607 namespace NS {
4608
4609 template <typename T>
4610 struct S {};
4611 template struct S<int>;
4612
4613 inline namespace INS {
4614 template <typename T>
4615 struct S {};
4616 template struct S<int>;
4617 }
4618
4619 }
4620 )", Lang_CXX11, "input0.cc");
4621 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4622 TU, namespaceDecl());
4623 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4624 TU, classTemplateSpecializationDecl());
4625 ASSERT_TRUE(NS->containsDecl(Spec));
4626
4627 NS->removeDecl(Spec);
4628 EXPECT_FALSE(NS->containsDecl(Spec));
4629}
4630
Gabor Marton7df342a2018-12-17 12:42:12 +00004631TEST_P(DeclContextTest,
4632 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4633 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4634 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4635 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4636
4637 // Investigate the list.
4638 auto *DC = A0->getDeclContext();
4639 ASSERT_TRUE(DC->containsDecl(A0));
4640 ASSERT_TRUE(DC->containsDecl(A1));
4641
4642 // Investigate the lookup table.
4643 auto *Map = DC->getLookupPtr();
4644 ASSERT_TRUE(Map);
4645 auto I = Map->find(A0->getDeclName());
4646 ASSERT_NE(I, Map->end());
4647 StoredDeclsList &L = I->second;
4648 // The lookup table contains the most recent decl of A.
4649 ASSERT_NE(L.getAsDecl(), A0);
4650 ASSERT_EQ(L.getAsDecl(), A1);
4651
4652 ASSERT_TRUE(L.getAsDecl());
4653 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4654 // The point here is to have a Vec with only one element, which is not the
4655 // one we are going to delete from the DC later.
4656 L.setHasExternalDecls();
4657 ASSERT_TRUE(L.getAsVector());
4658 ASSERT_EQ(1u, L.getAsVector()->size());
4659
4660 // This asserts in the old implementation.
4661 DC->removeDecl(A0);
4662 EXPECT_FALSE(DC->containsDecl(A0));
4663}
4664
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004665struct ImportFunctionTemplateSpecializations
4666 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004667
4668TEST_P(ImportFunctionTemplateSpecializations,
4669 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4670
4671 Decl *FromTU = getTuDecl(
4672 R"(
4673 template<class T>
4674 int f() { return 0; }
4675 void foo() { f<int>(); }
4676 )",
4677 Lang_CXX, "input0.cc");
4678
4679 // Check that the function template instantiation is NOT the child of the TU.
4680 auto Pattern = translationUnitDecl(
4681 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4682 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4683
4684 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4685 FromTU, functionDecl(hasName("foo")));
4686 ASSERT_TRUE(Import(Foo, Lang_CXX));
4687
4688 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4689 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4690}
4691
4692TEST_P(ImportFunctionTemplateSpecializations,
4693 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4694
4695 Decl *FromTU = getTuDecl(
4696 R"(
4697 template<class T>
4698 int f() { return 0; }
4699 template int f<int>();
4700 )",
4701 Lang_CXX, "input0.cc");
4702
4703 // Check that the function template instantiation is NOT the child of the TU.
4704 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4705 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4706 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4707
4708 ASSERT_TRUE(
4709 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4710
4711 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4712 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4713}
4714
4715TEST_P(ImportFunctionTemplateSpecializations,
4716 TUshouldContainFunctionTemplateSpecialization) {
4717
4718 Decl *FromTU = getTuDecl(
4719 R"(
4720 template<class T>
4721 int f() { return 0; }
4722 template <> int f<int>() { return 4; }
4723 )",
4724 Lang_CXX, "input0.cc");
4725
4726 // Check that the function template specialization is the child of the TU.
4727 auto Specialization =
4728 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4729 auto Pattern = translationUnitDecl(has(Specialization));
4730 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4731
4732 ASSERT_TRUE(
4733 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4734
4735 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4736 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4737}
4738
4739TEST_P(ImportFunctionTemplateSpecializations,
4740 FunctionTemplateSpecializationRedeclChain) {
4741
4742 Decl *FromTU = getTuDecl(
4743 R"(
4744 template<class T>
4745 int f() { return 0; }
4746 template <> int f<int>() { return 4; }
4747 )",
4748 Lang_CXX, "input0.cc");
4749
4750 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4751 hasParent(translationUnitDecl()));
4752 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4753 {
4754 auto *TU = FromTU;
4755 auto *SpecD = FromSpecD;
4756 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4757 TU, functionTemplateDecl());
4758 auto *FirstSpecD = *(TemplateD->spec_begin());
4759 ASSERT_EQ(SpecD, FirstSpecD);
4760 ASSERT_TRUE(SpecD->getPreviousDecl());
4761 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4762 ->doesThisDeclarationHaveABody());
4763 }
4764
4765 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4766
4767 {
4768 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4769 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4770 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4771 TU, functionTemplateDecl());
4772 auto *FirstSpecD = *(TemplateD->spec_begin());
4773 EXPECT_EQ(SpecD, FirstSpecD);
4774 ASSERT_TRUE(SpecD->getPreviousDecl());
4775 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4776 ->doesThisDeclarationHaveABody());
4777 }
4778}
4779
4780TEST_P(ImportFunctionTemplateSpecializations,
4781 MatchNumberOfFunctionTemplateSpecializations) {
4782
4783 Decl *FromTU = getTuDecl(
4784 R"(
4785 template <typename T> constexpr int f() { return 0; }
4786 template <> constexpr int f<int>() { return 4; }
4787 void foo() {
4788 static_assert(f<char>() == 0, "");
4789 static_assert(f<int>() == 4, "");
4790 }
4791 )",
4792 Lang_CXX11, "input0.cc");
4793 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4794 FromTU, functionDecl(hasName("foo")));
4795
4796 Import(FromD, Lang_CXX11);
4797 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4798 EXPECT_EQ(
4799 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4800 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4801}
4802
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004803TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004804 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4805 {
4806 Decl *FromTU = getTuDecl(
4807 R"(
4808 template <typename T>
4809 struct B;
4810 )",
4811 Lang_CXX, "input0.cc");
4812 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4813 FromTU, classTemplateDecl(hasName("B")));
4814
4815 Import(FromD, Lang_CXX);
4816 }
4817
4818 {
4819 Decl *FromTU = getTuDecl(
4820 R"(
4821 template <typename T>
4822 struct B {
4823 void f();
4824 B* b;
4825 };
4826 )",
4827 Lang_CXX, "input1.cc");
4828 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4829 FromTU, functionDecl(hasName("f")));
4830 Import(FromD, Lang_CXX);
4831 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4832 FromTU, classTemplateDecl(hasName("B")));
4833 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4834 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4835
4836 // We expect no (ODR) warning during the import.
4837 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4838 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4839 }
4840}
4841
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004842TEST_P(ASTImporterOptionSpecificTestBase,
4843 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004844 // We already have an incomplete underlying type in the "To" context.
4845 auto Code =
4846 R"(
4847 template <typename T>
4848 struct S {
4849 void foo();
4850 };
4851 using U = S<int>;
4852 )";
4853 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4854 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4855 typedefNameDecl(hasName("U")));
4856 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4857
4858 // The "From" context has the same typedef, but the underlying type is
4859 // complete this time.
4860 Decl *FromTU = getTuDecl(std::string(Code) +
4861 R"(
4862 void foo(U* u) {
4863 u->foo();
4864 }
4865 )", Lang_CXX11);
4866 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4867 typedefNameDecl(hasName("U")));
4868 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4869
4870 // The imported type should be complete.
4871 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4872 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4873}
4874
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004875struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004876
4877TEST_P(ASTImporterLookupTableTest, OneDecl) {
4878 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4879 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4880 ASTImporterLookupTable LT(*ToTU);
4881 auto Res = LT.lookup(ToTU, D->getDeclName());
4882 ASSERT_EQ(Res.size(), 1u);
4883 EXPECT_EQ(*Res.begin(), D);
4884}
4885
4886static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4887 for (Decl *D : DC->decls()) {
4888 if (auto *ND = dyn_cast<NamedDecl>(D))
4889 if (ND->getDeclName() == Name)
4890 return ND;
4891 }
4892 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004893}
Gabor Marton54058b52018-12-17 13:53:12 +00004894
4895TEST_P(ASTImporterLookupTableTest,
4896 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4897 auto *Code = R"(
4898 template <class T>
4899 struct X {
4900 friend void foo(){}
4901 };
4902 )";
4903 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4904 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4905 ToTU, classTemplateDecl(hasName("X")));
4906 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4907 ToTU, functionDecl(hasName("foo")));
4908 DeclContext *FooDC = Foo->getDeclContext();
4909 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4910 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4911 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4912 DeclarationName FooName = Foo->getDeclName();
4913
4914 // Cannot find in the LookupTable of its DC (TUDecl)
4915 SmallVector<NamedDecl *, 2> FoundDecls;
4916 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4917 EXPECT_EQ(FoundDecls.size(), 0u);
4918
4919 // Cannot find in the LookupTable of its LexicalDC (X)
4920 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4921 EXPECT_EQ(FoundDecls.size(), 0u);
4922
4923 // Can't find in the list of Decls of the DC.
4924 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4925
4926 // Can't find in the list of Decls of the LexicalDC
4927 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4928
4929 // ASTImporter specific lookup finds it.
4930 ASTImporterLookupTable LT(*ToTU);
4931 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4932 ASSERT_EQ(Res.size(), 1u);
4933 EXPECT_EQ(*Res.begin(), Foo);
4934}
4935
4936TEST_P(ASTImporterLookupTableTest,
4937 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4938 TranslationUnitDecl *ToTU =
4939 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4940 auto *Foo =
4941 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4942 auto *A =
4943 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4944 DeclContext *FooDC = Foo->getDeclContext();
4945 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4946 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4947 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4948 DeclarationName FooName = Foo->getDeclName();
4949
4950 // Cannot find in the LookupTable of its DC (TUDecl).
4951 SmallVector<NamedDecl *, 2> FoundDecls;
4952 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4953 EXPECT_EQ(FoundDecls.size(), 0u);
4954
4955 // Cannot find in the LookupTable of its LexicalDC (A).
4956 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4957 EXPECT_EQ(FoundDecls.size(), 0u);
4958
4959 // Can't find in the list of Decls of the DC.
4960 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4961
4962 // Can find in the list of Decls of the LexicalDC.
4963 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4964
4965 // ASTImporter specific lookup finds it.
4966 ASTImporterLookupTable LT(*ToTU);
4967 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4968 ASSERT_EQ(Res.size(), 1u);
4969 EXPECT_EQ(*Res.begin(), Foo);
4970}
4971
4972TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4973 TranslationUnitDecl *ToTU =
4974 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4975 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4976 .match(ToTU, varDecl(hasName("V")))
4977 ->getDeclName();
4978 auto *A =
4979 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4980 auto *B =
4981 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4982
4983 ASTImporterLookupTable LT(*ToTU);
4984
4985 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4986 ASSERT_EQ(Res.size(), 1u);
4987 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4988 ToTU, fieldDecl(hasName("V"),
4989 hasParent(recordDecl(hasName("A"))))));
4990 Res = LT.lookup(cast<DeclContext>(B), VName);
4991 ASSERT_EQ(Res.size(), 1u);
4992 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4993 ToTU, fieldDecl(hasName("V"),
4994 hasParent(recordDecl(hasName("B"))))));
4995 Res = LT.lookup(ToTU, VName);
4996 ASSERT_EQ(Res.size(), 1u);
4997 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4998 ToTU, varDecl(hasName("V"),
4999 hasParent(translationUnitDecl()))));
5000}
5001
5002TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5003 TranslationUnitDecl *ToTU = getToTuDecl(
5004 R"(
5005 void foo();
5006 void foo(int);
5007 void foo(int, int);
5008 )",
5009 Lang_CXX);
5010
5011 ASTImporterLookupTable LT(*ToTU);
5012 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5013 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5014 DeclarationName Name = F0->getDeclName();
5015 auto Res = LT.lookup(ToTU, Name);
5016 EXPECT_EQ(Res.size(), 3u);
5017 EXPECT_EQ(Res.count(F0), 1u);
5018 EXPECT_EQ(Res.count(F2), 1u);
5019}
5020
Gabor Martona9cab312019-02-08 09:19:34 +00005021TEST_P(ASTImporterLookupTableTest,
5022 DifferentOperatorsShouldHaveDifferentResultSet) {
5023 TranslationUnitDecl *ToTU = getToTuDecl(
5024 R"(
5025 struct X{};
5026 void operator+(X, X);
5027 void operator-(X, X);
5028 )",
5029 Lang_CXX);
5030
5031 ASTImporterLookupTable LT(*ToTU);
5032 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5033 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5034 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5035 ToTU, functionDecl(hasOverloadedOperatorName("-")));
5036 DeclarationName NamePlus = FPlus->getDeclName();
5037 auto ResPlus = LT.lookup(ToTU, NamePlus);
5038 EXPECT_EQ(ResPlus.size(), 1u);
5039 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5040 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5041 DeclarationName NameMinus = FMinus->getDeclName();
5042 auto ResMinus = LT.lookup(ToTU, NameMinus);
5043 EXPECT_EQ(ResMinus.size(), 1u);
5044 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5045 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5046 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5047}
5048
5049TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5050 TranslationUnitDecl *ToTU = getToTuDecl(
5051 R"(
5052 struct X {};
5053 void operator+(X, X);
5054 )",
5055 Lang_CXX);
5056 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5057 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5058
5059 Decl *FromTU = getTuDecl(
5060 R"(
5061 struct X {};
5062 void operator+(X, X);
5063 )",
5064 Lang_CXX);
5065 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5066 FromTU, functionDecl(hasOverloadedOperatorName("+")));
5067
5068 // FromPlus have a different TU, thus its DeclarationName is different too.
5069 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5070
5071 ASTImporterLookupTable LT(*ToTU);
5072 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
5073 ASSERT_EQ(Res.size(), 1u);
5074 EXPECT_EQ(*Res.begin(), ToPlus);
5075
5076 // FromPlus have a different TU, thus its DeclarationName is different too.
5077 Res = LT.lookup(ToTU, FromPlus->getDeclName());
5078 ASSERT_EQ(Res.size(), 0u);
5079}
5080
Gabor Marton54058b52018-12-17 13:53:12 +00005081static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
5082 QualType Ty = FD->getFriendType()->getType();
5083 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
5084 return cast<RecordType>(NamedTy)->getDecl();
5085}
5086
5087TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
5088 TranslationUnitDecl *ToTU = getToTuDecl(
5089 R"(
5090 class Y { friend class F; };
5091 )",
5092 Lang_CXX);
5093
5094 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5095 // So we must dig up the underlying CXXRecordDecl.
5096 ASTImporterLookupTable LT(*ToTU);
5097 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5098 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5099 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5100 ToTU, cxxRecordDecl(hasName("Y")));
5101
5102 DeclarationName Name = RD->getDeclName();
5103 auto Res = LT.lookup(ToTU, Name);
5104 EXPECT_EQ(Res.size(), 1u);
5105 EXPECT_EQ(*Res.begin(), RD);
5106
5107 Res = LT.lookup(Y, Name);
5108 EXPECT_EQ(Res.size(), 0u);
5109}
5110
5111TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5112 TranslationUnitDecl *ToTU = getToTuDecl(
5113 R"(
5114 class Y { template <class T> friend class F; };
5115 )",
5116 Lang_CXX);
5117
5118 ASTImporterLookupTable LT(*ToTU);
5119 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5120 ToTU, classTemplateDecl(hasName("F")));
5121 DeclarationName Name = F->getDeclName();
5122 auto Res = LT.lookup(ToTU, Name);
5123 EXPECT_EQ(Res.size(), 2u);
5124 EXPECT_EQ(Res.count(F), 1u);
5125 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5126}
5127
5128TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5129 TranslationUnitDecl *ToTU = getToTuDecl(
5130 R"(
5131 template <typename T>
5132 class F;
5133
5134 template <typename T>
5135 class Y {
5136 friend class F<T>;
5137 };
5138 )",
5139 Lang_CXX);
5140
5141 ASTImporterLookupTable LT(*ToTU);
5142 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5143 ToTU, classTemplateDecl(hasName("F")));
5144 DeclarationName Name = F->getDeclName();
5145 auto Res = LT.lookup(ToTU, Name);
5146 EXPECT_EQ(Res.size(), 2u);
5147 EXPECT_EQ(Res.count(F), 1u);
5148 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5149}
5150
5151TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
5152 TranslationUnitDecl *ToTU = getToTuDecl(
5153 R"(
5154 template <typename T>
5155 class F;
5156
5157 class Y {
5158 friend class F<int>;
5159 };
5160 )",
5161 Lang_CXX);
5162
5163 ASTImporterLookupTable LT(*ToTU);
5164 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5165 ToTU, classTemplateDecl(hasName("F")));
5166 DeclarationName Name = F->getDeclName();
5167 auto Res = LT.lookup(ToTU, Name);
5168 ASSERT_EQ(Res.size(), 3u);
5169 EXPECT_EQ(Res.count(F), 1u);
5170 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5171 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
5172}
5173
5174TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
5175 TranslationUnitDecl *ToTU = getToTuDecl(
5176 R"(
5177 class Y { friend void F(); };
5178 )",
5179 Lang_CXX);
5180
5181 ASTImporterLookupTable LT(*ToTU);
5182 auto *F =
5183 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
5184 DeclarationName Name = F->getDeclName();
5185 auto Res = LT.lookup(ToTU, Name);
5186 EXPECT_EQ(Res.size(), 1u);
5187 EXPECT_EQ(*Res.begin(), F);
5188}
5189
5190TEST_P(ASTImporterLookupTableTest,
5191 LookupFindsDeclsInClassTemplateSpecialization) {
5192 TranslationUnitDecl *ToTU = getToTuDecl(
5193 R"(
5194 template <typename T>
5195 struct X {
5196 int F;
5197 };
5198 void foo() {
5199 X<char> xc;
5200 }
5201 )",
5202 Lang_CXX);
5203
5204 ASTImporterLookupTable LT(*ToTU);
5205
5206 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
5207 ToTU, classTemplateDecl(hasName("X")));
5208 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
5209 ToTU,
5210 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
5211
5212 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5213 ToTU, classTemplateSpecializationDecl(hasName("X")));
5214 FieldDecl *FieldInSpec = *Spec->field_begin();
5215 ASSERT_TRUE(FieldInSpec);
5216
5217 DeclarationName Name = FieldInSpec->getDeclName();
5218 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
5219
5220 SmallVector<NamedDecl *, 2> FoundDecls;
5221 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
5222 EXPECT_EQ(FoundDecls.size(), 1u);
5223 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
5224
5225 auto Res = LT.lookup(TemplateDC, Name);
5226 ASSERT_EQ(Res.size(), 1u);
5227 EXPECT_EQ(*Res.begin(), FieldInTemplate);
5228
5229 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
5230 FoundDecls);
5231 EXPECT_EQ(FoundDecls.size(), 1u);
5232 EXPECT_EQ(FoundDecls[0], FieldInSpec);
5233
5234 Res = LT.lookup(cast<DeclContext>(Spec), Name);
5235 ASSERT_EQ(Res.size(), 1u);
5236 EXPECT_EQ(*Res.begin(), FieldInSpec);
5237}
5238
5239TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
5240 TranslationUnitDecl *ToTU = getToTuDecl(
5241 R"(
5242 class Y { template <class T> friend void F(); };
5243 )",
5244 Lang_CXX);
5245
5246 ASTImporterLookupTable LT(*ToTU);
5247 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
5248 ToTU, functionTemplateDecl(hasName("F")));
5249 DeclarationName Name = F->getDeclName();
5250 auto Res = LT.lookup(ToTU, Name);
5251 EXPECT_EQ(Res.size(), 2u);
5252 EXPECT_EQ(Res.count(F), 1u);
5253 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5254}
5255
5256TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
5257 TranslationUnitDecl *ToTU = getToTuDecl(
5258 R"(
5259 struct X;
5260 struct A {
5261 friend struct X;
5262 };
5263 struct B {
5264 friend struct X;
5265 };
5266 )",
5267 Lang_CXX);
5268
5269 ASTImporterLookupTable LT(*ToTU);
5270 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
5271 ToTU, cxxRecordDecl(hasName("X")));
5272 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5273 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5274 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
5275 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
5276 ASSERT_EQ(RD0, RD1);
5277 ASSERT_EQ(RD1, X);
5278
5279 DeclarationName Name = X->getDeclName();
5280 auto Res = LT.lookup(ToTU, Name);
5281 EXPECT_EQ(Res.size(), 1u);
5282 EXPECT_EQ(*Res.begin(), X);
5283}
5284
5285TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
5286 TranslationUnitDecl *ToTU = getToTuDecl(
5287 R"(
5288 enum E {
5289 A,
5290 B
5291 };
5292 )",
5293 Lang_C);
5294
5295 ASTImporterLookupTable LT(*ToTU);
5296 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
5297 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
5298 ToTU, enumConstantDecl(hasName("A")));
5299
5300 DeclarationName Name = A->getDeclName();
5301 // Redecl context is the TU.
5302 ASSERT_EQ(E->getRedeclContext(), ToTU);
5303
5304 SmallVector<NamedDecl *, 2> FoundDecls;
5305 // Normal lookup finds in the DC.
5306 E->localUncachedLookup(Name, FoundDecls);
5307 EXPECT_EQ(FoundDecls.size(), 1u);
5308
5309 // Normal lookup finds in the Redecl context.
5310 ToTU->localUncachedLookup(Name, FoundDecls);
5311 EXPECT_EQ(FoundDecls.size(), 1u);
5312
5313 // Import specific lookup finds in the DC.
5314 auto Res = LT.lookup(E, Name);
5315 ASSERT_EQ(Res.size(), 1u);
5316 EXPECT_EQ(*Res.begin(), A);
5317
5318 // Import specific lookup finds in the Redecl context.
5319 Res = LT.lookup(ToTU, Name);
5320 ASSERT_EQ(Res.size(), 1u);
5321 EXPECT_EQ(*Res.begin(), A);
5322}
5323
5324TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
5325 TranslationUnitDecl *ToTU = getToTuDecl(
5326 R"(
5327 namespace N {
5328 int A;
5329 }
5330 namespace N {
5331 }
5332 )",
5333 Lang_CXX);
5334 auto *N1 =
5335 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
5336 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
5337 DeclarationName Name = A->getDeclName();
5338
5339 ASTImporterLookupTable LT(*ToTU);
5340 auto Res = LT.lookup(N1, Name);
5341 ASSERT_EQ(Res.size(), 1u);
5342 EXPECT_EQ(*Res.begin(), A);
5343}
5344
Gabor Marton19f4f392018-06-25 13:04:37 +00005345INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5346 ::testing::Values(ArgVector()), );
5347
Gabor Marton5254e642018-06-27 13:32:50 +00005348INSTANTIATE_TEST_CASE_P(
5349 ParameterizedTests, CanonicalRedeclChain,
5350 ::testing::Values(ArgVector()),);
5351
Gabor Marton0e04ebd2019-02-11 10:27:58 +00005352// FIXME This test is disabled currently, upcoming patches will make it
5353// possible to enable.
5354TEST_P(ASTImporterOptionSpecificTestBase,
5355 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
5356 Decl *FromTU = getTuDecl(
5357 R"(
5358 namespace NS {
5359 struct X;
5360 struct Y {
5361 static const int I = 3;
5362 };
5363 }
5364 namespace NS {
5365 struct X { // <--- To be imported
5366 void method(int i = Y::I) {}
5367 int f;
5368 };
5369 }
5370 )",
5371 Lang_CXX);
5372 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5373 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5374 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
5375 FromTU,
5376 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
5377 ASSERT_NE(FromFwd, FromDef);
5378 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
5379 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
5380 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
5381
5382 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
5383 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
5384 EXPECT_NE(ToFwd, ToDef);
5385 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
5386 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
5387 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
5388 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5389 // We expect no (ODR) warning during the import.
5390 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5391}
5392
Gabor Martone331e632019-02-18 13:09:27 +00005393struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
5394
5395TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
5396 Decl *ToTU = getToTuDecl(
5397 R"(
5398 class X {
5399 template <typename T> friend void foo();
5400 };
5401 )",
5402 Lang_CXX);
5403 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
5404 ToTU, functionTemplateDecl(hasName("foo")));
5405
5406 Decl *FromTU = getTuDecl(
5407 R"(
5408 template <typename T> void foo();
5409 )",
5410 Lang_CXX);
5411 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
5412 FromTU, functionTemplateDecl(hasName("foo")));
5413 auto *Imported = Import(FromFoo, Lang_CXX);
5414
5415 // FIXME Currently chains of FunctionTemplateDecls are not implemented.
5416 //EXPECT_EQ(Imported->getPreviousDecl(), Friend);
5417 EXPECT_EQ(Imported, Friend);
5418}
5419
Gabor Marton54058b52018-12-17 13:53:12 +00005420INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5421 DefaultTestValuesForRunOptions, );
5422
Gabor Marton19f4f392018-06-25 13:04:37 +00005423INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5424 DefaultTestValuesForRunOptions, );
5425
5426INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5427 DefaultTestValuesForRunOptions, );
5428
5429INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5430 DefaultTestValuesForRunOptions, );
5431
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005432INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005433 DefaultTestValuesForRunOptions, );
5434
5435INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5436 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005437
Gabor Martone331e632019-02-18 13:09:27 +00005438INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5439 DefaultTestValuesForRunOptions, );
5440
Gabor Marton54058b52018-12-17 13:53:12 +00005441INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005442 DefaultTestValuesForRunOptions, );
5443
Gabor Marton54058b52018-12-17 13:53:12 +00005444INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005445 DefaultTestValuesForRunOptions, );
5446
Gabor Marton7df342a2018-12-17 12:42:12 +00005447INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5448 DefaultTestValuesForRunOptions, );
5449
Gabor Marton5254e642018-06-27 13:32:50 +00005450INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5451 ImportFunctionTemplateSpecializations,
5452 DefaultTestValuesForRunOptions, );
5453
Gabor Martonac3a5d62018-09-17 12:04:52 +00005454INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5455 DefaultTestValuesForRunOptions, );
5456
5457INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5458 DefaultTestValuesForRunOptions, );
5459
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005460} // end namespace ast_matchers
5461} // end namespace clang