clang: lib/AST/CXXInheritance.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
23#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/ADT/iterator_range.h"
27#include
28#include
29#include
30
31using namespace clang;
32
33
34
35
36
38 BaseType = BaseType.getUnqualifiedType();
39 IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects.lookup(BaseType);
40 return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1;
41}
42
43
45 Paths.clear();
46 ClassSubobjects.clear();
47 VisitedDependentRecords.clear();
48 ScratchPath.clear();
49 DetectedVirtual = nullptr;
50}
51
52
53
55 std::swap(Origin, Other.Origin);
56 Paths.swap(Other.Paths);
57 ClassSubobjects.swap(Other.ClassSubobjects);
58 VisitedDependentRecords.swap(Other.VisitedDependentRecords);
59 std::swap(FindAmbiguities, Other.FindAmbiguities);
60 std::swap(RecordPaths, Other.RecordPaths);
61 std::swap(DetectVirtual, Other.DetectVirtual);
62 std::swap(DetectedVirtual, Other.DetectedVirtual);
63}
64
70
74 return false;
75
77
81 return Specifier->getType()->getAsRecordDecl() &&
83 },
84 Paths);
85}
86
89 return false;
90
91 CXXBasePaths Paths(false, false,
92 false);
93
95 return false;
96
98
103 },
104 Paths);
105}
106
110 return Base->getCanonicalDecl() != TargetDecl;
111 });
112}
113
114bool
117
119 if (CurContext->Equals(this))
120 return true;
121
122 return false;
123}
124
127
129 while (true) {
130 for (const auto &I : Record->bases()) {
131 const auto *Base = I.getType()->getAsCXXRecordDecl();
132 if ( || !(Base->isBeingDefined() || Base->isCompleteDefinition()))
133 return false;
134 if (Base->isDependentContext() && ->isCurrentInstantiation(Record))
135 return false;
136
137 Queue.push_back(Base);
138 if (!BaseMatches(Base))
139 return false;
140 }
141
142 if (Queue.empty())
143 break;
144 Record = Queue.pop_back_val();
145 }
146
147 return true;
148}
149
150bool CXXBasePaths::lookupInBases(ASTContext &Context,
153 bool LookupInDependent) {
154 bool FoundPath = false;
155
156
158 bool IsFirstStep = ScratchPath.empty();
159
160 for (const auto &BaseSpec : Record->bases()) {
161
164
166 if (!isCurrentInstantiation) {
167 if (auto *BaseRecord = cast_if_present(
168 BaseSpec.getType()->getAsRecordDecl()))
169 isCurrentInstantiation = BaseRecord->isDependentContext() &&
170 BaseRecord->isCurrentInstantiation(Record);
171 }
172
173
174
175
176
177
178 if (!LookupInDependent &&
179 (BaseType->isDependentType() && !isCurrentInstantiation))
180 continue;
181
182
183
184 IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType];
185 bool VisitBase = true;
186 bool SetVirtual = false;
187 if (BaseSpec.isVirtual()) {
188 VisitBase = !Subobjects.IsVirtBase;
189 Subobjects.IsVirtBase = true;
191
192
193 DetectedVirtual = BaseType->getAsCanonical();
194 SetVirtual = true;
195 }
196 } else {
197 ++Subobjects.NumberOfNonVirtBases;
198 }
200
201 CXXBasePathElement Element;
202 Element.Base = &BaseSpec;
204 if (BaseSpec.isVirtual())
206 else
207 Element.SubobjectNumber = Subobjects.NumberOfNonVirtBases;
208 ScratchPath.push_back(Element);
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225 if (IsFirstStep)
226 ScratchPath.Access = BaseSpec.getAccessSpecifier();
227 else
229 BaseSpec.getAccessSpecifier());
230 }
231
232
233 bool FoundPathThroughBase = false;
234
235 if (BaseMatches(&BaseSpec, ScratchPath)) {
236
237 FoundPath = FoundPathThroughBase = true;
239
240 Paths.push_back(ScratchPath);
242
243
244 return FoundPath;
245 }
246 } else if (VisitBase) {
248 if (LookupInDependent) {
249 const TemplateSpecializationType *TST =
250 BaseSpec.getType()->getAs();
251 if (!TST) {
252 BaseRecord = BaseSpec.getType()->getAsCXXRecordDecl();
253 } else {
255 if (auto *TD =
257 BaseRecord = TD->getTemplatedDecl();
258 }
259 if (BaseRecord) {
261 BaseRecord = nullptr;
262 else if (!VisitedDependentRecords.insert(BaseRecord).second)
263 BaseRecord = nullptr;
264 }
265 } else {
266 BaseRecord = BaseSpec.getType()->castAsCXXRecordDecl();
267 }
268 if (BaseRecord &&
269 lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
270
271
272
273
274
275
276
277
278 FoundPath = FoundPathThroughBase = true;
280 return FoundPath;
281 }
282 }
283
284
285
287 ScratchPath.pop_back();
288 }
289
290
291 if (SetVirtual && !FoundPathThroughBase) {
292 DetectedVirtual = nullptr;
293 }
294 }
295
296
297 ScratchPath.Access = AccessToHere;
298
299 return FoundPath;
300}
301
304 bool LookupInDependent) const {
305
306 if (!Paths.lookupInBases(getASTContext(), this, BaseMatches,
307 LookupInDependent))
308 return false;
309
310
311
313 return true;
314
315
316
317
318
319
320
321
322
323
324
325 Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) {
327 if (!PE.Base->isVirtual())
328 continue;
329
330 auto *VBase = PE.Base->getType()->getAsCXXRecordDecl();
331 if (!VBase)
332 break;
333
334
335
336
337
338 for (const CXXBasePath &HidingP : Paths) {
339 auto *HidingClass =
340 HidingP.back().Base->getType()->getAsCXXRecordDecl();
341 if (!HidingClass)
342 break;
343
344 if (HidingClass->isVirtuallyDerivedFrom(VBase))
345 return true;
346 }
347 }
348 return false;
349 });
350
351 return true;
352}
353
358 "User data for FindBaseClass is not canonical!");
360 ->getCanonicalDecl() == BaseRecord;
361}
362
367 "User data for FindBaseClass is not canonical!");
368 return Specifier->isVirtual() &&
370 ->getCanonicalDecl() == BaseRecord;
371}
372
377
383 return true;
384
385 return false;
386}
387
391 return true;
392
396 return findOrdinaryMember(Specifier->getType()->castAsCXXRecordDecl(),
397 Path, Name);
398 },
399 Paths);
400}
401
405 = Overrides[OverriddenSubobject];
406 if (!llvm::is_contained(SubobjectOverrides, Overriding))
407 SubobjectOverrides.push_back(Overriding);
408}
409
413 MEnd = I->second.end();
414 M != MEnd;
415 ++M)
416 add(I->first, *M);
417 }
418}
419
422 I->second.clear();
423 I->second.push_back(Overriding);
424 }
425}
426
427namespace {
428
429class FinalOverriderCollector {
430
431
432 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
433
434
435 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
436
438
439public:
440 ~FinalOverriderCollector();
441
445};
446
447}
448
449void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
453 unsigned SubobjectNumber = 0;
455 SubobjectNumber
457
458 for (const auto &Base : RD->bases()) {
459 if (const auto *BaseDecl = Base.getType()->getAsCXXRecordDecl()) {
460 if (!BaseDecl->isPolymorphic())
461 continue;
462
463 if (Overriders.empty() && .isVirtual()) {
464
465
466 Collect(BaseDecl, false, InVirtualSubobject, Overriders);
467 continue;
468 }
469
470
471
472
473
474
477 if (Base.isVirtual()) {
479 BaseOverriders = MyVirtualOverriders;
480 if (!MyVirtualOverriders) {
482
483
484
485
486 BaseOverriders = MyVirtualOverriders;
487
488 Collect(BaseDecl, true, BaseDecl, *MyVirtualOverriders);
489 }
490 } else
491 Collect(BaseDecl, false, InVirtualSubobject, ComputedBaseOverriders);
492
493
494
495 for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
496 OMEnd = BaseOverriders->end();
497 OM != OMEnd;
498 ++OM) {
500 Overriders[CanonOM].add(OM->second);
501 }
502 }
503 }
504
505 for (auto *M : RD->methods()) {
506
507 if (!M->isVirtual())
508 continue;
509
511 using OverriddenMethodsRange =
512 llvm::iterator_rangeCXXMethodDecl::method\_iterator;
513 OverriddenMethodsRange OverriddenMethods = CanonM->overridden_methods();
514
515 if (OverriddenMethods.begin() == OverriddenMethods.end()) {
516
517
518
519
520
521
522 Overriders[CanonM].add(SubobjectNumber,
524 InVirtualSubobject));
525 continue;
526 }
527
528
529
530
531
532
533
535 while (!Stack.empty()) {
536 for (const CXXMethodDecl *OM : Stack.pop_back_val()) {
538
539
540
541
542
543
544
545
546
547
548 Overriders[CanonOM].replaceAll(
550 InVirtualSubobject));
551
553 if (OverriddenMethods.begin() == OverriddenMethods.end())
554 continue;
555
556
557
558 Stack.push_back(OverriddenMethods);
559 }
560 }
561
562
563
564 Overriders[CanonM].add(SubobjectNumber,
566 InVirtualSubobject));
567 }
568}
569
570FinalOverriderCollector::~FinalOverriderCollector() {
571 for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
572 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
573 VO != VOEnd;
574 ++VO)
575 delete VO->second;
576}
577
578void
580 FinalOverriderCollector Collector;
581 Collector.Collect(this, false, nullptr, FinalOverriders);
582
583
584
585
586 for (auto &OM : FinalOverriders) {
587 for (auto &SO : OM.second) {
589 if (Overriding.size() < 2)
590 continue;
591
593 if (!M.InVirtualSubobject)
594 return false;
595
596
597
598
599
600
602 if (&M != &OP &&
603 OP.Method->getParent()->isVirtuallyDerivedFrom(
604 M.InVirtualSubobject))
605 return true;
606 return false;
607 };
608
609
610
611 llvm::erase_if(Overriding, IsHidden);
612 }
613 }
614}
615
616static void
619
620 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
623
624 for (const auto &I : RD->bases()) {
625 assert(!I.getType()->isDependentType() &&
626 "Cannot get indirect primary bases for class with dependent bases.");
627
630
631
632
635 }
636
637}
638
639void
642
644 return;
645
646 for (const auto &I : bases()) {
647 assert(!I.getType()->isDependentType() &&
648 "Cannot get indirect primary bases for class with dependent bases.");
649
652
653
654
657 }
658}
Defines the clang::ASTContext interface.
static void AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, CXXIndirectPrimaryBaseSet &Bases)
Definition CXXInheritance.cpp:617
static bool isOrdinaryMember(const NamedDecl *ND)
Definition CXXInheritance.cpp:373
static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, DeclarationName Name)
Definition CXXInheritance.cpp:378
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::MachO::Record Record
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
DeclContext::lookup_iterator Decls
The declarations found inside this base class subobject.
AccessSpecifier Access
The access along this inheritance path.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
CXXBasePaths(bool FindAmbiguities=true, bool RecordPaths=true, bool DetectVirtual=true)
BasePaths - Construct a new BasePaths structure to record the paths for a derived-to-base search.
bool isRecordingPaths() const
Whether we are recording paths.
void setOrigin(const CXXRecordDecl *Rec)
bool isDetectingVirtual() const
Whether we are detecting virtual bases.
void clear()
Clear the base-paths results.
Definition CXXInheritance.cpp:44
friend class CXXRecordDecl
bool isFindingAmbiguities() const
Whether we are finding multiple paths to detect ambiguities.
void swap(CXXBasePaths &Other)
Swap this data structure's contents with another CXXBasePaths object.
Definition CXXInheritance.cpp:54
bool isAmbiguous(CanQualType BaseType) const
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
Definition CXXInheritance.cpp:37
Represents a base class of a C++ class.
A mapping from each virtual member function to its set of final overriders.
A set of all the primary bases for a class.
Represents a static or instance method of a struct/union/class.
overridden_method_range overridden_methods() const
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a C++ struct/union/class.
llvm::function_ref< bool(const CXXBaseSpecifier *Specifier, CXXBasePath &Path)> BaseMatchesCallback
Function type used by lookupInBases() to determine whether a specific base class subobject matches th...
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
Definition CXXInheritance.cpp:640
llvm::function_ref< bool(const CXXRecordDecl *BaseDefinition)> ForallBasesCallback
Function type used by forallBases() as a callback.
bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is provably not derived from the type Base.
Definition CXXInheritance.cpp:107
method_range methods() const
static AccessSpecifier MergeAccess(AccessSpecifier PathAccess, AccessSpecifier DeclAccess)
Calculates the access of a decl that is reached along a path.
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent=false) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
Definition CXXInheritance.cpp:302
CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl)
bool hasDefinition() const
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
Definition CXXInheritance.cpp:579
bool isCurrentInstantiation(const DeclContext *CurContext) const
Determine whether this dependent class is a current instantiation, when viewed from within the given ...
Definition CXXInheritance.cpp:115
bool hasMemberName(DeclarationName N) const
Determine whether this class has a member with the given name, possibly in a non-dependent base class...
Definition CXXInheritance.cpp:388
static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, const CXXRecordDecl *BaseRecord)
Base-class lookup callback that determines whether the given base class specifier refers to a specifi...
Definition CXXInheritance.cpp:363
static bool FindBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, const CXXRecordDecl *BaseRecord)
Base-class lookup callback that determines whether the given base class specifier refers to a specifi...
Definition CXXInheritance.cpp:354
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is virtually derived from the class Base.
Definition CXXInheritance.cpp:87
bool forallBases(ForallBasesCallback BaseMatches) const
Determines if the given callback holds for all the direct or indirect base classes of this type.
Definition CXXInheritance.cpp:125
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
Definition CXXInheritance.cpp:65
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
lookup_result::iterator lookup_iterator
bool isFileContext() const
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
ASTContext & getASTContext() const LLVM_READONLY
bool isInIdentifierNamespace(unsigned NS) const
@ IDNS_Ordinary
Ordinary names.
@ IDNS_Member
Members, declared with object declarations within tag definitions.
@ IDNS_Tag
Tags, declared with 'struct foo;' and referenced with 'struct foo'.
The name of a declaration.
This represents a decl that may have a name.
The set of methods that override a given virtual method in each subobject where it occurs.
void replaceAll(UniqueVirtualMethod Overriding)
Definition CXXInheritance.cpp:420
MapType::iterator iterator
MapType::const_iterator const_iterator
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding)
Definition CXXInheritance.cpp:402
SmallVectorImpl< UniqueVirtualMethod >::const_iterator overriding_const_iterator
A (possibly-)qualified type.
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
U cast(CodeGen::Address addr)
@ Other
Other implicit parameter.
Represents an element in a path from a derived class to a base class.
int SubobjectNumber
Identifies which base class subobject (of type Base->getType()) this base path element refers to.
const CXXRecordDecl * Class
The record decl of the class that the base is a base of.
const CXXBaseSpecifier * Base
The base specifier that states the link from a derived class to a base class, which will be followed ...
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...