Go to the documentation of this file.
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/ADT/SetVector.h"
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/ADT/iterator_range.h"
28 #include "llvm/Support/Casting.h"
34 using namespace clang;
42 IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[BaseType];
43 return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1;
49 ClassSubobjects.clear();
50 VisitedDependentRecords.clear();
52 DetectedVirtual =
nullptr;
58 std::swap(Origin, Other.Origin);
59 Paths.swap(Other.Paths);
60 ClassSubobjects.swap(Other.ClassSubobjects);
61 VisitedDependentRecords.swap(Other.VisitedDependentRecords);
62 std::swap(FindAmbiguities, Other.FindAmbiguities);
63 std::swap(RecordPaths, Other.RecordPaths);
64 std::swap(DetectVirtual, Other.DetectVirtual);
65 std::swap(DetectedVirtual, Other.DetectedVirtual);
112 return Base->getCanonicalDecl() != TargetDecl;
121 if (CurContext->
Equals(
this))
132 for (
const auto &I : Record->
bases()) {
140 (
Base->isDependentContext() &&
141 !
Base->isCurrentInstantiation(Record))) {
145 Queue.push_back(
Base);
146 if (!BaseMatches(
Base))
152 Record = Queue.pop_back_val();
158 bool CXXBasePaths::lookupInBases(
ASTContext &Context,
161 bool LookupInDependent) {
162 bool FoundPath =
false;
166 bool IsFirstStep = ScratchPath.empty();
168 for (
const auto &BaseSpec : Record->
bases()) {
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;
197 ++Subobjects.NumberOfNonVirtBases;
202 Element.
Base = &BaseSpec;
203 Element.
Class = Record;
204 if (BaseSpec.isVirtual())
208 ScratchPath.push_back(Element);
226 ScratchPath.
Access = BaseSpec.getAccessSpecifier();
229 BaseSpec.getAccessSpecifier());
233 bool FoundPathThroughBase =
false;
235 if (BaseMatches(&BaseSpec, ScratchPath)) {
237 FoundPath = FoundPathThroughBase =
true;
240 Paths.push_back(ScratchPath);
246 }
else if (VisitBase) {
248 if (LookupInDependent) {
249 BaseRecord =
nullptr;
253 if (
auto *RT = BaseSpec.getType()->getAs<
RecordType>())
254 BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
259 BaseRecord = TD->getTemplatedDecl();
263 VisitedDependentRecords.count(BaseRecord)) {
264 BaseRecord =
nullptr;
266 VisitedDependentRecords.insert(BaseRecord);
270 BaseRecord = cast<CXXRecordDecl>(
274 lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
283 FoundPath = FoundPathThroughBase =
true;
292 ScratchPath.pop_back();
296 if (SetVirtual && !FoundPathThroughBase) {
297 DetectedVirtual =
nullptr;
302 ScratchPath.
Access = AccessToHere;
309 bool LookupInDependent)
const {
317 if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities())
330 Paths.Paths.remove_if([&Paths](
const CXXBasePath &Path) {
332 if (!PE.Base->isVirtual())
337 VBase = cast<CXXRecordDecl>(Record->getDecl());
348 HidingP.back().Base->getType()->getAs<
RecordType>())
349 HidingClass = cast<CXXRecordDecl>(Record->getDecl());
367 "User data for FindBaseClass is not canonical!");
369 ->getCanonicalDecl() == BaseRecord;
376 "User data for FindBaseClass is not canonical!");
379 ->getCanonicalDecl() == BaseRecord;
435 std::vector<const NamedDecl *> Results;
437 bool AnyOrdinaryMembers =
false;
440 AnyOrdinaryMembers =
true;
442 Results.push_back(ND);
444 if (AnyOrdinaryMembers)
449 Paths.setOrigin(
this);
459 Results.push_back(*I);
467 = Overrides[OverriddenSubobject];
468 if (!llvm::is_contained(SubobjectOverrides, Overriding))
469 SubobjectOverrides.push_back(Overriding);
475 MEnd = I->second.end();
485 I->second.push_back(Overriding);
491 class FinalOverriderCollector {
494 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
497 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
502 ~FinalOverriderCollector();
511 void FinalOverriderCollector::Collect(
const CXXRecordDecl *RD,
515 unsigned SubobjectNumber = 0;
522 const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
526 if (Overriders.empty() && !
Base.isVirtual()) {
529 Collect(BaseDecl,
false, InVirtualSubobject, Overriders);
540 if (
Base.isVirtual()) {
542 BaseOverriders = MyVirtualOverriders;
543 if (!MyVirtualOverriders) {
549 BaseOverriders = MyVirtualOverriders;
551 Collect(BaseDecl,
true, BaseDecl, *MyVirtualOverriders);
554 Collect(BaseDecl,
false, InVirtualSubobject, ComputedBaseOverriders);
558 for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
559 OMEnd = BaseOverriders->end();
563 Overriders[CanonOM].add(OM->second);
568 for (
auto *M : RD->
methods()) {
574 using OverriddenMethodsRange =
575 llvm::iterator_range<CXXMethodDecl::method_iterator>;
578 if (OverriddenMethods.begin() == OverriddenMethods.end()) {
585 Overriders[CanonM].add(SubobjectNumber,
587 InVirtualSubobject));
598 while (!Stack.empty()) {
611 Overriders[CanonOM].replaceAll(
613 InVirtualSubobject));
616 if (OverriddenMethods.begin() == OverriddenMethods.end())
621 Stack.push_back(OverriddenMethods);
627 Overriders[CanonM].add(SubobjectNumber,
629 InVirtualSubobject));
633 FinalOverriderCollector::~FinalOverriderCollector() {
634 for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
635 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
643 FinalOverriderCollector Collector;
644 Collector.Collect(
this,
false,
nullptr, FinalOverriders);
649 for (
auto &OM : FinalOverriders) {
650 for (
auto &SO : OM.second) {
652 if (Overriding.size() < 2)
656 if (!M.InVirtualSubobject)
666 OP.Method->getParent()->isVirtuallyDerivedFrom(
667 M.InVirtualSubobject))
674 llvm::erase_if(Overriding, IsHidden);
687 for (
const auto &I : RD->
bases()) {
688 assert(!I.getType()->isDependentType() &&
689 "Cannot get indirect primary bases for class with dependent bases.");
709 for (
const auto &I :
bases()) {
710 assert(!I.getType()->isDependentType() &&
711 "Cannot get indirect primary bases for class with dependent bases.");
void clear()
Clear the base-paths results.
ASTContext & getASTContext() const LLVM_READONLY
A mapping from each virtual member function to its set of final overriders.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void swap(CXXBasePaths &Other)
Swap this data structure's contents with another CXXBasePaths object.
DeclContext::lookup_iterator Decls
The declarations found inside this base class subobject.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
This represents a decl that may have a name.
A (possibly-)qualified type.
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known.
bool isDetectingVirtual() const
Whether we are detecting virtual bases.
static AccessSpecifier MergeAccess(AccessSpecifier PathAccess, AccessSpecifier DeclAccess)
Calculates the access of a decl that is reached along a path.
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a type template specialization; the template must be a class template, a type alias templa...
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
llvm::function_ref< bool(const CXXRecordDecl *BaseDefinition)> ForallBasesCallback
Function type used by forallBases() as a callback.
MapType::const_iterator const_iterator
int SubobjectNumber
Identifies which base class subobject (of type Base->getType()) this base path element refers to.
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, DeclarationName Name)
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...
The name of a declaration.
The set of methods that override a given virtual method in each subobject where it occurs.
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...
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
overridden_method_range overridden_methods() const
MapType::iterator iterator
method_range methods() const
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is virtually derived from the class Base.
bool isCurrentInstantiation(const DeclContext *CurContext) const
Determine whether this dependent class is a current instantiation, when viewed from within the given ...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool isAmbiguous(CanQualType BaseType)
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
const T * getAs() const
Member-template getAs<specific type>'.
void replaceAll(UniqueVirtualMethod Overriding)
Represents an element in a path from a derived class to a base class.
A set of all the primary bases for a class.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...
static bool isOrdinaryMember(const NamedDecl *ND)
bool forallBases(ForallBasesCallback BaseMatches) const
Determines if the given callback holds for all the direct or indirect base classes of this type.
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...
@ IDNS_Member
Members, declared with object declarations within tag definitions.
@ IDNS_Ordinary
Ordinary names.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
bool hasMemberName(DeclarationName N) const
Determine whether this class has a member with the given name, possibly in a non-dependent base class...
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool isInIdentifierNamespace(unsigned NS) const
Represents a C++ struct/union/class.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
static bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name)
Represents a C++ template name within the type system.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
const NestedNameSpecifier * Specifier
bool isFileContext() const
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isRecordingPaths() const
Whether we are recording paths.
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a base class of a C++ class.
bool hasDefinition() const
const CXXBaseSpecifier * Base
The base specifier that states the link from a derived class to a base class, which will be followed ...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
AccessSpecifier Access
The access along this inheritance path.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
RecordDecl * getDecl() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding)
bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is provably not derived from the type Base.
static void AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, CXXIndirectPrimaryBaseSet &Bases)
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this 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...
std::vector< const NamedDecl * > lookupDependentName(DeclarationName Name, llvm::function_ref< bool(const NamedDecl *ND)> Filter)
Performs an imprecise lookup of a dependent name in this class.
SmallVectorImpl< UniqueVirtualMethod >::const_iterator overriding_const_iterator
@ IDNS_Tag
Tags, declared with 'struct foo;' and referenced with 'struct foo'.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
bool isFindingAmbiguities() const
Whether we are finding multiple paths to detect ambiguities.
const CXXRecordDecl * Class
The record decl of the class that the base is a base of.
Represents a static or instance method of a struct/union/class.
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.