71
71
72
72
namespace clang {
73
73
74
+ template <class T >
75
+ SmallVector<Decl*, 2 >
76
+ getCanonicalForwardRedeclChain (Redeclarable<T>* D) {
77
+ SmallVector<Decl*, 2 > Redecls;
78
+ for (auto *R : D->getFirstDecl ()->redecls ()) {
79
+ if (R != D->getFirstDecl ())
80
+ Redecls.push_back (R);
81
+ }
82
+ Redecls.push_back (D->getFirstDecl ());
83
+ std::reverse (Redecls.begin (), Redecls.end ());
84
+ return Redecls;
85
+ }
86
+
87
+ SmallVector<Decl*, 2 > getCanonicalForwardRedeclChain (Decl* D) {
88
+ // Currently only FunctionDecl is supported
89
+ auto FD = cast<FunctionDecl>(D);
90
+ return getCanonicalForwardRedeclChain<FunctionDecl>(FD);
91
+ }
92
+
74
93
class ASTNodeImporter : public TypeVisitor <ASTNodeImporter, QualType>,
75
94
public DeclVisitor<ASTNodeImporter, Decl *>,
76
95
public StmtVisitor<ASTNodeImporter, Stmt *> {
@@ -195,6 +214,12 @@ namespace clang {
195
214
const InContainerTy &Container,
196
215
TemplateArgumentListInfo &Result);
197
216
217
+ using TemplateArgsTy = SmallVector<TemplateArgument, 8 >;
218
+ using OptionalTemplateArgsTy = Optional<TemplateArgsTy>;
219
+ std::tuple<FunctionTemplateDecl *, OptionalTemplateArgsTy>
220
+ ImportFunctionTemplateWithTemplateArgsFromSpecialization (
221
+ FunctionDecl *FromFD);
222
+
198
223
bool ImportTemplateInformation (FunctionDecl *FromFD, FunctionDecl *ToFD);
199
224
200
225
bool IsStructuralMatch (RecordDecl *FromRecord, RecordDecl *ToRecord,
@@ -408,6 +433,8 @@ namespace clang {
408
433
409
434
// Importing overrides.
410
435
void ImportOverrides (CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod);
436
+
437
+ FunctionDecl *FindFunctionTemplateSpecialization (FunctionDecl *FromFD);
411
438
};
412
439
413
440
template <typename InContainerTy>
@@ -437,6 +464,25 @@ bool ASTNodeImporter::ImportTemplateArgumentListInfo<
437
464
From.arguments (), Result);
438
465
}
439
466
467
+ std::tuple<FunctionTemplateDecl *, ASTNodeImporter::OptionalTemplateArgsTy>
468
+ ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization (
469
+ FunctionDecl *FromFD) {
470
+ assert (FromFD->getTemplatedKind () ==
471
+ FunctionDecl::TK_FunctionTemplateSpecialization);
472
+ auto *FTSInfo = FromFD->getTemplateSpecializationInfo ();
473
+ auto *Template = cast_or_null<FunctionTemplateDecl>(
474
+ Importer.Import (FTSInfo->getTemplate ()));
475
+
476
+ // Import template arguments.
477
+ auto TemplArgs = FTSInfo->TemplateArguments ->asArray ();
478
+ TemplateArgsTy ToTemplArgs;
479
+ if (ImportTemplateArguments (TemplArgs.data (), TemplArgs.size (),
480
+ ToTemplArgs)) // Error during import.
481
+ return std::make_tuple (Template, OptionalTemplateArgsTy ());
482
+
483
+ return std::make_tuple (Template, ToTemplArgs);
484
+ }
485
+
440
486
} // namespace clang
441
487
442
488
// ----------------------------------------------------------------------------
@@ -2252,23 +2298,17 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD,
2252
2298
}
2253
2299
2254
2300
case FunctionDecl::TK_FunctionTemplateSpecialization: {
2255
- auto *FTSInfo = FromFD->getTemplateSpecializationInfo ();
2256
- auto *Template = cast_or_null<FunctionTemplateDecl>(
2257
- Importer.Import (FTSInfo->getTemplate ()));
2258
- if (!Template)
2259
- return true ;
2260
- TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind ();
2261
-
2262
- // Import template arguments.
2263
- auto TemplArgs = FTSInfo->TemplateArguments ->asArray ();
2264
- SmallVector<TemplateArgument, 8 > ToTemplArgs;
2265
- if (ImportTemplateArguments (TemplArgs.data (), TemplArgs.size (),
2266
- ToTemplArgs))
2301
+ FunctionTemplateDecl* Template;
2302
+ OptionalTemplateArgsTy ToTemplArgs;
2303
+ std::tie (Template, ToTemplArgs) =
2304
+ ImportFunctionTemplateWithTemplateArgsFromSpecialization (FromFD);
2305
+ if (!Template || !ToTemplArgs)
2267
2306
return true ;
2268
2307
2269
2308
TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy (
2270
- Importer.getToContext (), ToTemplArgs);
2309
+ Importer.getToContext (), * ToTemplArgs);
2271
2310
2311
+ auto *FTSInfo = FromFD->getTemplateSpecializationInfo ();
2272
2312
TemplateArgumentListInfo ToTAInfo;
2273
2313
const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten ;
2274
2314
if (FromTAArgsAsWritten)
@@ -2277,6 +2317,7 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD,
2277
2317
2278
2318
SourceLocation POI = Importer.Import (FTSInfo->getPointOfInstantiation ());
2279
2319
2320
+ TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind ();
2280
2321
ToFD->setFunctionTemplateSpecialization (
2281
2322
Template, ToTAList, /* InsertPos= */ nullptr ,
2282
2323
TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr , POI);
@@ -2312,7 +2353,31 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD,
2312
2353
llvm_unreachable (" All cases should be covered!" );
2313
2354
}
2314
2355
2356
+ FunctionDecl *
2357
+ ASTNodeImporter::FindFunctionTemplateSpecialization (FunctionDecl *FromFD) {
2358
+ FunctionTemplateDecl* Template;
2359
+ OptionalTemplateArgsTy ToTemplArgs;
2360
+ std::tie (Template, ToTemplArgs) =
2361
+ ImportFunctionTemplateWithTemplateArgsFromSpecialization (FromFD);
2362
+ if (!Template || !ToTemplArgs)
2363
+ return nullptr ;
2364
+
2365
+ void *InsertPos = nullptr ;
2366
+ auto *FoundSpec = Template->findSpecialization (*ToTemplArgs, InsertPos);
2367
+ return FoundSpec;
2368
+ }
2369
+
2315
2370
Decl *ASTNodeImporter::VisitFunctionDecl (FunctionDecl *D) {
2371
+
2372
+ SmallVector<Decl*, 2 > Redecls = getCanonicalForwardRedeclChain (D);
2373
+ auto RedeclIt = Redecls.begin ();
2374
+ // Import the first part of the decl chain. I.e. import all previous
2375
+ // declarations starting from the canonical decl.
2376
+ for (; RedeclIt != Redecls.end () && *RedeclIt != D; ++RedeclIt)
2377
+ if (!Importer.Import (*RedeclIt))
2378
+ return nullptr ;
2379
+ assert (*RedeclIt == D);
2380
+
2316
2381
// Import the major distinguishing characteristics of this function.
2317
2382
DeclContext *DC, *LexicalDC;
2318
2383
DeclarationName Name;
@@ -2323,13 +2388,27 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
2323
2388
if (ToD)
2324
2389
return ToD;
2325
2390
2326
- const FunctionDecl *FoundWithoutBody = nullptr ;
2327
-
2391
+ const FunctionDecl *FoundByLookup = nullptr ;
2392
+
2393
+ // If this is a function template specialization, then try to find the same
2394
+ // existing specialization in the "to" context. The localUncachedLookup
2395
+ // below will not find any specialization, but would find the primary
2396
+ // template; thus, we have to skip normal lookup in case of specializations.
2397
+ // FIXME handle member function templates (TK_MemberSpecialization) similarly?
2398
+ if (D->getTemplatedKind () ==
2399
+ FunctionDecl::TK_FunctionTemplateSpecialization) {
2400
+ if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization (D)) {
2401
+ if (D->doesThisDeclarationHaveABody () &&
2402
+ FoundFunction->hasBody ())
2403
+ return Importer.Imported (D, FoundFunction);
2404
+ FoundByLookup = FoundFunction;
2405
+ }
2406
+ }
2328
2407
// Try to find a function in our own ("to") context with the same name, same
2329
2408
// type, and in the same context as the function we're importing.
2330
- if (!LexicalDC->isFunctionOrMethod ()) {
2409
+ else if (!LexicalDC->isFunctionOrMethod ()) {
2331
2410
SmallVector<NamedDecl *, 4 > ConflictingDecls;
2332
- unsigned IDNS = Decl::IDNS_Ordinary;
2411
+ unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend ;
2333
2412
SmallVector<NamedDecl *, 2 > FoundDecls;
2334
2413
DC->getRedeclContext ()->localUncachedLookup (Name, FoundDecls);
2335
2414
for (auto *FoundDecl : FoundDecls) {
@@ -2341,15 +2420,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
2341
2420
D->hasExternalFormalLinkage ()) {
2342
2421
if (Importer.IsStructurallyEquivalent (D->getType (),
2343
2422
FoundFunction->getType ())) {
2344
- // FIXME: Actually try to merge the body and other attributes.
2345
- const FunctionDecl *FromBodyDecl = nullptr ;
2346
- D->hasBody (FromBodyDecl);
2347
- if (D == FromBodyDecl && !FoundFunction->hasBody ()) {
2348
- // This function is needed to merge completely.
2349
- FoundWithoutBody = FoundFunction;
2423
+ if (D->doesThisDeclarationHaveABody () &&
2424
+ FoundFunction->hasBody ())
2425
+ return Importer.Imported (D, FoundFunction);
2426
+ FoundByLookup = FoundFunction;
2350
2427
break ;
2351
- }
2352
- return Importer.Imported (D, FoundFunction);
2353
2428
}
2354
2429
2355
2430
// FIXME: Check for overloading more carefully, e.g., by boosting
@@ -2499,9 +2574,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
2499
2574
}
2500
2575
ToFunction->setParams (Parameters);
2501
2576
2502
- if (FoundWithoutBody ) {
2577
+ if (FoundByLookup ) {
2503
2578
auto *Recent = const_cast <FunctionDecl *>(
2504
- FoundWithoutBody ->getMostRecentDecl ());
2579
+ FoundByLookup ->getMostRecentDecl ());
2505
2580
ToFunction->setPreviousDecl (Recent);
2506
2581
}
2507
2582
@@ -2523,10 +2598,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
2523
2598
ToFunction->setType (T);
2524
2599
}
2525
2600
2526
- // Import the body, if any.
2527
- if (Stmt *FromBody = D->getBody ()) {
2528
- if (Stmt *ToBody = Importer.Import (FromBody)) {
2529
- ToFunction->setBody (ToBody);
2601
+ if (D->doesThisDeclarationHaveABody ()) {
2602
+ if (Stmt *FromBody = D->getBody ()) {
2603
+ if (Stmt *ToBody = Importer.Import (FromBody)) {
2604
+ ToFunction->setBody (ToBody);
2605
+ }
2530
2606
}
2531
2607
}
2532
2608
@@ -2536,14 +2612,29 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
2536
2612
if (ImportTemplateInformation (D, ToFunction))
2537
2613
return nullptr ;
2538
2614
2539
- // Add this function to the lexical context.
2540
- // NOTE: If the function is templated declaration, it should be not added into
2541
- // LexicalDC. But described template is imported during import of
2542
- // FunctionTemplateDecl (it happens later). So, we use source declaration
2543
- // to determine if we should add the result function.
2544
- if (! D->getDescribedFunctionTemplate ( ))
2615
+ bool IsFriend = D-> isInIdentifierNamespace (Decl::IDNS_OrdinaryFriend);
2616
+
2617
+ // TODO Can we generalize this approach to other AST nodes as well?
2618
+ if (D-> getDeclContext ()-> containsDecl (D))
2619
+ DC-> addDeclInternal (ToFunction);
2620
+ if (DC != LexicalDC && D->getLexicalDeclContext ()-> containsDecl (D ))
2545
2621
LexicalDC->addDeclInternal (ToFunction);
2546
2622
2623
+ // Friend declaration's lexical context is the befriending class, but the
2624
+ // semantic context is the enclosing scope of the befriending class.
2625
+ // We want the friend functions to be found in the semantic context by lookup.
2626
+ // FIXME should we handle this generically in VisitFriendDecl?
2627
+ // In Other cases when LexicalDC != DC we don't want it to be added,
2628
+ // e.g out-of-class definitions like void B::f() {} .
2629
+ if (LexicalDC != DC && IsFriend) {
2630
+ DC->makeDeclVisibleInContext (ToFunction);
2631
+ }
2632
+
2633
+ // Import the rest of the chain. I.e. import all subsequent declarations.
2634
+ for (++RedeclIt; RedeclIt != Redecls.end (); ++RedeclIt)
2635
+ if (!Importer.Import (*RedeclIt))
2636
+ return nullptr ;
2637
+
2547
2638
if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
2548
2639
ImportOverrides (cast<CXXMethodDecl>(ToFunction), FromCXXMethod);
2549
2640
0 commit comments