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"
39 IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[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);
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()) {
165 bool isCurrentInstantiation = isa<InjectedClassNameType>(BaseType);
166 if (!isCurrentInstantiation) {
167 if (
auto *BaseRecord = cast_if_present<CXXRecordDecl>(
168 BaseSpec.getType()->getAsRecordDecl()))
169 isCurrentInstantiation = BaseRecord->isDependentContext() &&
170 BaseRecord->isCurrentInstantiation(
Record);
178 if (!LookupInDependent &&
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;
204 if (BaseSpec.isVirtual())
205 Element.SubobjectNumber = 0;
207 Element.SubobjectNumber = Subobjects.NumberOfNonVirtBases;
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) {
252 BaseRecord = BaseSpec.getType()->getAsCXXRecordDecl();
257 BaseRecord = TD->getTemplatedDecl();
261 BaseRecord =
nullptr;
262 else if (!VisitedDependentRecords.insert(BaseRecord).second)
263 BaseRecord =
nullptr;
266 BaseRecord = BaseSpec.getType()->castAsCXXRecordDecl();
269 lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
278 FoundPath = FoundPathThroughBase =
true;
287 ScratchPath.pop_back();
291 if (SetVirtual && !FoundPathThroughBase) {
292 DetectedVirtual =
nullptr;
297 ScratchPath.
Access = AccessToHere;
304 bool LookupInDependent)
const {
312 if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities())
327 if (!PE.Base->isVirtual())
330 auto *VBase = PE.Base->getType()->getAsCXXRecordDecl();
340 HidingP.back().
Base->getType()->getAsCXXRecordDecl();
344 if (HidingClass->isVirtuallyDerivedFrom(VBase))
358 "User data for FindBaseClass is not canonical!");
359 return cast<CXXRecordDecl>(Specifier->getType()->getAsRecordDecl())
360 ->getCanonicalDecl() == BaseRecord;
367 "User data for FindBaseClass is not canonical!");
368 return Specifier->isVirtual() &&
369 cast<CXXRecordDecl>(Specifier->getType()->getAsRecordDecl())
370 ->getCanonicalDecl() == BaseRecord;
405 = Overrides[OverriddenSubobject];
406 if (!llvm::is_contained(SubobjectOverrides, Overriding))
407 SubobjectOverrides.push_back(Overriding);
413 MEnd = I->second.end();
423 I->second.push_back(Overriding);
429class FinalOverriderCollector {
432 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
435 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
440 ~FinalOverriderCollector();
449void FinalOverriderCollector::Collect(
const CXXRecordDecl *RD,
453 unsigned SubobjectNumber = 0;
459 if (
const auto *BaseDecl =
Base.getType()->getAsCXXRecordDecl()) {
460 if (!BaseDecl->isPolymorphic())
463 if (Overriders.empty() && !
Base.isVirtual()) {
466 Collect(BaseDecl,
false, InVirtualSubobject, Overriders);
477 if (
Base.isVirtual()) {
479 BaseOverriders = MyVirtualOverriders;
480 if (!MyVirtualOverriders) {
486 BaseOverriders = MyVirtualOverriders;
488 Collect(BaseDecl,
true, BaseDecl, *MyVirtualOverriders);
491 Collect(BaseDecl,
false, InVirtualSubobject, ComputedBaseOverriders);
495 for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
496 OMEnd = BaseOverriders->end();
500 Overriders[CanonOM].add(OM->second);
505 for (
auto *M : RD->
methods()) {
511 using OverriddenMethodsRange =
512 llvm::iterator_range<CXXMethodDecl::method_iterator>;
515 if (OverriddenMethods.begin() == OverriddenMethods.end()) {
522 Overriders[CanonM].add(SubobjectNumber,
524 InVirtualSubobject));
535 while (!Stack.empty()) {
548 Overriders[CanonOM].replaceAll(
550 InVirtualSubobject));
553 if (OverriddenMethods.begin() == OverriddenMethods.end())
558 Stack.push_back(OverriddenMethods);
564 Overriders[CanonM].add(SubobjectNumber,
566 InVirtualSubobject));
570FinalOverriderCollector::~FinalOverriderCollector() {
571 for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
572 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
580 FinalOverriderCollector Collector;
581 Collector.Collect(
this,
false,
nullptr, FinalOverriders);
586 for (
auto &OM : FinalOverriders) {
587 for (
auto &SO : OM.second) {
589 if (Overriding.size() < 2)
593 if (!M.InVirtualSubobject)
603 OP.Method->getParent()->isVirtuallyDerivedFrom(
604 M.InVirtualSubobject))
611 llvm::erase_if(Overriding, IsHidden);
624 for (
const auto &I : RD->
bases()) {
625 assert(!I.getType()->isDependentType() &&
626 "Cannot get indirect primary bases for class with dependent bases.");
629 cast<CXXRecordDecl>(I.getType()->getAsRecordDecl());
646 for (
const auto &I :
bases()) {
647 assert(!I.getType()->isDependentType() &&
648 "Cannot get indirect primary bases for class with dependent bases.");
651 cast<CXXRecordDecl>(I.getType()->getAsRecordDecl());
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
static RecordDecl * getAsRecordDecl(QualType BaseType, HeuristicResolver &Resolver)
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
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...
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...
bool isRecordingPaths() const
Whether we are recording paths.
bool isDetectingVirtual() const
Whether we are detecting virtual bases.
bool isAmbiguous(CanQualType BaseType)
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
void clear()
Clear the base-paths results.
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.
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.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
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...
bool hasDefinition() const
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
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...
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...
llvm::function_ref< bool(const CXXRecordDecl *BaseDefinition)> ForallBasesCallback
Function type used by forallBases() as a callback.
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.
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
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.
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
SmallVectorImpl< UniqueVirtualMethod >::const_iterator overriding_const_iterator
MapType::const_iterator const_iterator
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding)
A (possibly-)qualified type.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Represents a C++ template name within the type system.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
Represents a type template specialization; the template must be a class template, a type alias templa...
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * getAs() const
Member-template getAs<specific type>'.
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
@ Other
Other implicit parameter.
Represents an element in a path from a derived class to a base class.
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...