-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathDecl.cpp
4459 lines (3785 loc) · 158 KB
/
Decl.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//===--- Decl.cpp - Declaration AST Node Implementation -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Decl subclasses.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/Decl.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
using namespace clang;
Decl *clang::getPrimaryMergedDecl(Decl *D) {
return D->getASTContext().getPrimaryMergedDecl(D);
}
// Defined here so that it can be inlined into its direct callers.
bool Decl::isOutOfLine() const {
return !getLexicalDeclContext()->Equals(getDeclContext());
}
TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
: Decl(TranslationUnit, nullptr, SourceLocation()),
DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {}
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
// Visibility rules aren't rigorously externally specified, but here
// are the basic principles behind what we implement:
//
// 1. An explicit visibility attribute is generally a direct expression
// of the user's intent and should be honored. Only the innermost
// visibility attribute applies. If no visibility attribute applies,
// global visibility settings are considered.
//
// 2. There is one caveat to the above: on or in a template pattern,
// an explicit visibility attribute is just a default rule, and
// visibility can be decreased by the visibility of template
// arguments. But this, too, has an exception: an attribute on an
// explicit specialization or instantiation causes all the visibility
// restrictions of the template arguments to be ignored.
//
// 3. A variable that does not otherwise have explicit visibility can
// be restricted by the visibility of its type.
//
// 4. A visibility restriction is explicit if it comes from an
// attribute (or something like it), not a global visibility setting.
// When emitting a reference to an external symbol, visibility
// restrictions are ignored unless they are explicit.
//
// 5. When computing the visibility of a non-type, including a
// non-type member of a class, only non-type visibility restrictions
// are considered: the 'visibility' attribute, global value-visibility
// settings, and a few special cases like __private_extern.
//
// 6. When computing the visibility of a type, including a type member
// of a class, only type visibility restrictions are considered:
// the 'type_visibility' attribute and global type-visibility settings.
// However, a 'visibility' attribute counts as a 'type_visibility'
// attribute on any declaration that only has the former.
//
// The visibility of a "secondary" entity, like a template argument,
// is computed using the kind of that entity, not the kind of the
// primary entity for which we are computing visibility. For example,
// the visibility of a specialization of either of these templates:
// template <class T, bool (&compare)(T, X)> bool has_match(list<T>, X);
// template <class T, bool (&compare)(T, X)> class matcher;
// is restricted according to the type visibility of the argument 'T',
// the type visibility of 'bool(&)(T,X)', and the value visibility of
// the argument function 'compare'. That 'has_match' is a value
// and 'matcher' is a type only matters when looking for attributes
// and settings from the immediate context.
const unsigned IgnoreExplicitVisibilityBit = 2;
const unsigned IgnoreAllVisibilityBit = 4;
/// Kinds of LV computation. The linkage side of the computation is
/// always the same, but different things can change how visibility is
/// computed.
enum LVComputationKind {
/// Do an LV computation for, ultimately, a type.
/// Visibility may be restricted by type visibility settings and
/// the visibility of template arguments.
LVForType = NamedDecl::VisibilityForType,
/// Do an LV computation for, ultimately, a non-type declaration.
/// Visibility may be restricted by value visibility settings and
/// the visibility of template arguments.
LVForValue = NamedDecl::VisibilityForValue,
/// Do an LV computation for, ultimately, a type that already has
/// some sort of explicit visibility. Visibility may only be
/// restricted by the visibility of template arguments.
LVForExplicitType = (LVForType | IgnoreExplicitVisibilityBit),
/// Do an LV computation for, ultimately, a non-type declaration
/// that already has some sort of explicit visibility. Visibility
/// may only be restricted by the visibility of template arguments.
LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit),
/// Do an LV computation when we only care about the linkage.
LVForLinkageOnly =
LVForValue | IgnoreExplicitVisibilityBit | IgnoreAllVisibilityBit
};
/// Does this computation kind permit us to consider additional
/// visibility settings from attributes and the like?
static bool hasExplicitVisibilityAlready(LVComputationKind computation) {
return ((unsigned(computation) & IgnoreExplicitVisibilityBit) != 0);
}
/// Given an LVComputationKind, return one of the same type/value sort
/// that records that it already has explicit visibility.
static LVComputationKind
withExplicitVisibilityAlready(LVComputationKind oldKind) {
LVComputationKind newKind =
static_cast<LVComputationKind>(unsigned(oldKind) |
IgnoreExplicitVisibilityBit);
assert(oldKind != LVForType || newKind == LVForExplicitType);
assert(oldKind != LVForValue || newKind == LVForExplicitValue);
assert(oldKind != LVForExplicitType || newKind == LVForExplicitType);
assert(oldKind != LVForExplicitValue || newKind == LVForExplicitValue);
return newKind;
}
static Optional<Visibility> getExplicitVisibility(const NamedDecl *D,
LVComputationKind kind) {
assert(!hasExplicitVisibilityAlready(kind) &&
"asking for explicit visibility when we shouldn't be");
return D->getExplicitVisibility((NamedDecl::ExplicitVisibilityKind) kind);
}
/// Is the given declaration a "type" or a "value" for the purposes of
/// visibility computation?
static bool usesTypeVisibility(const NamedDecl *D) {
return isa<TypeDecl>(D) ||
isa<ClassTemplateDecl>(D) ||
isa<ObjCInterfaceDecl>(D);
}
/// Does the given declaration have member specialization information,
/// and if so, is it an explicit specialization?
template <class T> static typename
std::enable_if<!std::is_base_of<RedeclarableTemplateDecl, T>::value, bool>::type
isExplicitMemberSpecialization(const T *D) {
if (const MemberSpecializationInfo *member =
D->getMemberSpecializationInfo()) {
return member->isExplicitSpecialization();
}
return false;
}
/// For templates, this question is easier: a member template can't be
/// explicitly instantiated, so there's a single bit indicating whether
/// or not this is an explicit member specialization.
static bool isExplicitMemberSpecialization(const RedeclarableTemplateDecl *D) {
return D->isMemberSpecialization();
}
/// Given a visibility attribute, return the explicit visibility
/// associated with it.
template <class T>
static Visibility getVisibilityFromAttr(const T *attr) {
switch (attr->getVisibility()) {
case T::Default:
return DefaultVisibility;
case T::Hidden:
return HiddenVisibility;
case T::Protected:
return ProtectedVisibility;
}
llvm_unreachable("bad visibility kind");
}
/// Return the explicit visibility of the given declaration.
static Optional<Visibility> getVisibilityOf(const NamedDecl *D,
NamedDecl::ExplicitVisibilityKind kind) {
// If we're ultimately computing the visibility of a type, look for
// a 'type_visibility' attribute before looking for 'visibility'.
if (kind == NamedDecl::VisibilityForType) {
if (const auto *A = D->getAttr<TypeVisibilityAttr>()) {
return getVisibilityFromAttr(A);
}
}
// If this declaration has an explicit visibility attribute, use it.
if (const auto *A = D->getAttr<VisibilityAttr>()) {
return getVisibilityFromAttr(A);
}
// If we're on Mac OS X, an 'availability' for Mac OS X attribute
// implies visibility(default).
if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) {
for (const auto *A : D->specific_attrs<AvailabilityAttr>())
if (A->getPlatform()->getName().equals("macos"))
return DefaultVisibility;
}
return None;
}
static LinkageInfo
getLVForType(const Type &T, LVComputationKind computation) {
if (computation == LVForLinkageOnly)
return LinkageInfo(T.getLinkage(), DefaultVisibility, true);
return T.getLinkageAndVisibility();
}
/// \brief Get the most restrictive linkage for the types in the given
/// template parameter list. For visibility purposes, template
/// parameters are part of the signature of a template.
static LinkageInfo
getLVForTemplateParameterList(const TemplateParameterList *Params,
LVComputationKind computation) {
LinkageInfo LV;
for (const NamedDecl *P : *Params) {
// Template type parameters are the most common and never
// contribute to visibility, pack or not.
if (isa<TemplateTypeParmDecl>(P))
continue;
// Non-type template parameters can be restricted by the value type, e.g.
// template <enum X> class A { ... };
// We have to be careful here, though, because we can be dealing with
// dependent types.
if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
// Handle the non-pack case first.
if (!NTTP->isExpandedParameterPack()) {
if (!NTTP->getType()->isDependentType()) {
LV.merge(getLVForType(*NTTP->getType(), computation));
}
continue;
}
// Look at all the types in an expanded pack.
for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) {
QualType type = NTTP->getExpansionType(i);
if (!type->isDependentType())
LV.merge(type->getLinkageAndVisibility());
}
continue;
}
// Template template parameters can be restricted by their
// template parameters, recursively.
const auto *TTP = cast<TemplateTemplateParmDecl>(P);
// Handle the non-pack case first.
if (!TTP->isExpandedParameterPack()) {
LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters(),
computation));
continue;
}
// Look at all expansions in an expanded pack.
for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters();
i != n; ++i) {
LV.merge(getLVForTemplateParameterList(
TTP->getExpansionTemplateParameters(i), computation));
}
}
return LV;
}
/// getLVForDecl - Get the linkage and visibility for the given declaration.
static LinkageInfo getLVForDecl(const NamedDecl *D,
LVComputationKind computation);
static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
const Decl *Ret = nullptr;
const DeclContext *DC = D->getDeclContext();
while (DC->getDeclKind() != Decl::TranslationUnit) {
if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC))
Ret = cast<Decl>(DC);
DC = DC->getParent();
}
return Ret;
}
/// \brief Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
///
/// Note that we don't take an LVComputationKind because we always
/// want to honor the visibility of template arguments in the same way.
static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
LVComputationKind computation) {
LinkageInfo LV;
for (const TemplateArgument &Arg : Args) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Expression:
continue;
case TemplateArgument::Type:
LV.merge(getLVForType(*Arg.getAsType(), computation));
continue;
case TemplateArgument::Declaration:
if (const auto *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) {
assert(!usesTypeVisibility(ND));
LV.merge(getLVForDecl(ND, computation));
}
continue;
case TemplateArgument::NullPtr:
LV.merge(Arg.getNullPtrType()->getLinkageAndVisibility());
continue;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
if (TemplateDecl *Template =
Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
LV.merge(getLVForDecl(Template, computation));
continue;
case TemplateArgument::Pack:
LV.merge(getLVForTemplateArgumentList(Arg.getPackAsArray(), computation));
continue;
}
llvm_unreachable("bad template argument kind");
}
return LV;
}
static LinkageInfo
getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
LVComputationKind computation) {
return getLVForTemplateArgumentList(TArgs.asArray(), computation);
}
static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn,
const FunctionTemplateSpecializationInfo *specInfo) {
// Include visibility from the template parameters and arguments
// only if this is not an explicit instantiation or specialization
// with direct explicit visibility. (Implicit instantiations won't
// have a direct attribute.)
if (!specInfo->isExplicitInstantiationOrSpecialization())
return true;
return !fn->hasAttr<VisibilityAttr>();
}
/// Merge in template-related linkage and visibility for the given
/// function template specialization.
///
/// We don't need a computation kind here because we can assume
/// LVForValue.
///
/// \param[out] LV the computation to use for the parent
static void
mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
const FunctionTemplateSpecializationInfo *specInfo,
LVComputationKind computation) {
bool considerVisibility =
shouldConsiderTemplateVisibility(fn, specInfo);
// Merge information from the template parameters.
FunctionTemplateDecl *temp = specInfo->getTemplate();
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
// Merge information from the template arguments.
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
LV.mergeMaybeWithVisibility(argsLV, considerVisibility);
}
/// Does the given declaration have a direct visibility attribute
/// that would match the given rules?
static bool hasDirectVisibilityAttribute(const NamedDecl *D,
LVComputationKind computation) {
switch (computation) {
case LVForType:
case LVForExplicitType:
if (D->hasAttr<TypeVisibilityAttr>())
return true;
// fallthrough
case LVForValue:
case LVForExplicitValue:
if (D->hasAttr<VisibilityAttr>())
return true;
return false;
case LVForLinkageOnly:
return false;
}
llvm_unreachable("bad visibility computation kind");
}
/// Should we consider visibility associated with the template
/// arguments and parameters of the given class template specialization?
static bool shouldConsiderTemplateVisibility(
const ClassTemplateSpecializationDecl *spec,
LVComputationKind computation) {
// Include visibility from the template parameters and arguments
// only if this is not an explicit instantiation or specialization
// with direct explicit visibility (and note that implicit
// instantiations won't have a direct attribute).
//
// Furthermore, we want to ignore template parameters and arguments
// for an explicit specialization when computing the visibility of a
// member thereof with explicit visibility.
//
// This is a bit complex; let's unpack it.
//
// An explicit class specialization is an independent, top-level
// declaration. As such, if it or any of its members has an
// explicit visibility attribute, that must directly express the
// user's intent, and we should honor it. The same logic applies to
// an explicit instantiation of a member of such a thing.
// Fast path: if this is not an explicit instantiation or
// specialization, we always want to consider template-related
// visibility restrictions.
if (!spec->isExplicitInstantiationOrSpecialization())
return true;
// This is the 'member thereof' check.
if (spec->isExplicitSpecialization() &&
hasExplicitVisibilityAlready(computation))
return false;
return !hasDirectVisibilityAttribute(spec, computation);
}
/// Merge in template-related linkage and visibility for the given
/// class template specialization.
static void mergeTemplateLV(LinkageInfo &LV,
const ClassTemplateSpecializationDecl *spec,
LVComputationKind computation) {
bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
// Merge information from the template parameters, but ignore
// visibility if we're only considering template arguments.
ClassTemplateDecl *temp = spec->getSpecializedTemplate();
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV,
considerVisibility && !hasExplicitVisibilityAlready(computation));
// Merge information from the template arguments. We ignore
// template-argument visibility if we've got an explicit
// instantiation with a visibility attribute.
const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
if (considerVisibility)
LV.mergeVisibility(argsLV);
LV.mergeExternalVisibility(argsLV);
}
/// Should we consider visibility associated with the template
/// arguments and parameters of the given variable template
/// specialization? As usual, follow class template specialization
/// logic up to initialization.
static bool shouldConsiderTemplateVisibility(
const VarTemplateSpecializationDecl *spec,
LVComputationKind computation) {
// Include visibility from the template parameters and arguments
// only if this is not an explicit instantiation or specialization
// with direct explicit visibility (and note that implicit
// instantiations won't have a direct attribute).
if (!spec->isExplicitInstantiationOrSpecialization())
return true;
// An explicit variable specialization is an independent, top-level
// declaration. As such, if it has an explicit visibility attribute,
// that must directly express the user's intent, and we should honor
// it.
if (spec->isExplicitSpecialization() &&
hasExplicitVisibilityAlready(computation))
return false;
return !hasDirectVisibilityAttribute(spec, computation);
}
/// Merge in template-related linkage and visibility for the given
/// variable template specialization. As usual, follow class template
/// specialization logic up to initialization.
static void mergeTemplateLV(LinkageInfo &LV,
const VarTemplateSpecializationDecl *spec,
LVComputationKind computation) {
bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
// Merge information from the template parameters, but ignore
// visibility if we're only considering template arguments.
VarTemplateDecl *temp = spec->getSpecializedTemplate();
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV,
considerVisibility && !hasExplicitVisibilityAlready(computation));
// Merge information from the template arguments. We ignore
// template-argument visibility if we've got an explicit
// instantiation with a visibility attribute.
const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
if (considerVisibility)
LV.mergeVisibility(argsLV);
LV.mergeExternalVisibility(argsLV);
}
static bool useInlineVisibilityHidden(const NamedDecl *D) {
// FIXME: we should warn if -fvisibility-inlines-hidden is used with c.
const LangOptions &Opts = D->getASTContext().getLangOpts();
if (!Opts.CPlusPlus || !Opts.InlineVisibilityHidden)
return false;
const auto *FD = dyn_cast<FunctionDecl>(D);
if (!FD)
return false;
TemplateSpecializationKind TSK = TSK_Undeclared;
if (FunctionTemplateSpecializationInfo *spec
= FD->getTemplateSpecializationInfo()) {
TSK = spec->getTemplateSpecializationKind();
} else if (MemberSpecializationInfo *MSI =
FD->getMemberSpecializationInfo()) {
TSK = MSI->getTemplateSpecializationKind();
}
const FunctionDecl *Def = nullptr;
// InlineVisibilityHidden only applies to definitions, and
// isInlined() only gives meaningful answers on definitions
// anyway.
return TSK != TSK_ExplicitInstantiationDeclaration &&
TSK != TSK_ExplicitInstantiationDefinition &&
FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
}
template <typename T> static bool isFirstInExternCContext(T *D) {
const T *First = D->getFirstDecl();
return First->isInExternCContext();
}
static bool isSingleLineLanguageLinkage(const Decl &D) {
if (const auto *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext()))
if (!SD->hasBraces())
return true;
return false;
}
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
LVComputationKind computation) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
// C++ [basic.link]p3:
// A name having namespace scope (3.3.6) has internal linkage if it
// is the name of
// - an object, reference, function or function template that is
// explicitly declared static; or,
// (This bullet corresponds to C99 6.2.2p3.)
if (const auto *Var = dyn_cast<VarDecl>(D)) {
// Explicitly declared static.
if (Var->getStorageClass() == SC_Static)
return LinkageInfo::internal();
// - a non-inline, non-volatile object or reference that is explicitly
// declared const or constexpr and neither explicitly declared extern
// nor previously declared to have external linkage; or (there is no
// equivalent in C99)
if (Context.getLangOpts().CPlusPlus &&
Var->getType().isConstQualified() &&
!Var->getType().isVolatileQualified() &&
!Var->isInline()) {
const VarDecl *PrevVar = Var->getPreviousDecl();
if (PrevVar)
return getLVForDecl(PrevVar, computation);
if (Var->getStorageClass() != SC_Extern &&
Var->getStorageClass() != SC_PrivateExtern &&
!isSingleLineLanguageLinkage(*Var))
return LinkageInfo::internal();
}
for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar;
PrevVar = PrevVar->getPreviousDecl()) {
if (PrevVar->getStorageClass() == SC_PrivateExtern &&
Var->getStorageClass() == SC_None)
return PrevVar->getLinkageAndVisibility();
// Explicitly declared static.
if (PrevVar->getStorageClass() == SC_Static)
return LinkageInfo::internal();
}
} else if (const FunctionDecl *Function = D->getAsFunction()) {
// C++ [temp]p4:
// A non-member function template can have internal linkage; any
// other template name shall have external linkage.
// Explicitly declared static.
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
return LinkageInfo(InternalLinkage, DefaultVisibility, false);
} else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) {
// - a data member of an anonymous union.
const VarDecl *VD = IFD->getVarDecl();
assert(VD && "Expected a VarDecl in this IndirectFieldDecl!");
return getLVForNamespaceScopeDecl(VD, computation);
}
assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
if (D->isInAnonymousNamespace()) {
const auto *Var = dyn_cast<VarDecl>(D);
const auto *Func = dyn_cast<FunctionDecl>(D);
// FIXME: In C++11 onwards, anonymous namespaces should give decls
// within them internal linkage, not unique external linkage.
if ((!Var || !isFirstInExternCContext(Var)) &&
(!Func || !isFirstInExternCContext(Func)))
return LinkageInfo::uniqueExternal();
}
// Set up the defaults.
// C99 6.2.2p5:
// If the declaration of an identifier for an object has file
// scope and no storage-class specifier, its linkage is
// external.
LinkageInfo LV;
if (!hasExplicitVisibilityAlready(computation)) {
if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) {
LV.mergeVisibility(*Vis, true);
} else {
// If we're declared in a namespace with a visibility attribute,
// use that namespace's visibility, and it still counts as explicit.
for (const DeclContext *DC = D->getDeclContext();
!isa<TranslationUnitDecl>(DC);
DC = DC->getParent()) {
const auto *ND = dyn_cast<NamespaceDecl>(DC);
if (!ND) continue;
if (Optional<Visibility> Vis = getExplicitVisibility(ND, computation)) {
LV.mergeVisibility(*Vis, true);
break;
}
}
}
// Add in global settings if the above didn't give us direct visibility.
if (!LV.isVisibilityExplicit()) {
// Use global type/value visibility as appropriate.
Visibility globalVisibility;
if (computation == LVForValue) {
globalVisibility = Context.getLangOpts().getValueVisibilityMode();
} else {
assert(computation == LVForType);
globalVisibility = Context.getLangOpts().getTypeVisibilityMode();
}
LV.mergeVisibility(globalVisibility, /*explicit*/ false);
// If we're paying attention to global visibility, apply
// -finline-visibility-hidden if this is an inline method.
if (useInlineVisibilityHidden(D))
LV.mergeVisibility(HiddenVisibility, true);
}
}
// C++ [basic.link]p4:
// A name having namespace scope has external linkage if it is the
// name of
//
// - an object or reference, unless it has internal linkage; or
if (const auto *Var = dyn_cast<VarDecl>(D)) {
// GCC applies the following optimization to variables and static
// data members, but not to functions:
//
// Modify the variable's LV by the LV of its type unless this is
// C or extern "C". This follows from [basic.link]p9:
// A type without linkage shall not be used as the type of a
// variable or function with external linkage unless
// - the entity has C language linkage, or
// - the entity is declared within an unnamed namespace, or
// - the entity is not used or is defined in the same
// translation unit.
// and [basic.link]p10:
// ...the types specified by all declarations referring to a
// given variable or function shall be identical...
// C does not have an equivalent rule.
//
// Ignore this if we've got an explicit attribute; the user
// probably knows what they're doing.
//
// Note that we don't want to make the variable non-external
// because of this, but unique-external linkage suits us.
if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) {
LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
if (TypeLV.getLinkage() != ExternalLinkage)
return LinkageInfo::uniqueExternal();
if (!LV.isVisibilityExplicit())
LV.mergeVisibility(TypeLV);
}
if (Var->getStorageClass() == SC_PrivateExtern)
LV.mergeVisibility(HiddenVisibility, true);
// Note that Sema::MergeVarDecl already takes care of implementing
// C99 6.2.2p4 and propagating the visibility attribute, so we don't have
// to do it here.
// As per function and class template specializations (below),
// consider LV for the template and template arguments. We're at file
// scope, so we do not need to worry about nested specializations.
if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
mergeTemplateLV(LV, spec, computation);
}
// - a function, unless it has internal linkage; or
} else if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
// In theory, we can modify the function's LV by the LV of its
// type unless it has C linkage (see comment above about variables
// for justification). In practice, GCC doesn't do this, so it's
// just too painful to make work.
if (Function->getStorageClass() == SC_PrivateExtern)
LV.mergeVisibility(HiddenVisibility, true);
// Note that Sema::MergeCompatibleFunctionDecls already takes care of
// merging storage classes and visibility attributes, so we don't have to
// look at previous decls in here.
// In C++, then if the type of the function uses a type with
// unique-external linkage, it's not legally usable from outside
// this translation unit. However, we should use the C linkage
// rules instead for extern "C" declarations.
if (Context.getLangOpts().CPlusPlus &&
!Function->isInExternCContext()) {
// Only look at the type-as-written. If this function has an auto-deduced
// return type, we can't compute the linkage of that type because it could
// require looking at the linkage of this function, and we don't need this
// for correctness because the type is not part of the function's
// signature.
// FIXME: This is a hack. We should be able to solve this circularity and
// the one in getLVForClassMember for Functions some other way.
QualType TypeAsWritten = Function->getType();
if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
TypeAsWritten = TSI->getType();
if (TypeAsWritten->getLinkage() == UniqueExternalLinkage)
return LinkageInfo::uniqueExternal();
}
// Consider LV from the template and the template arguments.
// We're at file scope, so we do not need to worry about nested
// specializations.
if (FunctionTemplateSpecializationInfo *specInfo
= Function->getTemplateSpecializationInfo()) {
mergeTemplateLV(LV, Function, specInfo, computation);
}
// - a named class (Clause 9), or an unnamed class defined in a
// typedef declaration in which the class has the typedef name
// for linkage purposes (7.1.3); or
// - a named enumeration (7.2), or an unnamed enumeration
// defined in a typedef declaration in which the enumeration
// has the typedef name for linkage purposes (7.1.3); or
} else if (const auto *Tag = dyn_cast<TagDecl>(D)) {
// Unnamed tags have no linkage.
if (!Tag->hasNameForLinkage())
return LinkageInfo::none();
// If this is a class template specialization, consider the
// linkage of the template and template arguments. We're at file
// scope, so we do not need to worry about nested specializations.
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
mergeTemplateLV(LV, spec, computation);
}
// - an enumerator belonging to an enumeration with external linkage;
} else if (isa<EnumConstantDecl>(D)) {
LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()),
computation);
if (!isExternalFormalLinkage(EnumLV.getLinkage()))
return LinkageInfo::none();
LV.merge(EnumLV);
// - a template, unless it is a function template that has
// internal linkage (Clause 14);
} else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
bool considerVisibility = !hasExplicitVisibilityAlready(computation);
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
// - a namespace (7.3), unless it is declared within an unnamed
// namespace.
} else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) {
return LV;
// By extension, we assign external linkage to Objective-C
// interfaces.
} else if (isa<ObjCInterfaceDecl>(D)) {
// fallout
} else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
// A typedef declaration has linkage if it gives a type a name for
// linkage purposes.
if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
return LinkageInfo::none();
// Everything not covered here has no linkage.
} else {
return LinkageInfo::none();
}
// If we ended up with non-external linkage, visibility should
// always be default.
if (LV.getLinkage() != ExternalLinkage)
return LinkageInfo(LV.getLinkage(), DefaultVisibility, false);
return LV;
}
static LinkageInfo getLVForClassMember(const NamedDecl *D,
LVComputationKind computation) {
// Only certain class members have linkage. Note that fields don't
// really have linkage, but it's convenient to say they do for the
// purposes of calculating linkage of pointer-to-data-member
// template arguments.
//
// Templates also don't officially have linkage, but since we ignore
// the C++ standard and look at template arguments when determining
// linkage and visibility of a template specialization, we might hit
// a template template argument that way. If we do, we need to
// consider its linkage.
if (!(isa<CXXMethodDecl>(D) ||
isa<VarDecl>(D) ||
isa<FieldDecl>(D) ||
isa<IndirectFieldDecl>(D) ||
isa<TagDecl>(D) ||
isa<TemplateDecl>(D)))
return LinkageInfo::none();
LinkageInfo LV;
// If we have an explicit visibility attribute, merge that in.
if (!hasExplicitVisibilityAlready(computation)) {
if (Optional<Visibility> Vis = getExplicitVisibility(D, computation))
LV.mergeVisibility(*Vis, true);
// If we're paying attention to global visibility, apply
// -finline-visibility-hidden if this is an inline method.
//
// Note that we do this before merging information about
// the class visibility.
if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D))
LV.mergeVisibility(HiddenVisibility, true);
}
// If this class member has an explicit visibility attribute, the only
// thing that can change its visibility is the template arguments, so
// only look for them when processing the class.
LVComputationKind classComputation = computation;
if (LV.isVisibilityExplicit())
classComputation = withExplicitVisibilityAlready(computation);
LinkageInfo classLV =
getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation);
// If the class already has unique-external linkage, we can't improve.
if (classLV.getLinkage() == UniqueExternalLinkage)
return LinkageInfo::uniqueExternal();
if (!isExternallyVisible(classLV.getLinkage()))
return LinkageInfo::none();
// Otherwise, don't merge in classLV yet, because in certain cases
// we need to completely ignore the visibility from it.
// Specifically, if this decl exists and has an explicit attribute.
const NamedDecl *explicitSpecSuppressor = nullptr;
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
// If the type of the function uses a type with unique-external
// linkage, it's not legally usable from outside this translation unit.
// But only look at the type-as-written. If this function has an
// auto-deduced return type, we can't compute the linkage of that type
// because it could require looking at the linkage of this function, and we
// don't need this for correctness because the type is not part of the
// function's signature.
// FIXME: This is a hack. We should be able to solve this circularity and
// the one in getLVForNamespaceScopeDecl for Functions some other way.
{
QualType TypeAsWritten = MD->getType();
if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
TypeAsWritten = TSI->getType();
if (TypeAsWritten->getLinkage() == UniqueExternalLinkage)
return LinkageInfo::uniqueExternal();
}
// If this is a method template specialization, use the linkage for
// the template parameters and arguments.
if (FunctionTemplateSpecializationInfo *spec
= MD->getTemplateSpecializationInfo()) {
mergeTemplateLV(LV, MD, spec, computation);
if (spec->isExplicitSpecialization()) {
explicitSpecSuppressor = MD;
} else if (isExplicitMemberSpecialization(spec->getTemplate())) {
explicitSpecSuppressor = spec->getTemplate()->getTemplatedDecl();
}
} else if (isExplicitMemberSpecialization(MD)) {
explicitSpecSuppressor = MD;
}
} else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
mergeTemplateLV(LV, spec, computation);
if (spec->isExplicitSpecialization()) {
explicitSpecSuppressor = spec;
} else {
const ClassTemplateDecl *temp = spec->getSpecializedTemplate();
if (isExplicitMemberSpecialization(temp)) {
explicitSpecSuppressor = temp->getTemplatedDecl();
}
}
} else if (isExplicitMemberSpecialization(RD)) {
explicitSpecSuppressor = RD;
}
// Static data members.
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(VD))
mergeTemplateLV(LV, spec, computation);
// Modify the variable's linkage by its type, but ignore the
// type's visibility unless it's a definition.
LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
LV.mergeVisibility(typeLV);
LV.mergeExternalVisibility(typeLV);
if (isExplicitMemberSpecialization(VD)) {
explicitSpecSuppressor = VD;
}
// Template members.
} else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
bool considerVisibility =
(!LV.isVisibilityExplicit() &&
!classLV.isVisibilityExplicit() &&
!hasExplicitVisibilityAlready(computation));
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) {
if (isExplicitMemberSpecialization(redeclTemp)) {
explicitSpecSuppressor = temp->getTemplatedDecl();
}
}
}
// We should never be looking for an attribute directly on a template.
assert(!explicitSpecSuppressor || !isa<TemplateDecl>(explicitSpecSuppressor));
// If this member is an explicit member specialization, and it has
// an explicit attribute, ignore visibility from the parent.
bool considerClassVisibility = true;
if (explicitSpecSuppressor &&
// optimization: hasDVA() is true only with explicit visibility.
LV.isVisibilityExplicit() &&
classLV.getVisibility() != DefaultVisibility &&
hasDirectVisibilityAttribute(explicitSpecSuppressor, computation)) {
considerClassVisibility = false;
}
// Finally, merge in information from the class.
LV.mergeMaybeWithVisibility(classLV, considerClassVisibility);
return LV;
}