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"
38 BaseType = BaseType.getUnqualifiedType();
39 IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects.lookup(BaseType);
40 return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1;
46 ClassSubobjects.clear();
47 VisitedDependentRecords.clear();
49 DetectedVirtual =
nullptr;
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);
81 return Specifier->getType()->getAsRecordDecl() &&
110 return Base->getCanonicalDecl() != TargetDecl;
119 if (CurContext->
Equals(
this))
130 for (
const auto &I :
Record->bases()) {
131 const auto *
Base = I.getType()->getAsCXXRecordDecl();
132 if (!
Base || !(
Base->isBeingDefined() ||
Base->isCompleteDefinition()))
134 if (
Base->isDependentContext() && !
Base->isCurrentInstantiation(
Record))
137 Queue.push_back(
Base);
138 if (!BaseMatches(
Base))
144 Record = Queue.pop_back_val();
150bool CXXBasePaths::lookupInBases(
ASTContext &Context,
153 bool LookupInDependent) {
154 bool FoundPath =
false;
158 bool IsFirstStep = ScratchPath.empty();
160 for (
const auto &BaseSpec :
Record->bases()) {
171 if (!LookupInDependent && BaseType->isDependentType()) {
173 if (!isCurrentInstantiation) {
174 if (
auto *BaseRecord = cast_if_present<CXXRecordDecl>(
175 BaseSpec.getType()->getAsRecordDecl()))
176 isCurrentInstantiation = BaseRecord->isDependentContext() &&
177 BaseRecord->isCurrentInstantiation(
Record);
179 if (!isCurrentInstantiation)
185 IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType];
186 bool VisitBase =
true;
187 bool SetVirtual =
false;
188 if (BaseSpec.isVirtual()) {
189 VisitBase = !Subobjects.IsVirtBase;
190 Subobjects.IsVirtBase =
true;
198 ++Subobjects.NumberOfNonVirtBases;
202 CXXBasePathElement Element;
203 Element.
Base = &BaseSpec;
205 if (BaseSpec.isVirtual())
209 ScratchPath.push_back(Element);
227 ScratchPath.Access = BaseSpec.getAccessSpecifier();
230 BaseSpec.getAccessSpecifier());
234 bool FoundPathThroughBase =
false;
236 if (BaseMatches(&BaseSpec, ScratchPath)) {
238 FoundPath = FoundPathThroughBase =
true;
241 Paths.push_back(ScratchPath);
247 }
else if (VisitBase) {
249 if (LookupInDependent) {
250 const TemplateSpecializationType *TST =
251 BaseSpec.getType()->getAs<TemplateSpecializationType>();
253 BaseRecord = BaseSpec.getType()->getAsCXXRecordDecl();
258 BaseRecord = TD->getTemplatedDecl();
262 BaseRecord =
nullptr;
263 else if (!VisitedDependentRecords.insert(BaseRecord).second)
264 BaseRecord =
nullptr;
267 BaseRecord = BaseSpec.getType()->castAsCXXRecordDecl();
270 lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
279 FoundPath = FoundPathThroughBase =
true;
288 ScratchPath.pop_back();
292 if (SetVirtual && !FoundPathThroughBase) {
293 DetectedVirtual =
nullptr;
298 ScratchPath.
Access = AccessToHere;
305 bool LookupInDependent)
const {
326 Paths.Paths.remove_if([&Paths](
const CXXBasePath &Path) {
328 if (!PE.Base->isVirtual())
331 auto *VBase = PE.Base->getType()->getAsCXXRecordDecl();
341 HidingP.back().Base->getType()->getAsCXXRecordDecl();
345 if (HidingClass->isVirtuallyDerivedFrom(VBase))
359 "User data for FindBaseClass is not canonical!");
361 ->getCanonicalDecl() == BaseRecord;
368 "User data for FindBaseClass is not canonical!");
369 return Specifier->isVirtual() &&
371 ->getCanonicalDecl() == BaseRecord;
406 = Overrides[OverriddenSubobject];
407 if (!llvm::is_contained(SubobjectOverrides, Overriding))
408 SubobjectOverrides.push_back(Overriding);
414 MEnd = I->second.end();
424 I->second.push_back(Overriding);
430class FinalOverriderCollector {
433 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
436 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
441 ~FinalOverriderCollector();
450void FinalOverriderCollector::Collect(
const CXXRecordDecl *RD,
454 unsigned SubobjectNumber = 0;
459 for (
const auto &Base : RD->
bases()) {
460 if (
const auto *BaseDecl =
Base.getType()->getAsCXXRecordDecl()) {
461 if (!BaseDecl->isPolymorphic())
464 if (Overriders.empty() && !
Base.isVirtual()) {
467 Collect(BaseDecl,
false, InVirtualSubobject, Overriders);
478 if (
Base.isVirtual()) {
480 BaseOverriders = MyVirtualOverriders;
481 if (!MyVirtualOverriders) {
487 BaseOverriders = MyVirtualOverriders;
489 Collect(BaseDecl,
true, BaseDecl, *MyVirtualOverriders);
492 Collect(BaseDecl,
false, InVirtualSubobject, ComputedBaseOverriders);
496 for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
497 OMEnd = BaseOverriders->end();
501 Overriders[CanonOM].add(OM->second);
506 for (
auto *M : RD->
methods()) {
512 using OverriddenMethodsRange =
513 llvm::iterator_range<CXXMethodDecl::method_iterator>;
516 if (OverriddenMethods.begin() == OverriddenMethods.end()) {
523 Overriders[CanonM].add(SubobjectNumber,
525 InVirtualSubobject));
536 while (!Stack.empty()) {
549 Overriders[CanonOM].replaceAll(
551 InVirtualSubobject));
554 if (OverriddenMethods.begin() == OverriddenMethods.end())
559 Stack.push_back(OverriddenMethods);
565 Overriders[CanonM].add(SubobjectNumber,
567 InVirtualSubobject));
571FinalOverriderCollector::~FinalOverriderCollector() {
572 for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
573 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
581 FinalOverriderCollector Collector;
582 Collector.Collect(
this,
false,
nullptr, FinalOverriders);
587 for (
auto &OM : FinalOverriders) {
588 for (
auto &SO : OM.second) {
590 if (Overriding.size() < 2)
594 if (!M.InVirtualSubobject)
604 OP.Method->getParent()->isVirtuallyDerivedFrom(
605 M.InVirtualSubobject))
612 llvm::erase_if(Overriding, IsHidden);
625 for (
const auto &I : RD->
bases()) {
626 assert(!I.getType()->isDependentType() &&
627 "Cannot get indirect primary bases for class with dependent bases.");
647 for (
const auto &I :
bases()) {
648 assert(!I.getType()->isDependentType() &&
649 "Cannot get indirect primary bases for class with dependent bases.");
Defines the clang::ASTContext interface.
static void AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, CXXIndirectPrimaryBaseSet &Bases)
static bool isOrdinaryMember(const NamedDecl *ND)
static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, DeclarationName Name)
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.
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.
bool isAmbiguous(CanQualType BaseType) const
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
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.
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.
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...
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...
bool isCurrentInstantiation(const DeclContext *CurContext) const
Determine whether this dependent class is a current instantiation, when viewed from within the given ...
bool hasMemberName(DeclarationName N) const
Determine whether this class has a member with the given name, possibly in a non-dependent base class...
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...
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...
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is virtually derived from the class Base.
bool forallBases(ForallBasesCallback BaseMatches) const
Determines if the given callback holds for all the direct or indirect base classes of this type.
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.
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)
MapType::iterator iterator
MapType::const_iterator const_iterator
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding)
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.
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
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...