17 #include "llvm/ADT/SetVector.h"
21 using namespace clang;
25 void CXXBasePaths::ComputeDeclsFound() {
26 assert(NumDeclsFound == 0 && !DeclsFound &&
27 "Already computed the set of declarations");
29 llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8> > Decls;
31 Decls.insert(Path->Decls.front());
33 NumDeclsFound = Decls.size();
34 DeclsFound =
new NamedDecl * [NumDeclsFound];
35 std::copy(Decls.begin(), Decls.end(), DeclsFound);
39 if (NumDeclsFound == 0)
52 std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
53 return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
59 ClassSubobjects.clear();
61 DetectedVirtual =
nullptr;
67 std::swap(Origin, Other.Origin);
68 Paths.swap(Other.Paths);
69 ClassSubobjects.swap(Other.ClassSubobjects);
70 std::swap(FindAmbiguities, Other.FindAmbiguities);
71 std::swap(RecordPaths, Other.RecordPaths);
72 std::swap(DetectVirtual, Other.DetectVirtual);
73 std::swap(DetectedVirtual, Other.DetectedVirtual);
87 Paths.
setOrigin(const_cast<CXXRecordDecl*>(
this));
103 Paths.
setOrigin(const_cast<CXXRecordDecl*>(
this));
107 const_cast<void *>(BasePtr),
126 if (CurContext->
Equals(
this))
134 bool AllowShortCircuit)
const {
138 bool AllMatches =
true;
140 for (
const auto &I : Record->
bases()) {
143 if (AllowShortCircuit)
return false;
153 if (AllowShortCircuit)
return false;
158 Queue.push_back(Base);
159 if (!BaseMatches(Base, OpaqueData)) {
160 if (AllowShortCircuit)
return false;
168 Record = Queue.pop_back_val();
182 bool IsFirstStep = ScratchPath.empty();
184 for (
const auto &BaseSpec : Record->
bases()) {
200 std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
201 bool VisitBase =
true;
202 bool SetVirtual =
false;
203 if (BaseSpec.isVirtual()) {
204 VisitBase = !Subobjects.first;
205 Subobjects.first =
true;
218 Element.
Base = &BaseSpec;
219 Element.
Class = Record;
220 if (BaseSpec.isVirtual())
224 ScratchPath.push_back(Element);
242 ScratchPath.
Access = BaseSpec.getAccessSpecifier();
245 BaseSpec.getAccessSpecifier());
249 bool FoundPathThroughBase =
false;
251 if (BaseMatches(&BaseSpec, ScratchPath, UserData)) {
253 FoundPath = FoundPathThroughBase =
true;
256 Paths.push_back(ScratchPath);
262 }
else if (VisitBase) {
264 = cast<CXXRecordDecl>(BaseSpec.getType()->castAs<
RecordType>()
266 if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) {
275 FoundPath = FoundPathThroughBase =
true;
284 ScratchPath.pop_back();
288 if (SetVirtual && !FoundPathThroughBase) {
289 DetectedVirtual =
nullptr;
294 ScratchPath.
Access = AccessToHere;
303 if (!Paths.lookupInBases(
getASTContext(),
this, BaseMatches, UserData))
321 Paths.Paths.remove_if([&Paths](
const CXXBasePath &Path) {
323 if (!PE.Base->isVirtual())
328 VBase = cast<CXXRecordDecl>(Record->getDecl());
339 HidingP.back().Base->getType()->getAs<
RecordType>())
340 HidingClass = cast<CXXRecordDecl>(Record->getDecl());
358 "User data for FindBaseClass is not canonical!");
360 ->getCanonicalDecl() == BaseRecord;
367 "User data for FindBaseClass is not canonical!");
370 ->getCanonicalDecl() == BaseRecord;
401 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS))
420 if (isa<TypedefNameDecl>(Path.
Decls.
front()) ||
431 = Overrides[OverriddenSubobject];
432 if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(),
433 Overriding) == SubobjectOverrides.end())
434 SubobjectOverrides.push_back(Overriding);
440 MEnd = I->second.end();
450 I->second.push_back(Overriding);
456 class FinalOverriderCollector {
459 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
462 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
467 ~FinalOverriderCollector();
475 void FinalOverriderCollector::Collect(
const CXXRecordDecl *RD,
479 unsigned SubobjectNumber = 0;
486 const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
490 if (Overriders.empty() && !
Base.isVirtual()) {
493 Collect(BaseDecl,
false, InVirtualSubobject, Overriders);
504 if (
Base.isVirtual()) {
506 BaseOverriders = MyVirtualOverriders;
507 if (!MyVirtualOverriders) {
513 BaseOverriders = MyVirtualOverriders;
515 Collect(BaseDecl,
true, BaseDecl, *MyVirtualOverriders);
518 Collect(BaseDecl,
false, InVirtualSubobject, ComputedBaseOverriders);
522 for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
523 OMEnd = BaseOverriders->end();
527 = cast<CXXMethodDecl>(OM->first->getCanonicalDecl());
528 Overriders[CanonOM].add(OM->second);
533 for (
auto *M : RD->
methods()) {
538 CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl());
548 Overriders[CanonM].add(SubobjectNumber,
550 InVirtualSubobject));
560 typedef llvm::iterator_range<CXXMethodDecl::method_iterator>
565 while (!Stack.empty()) {
578 Overriders[CanonOM].replaceAll(
580 InVirtualSubobject));
595 Overriders[CanonM].add(SubobjectNumber,
597 InVirtualSubobject));
601 FinalOverriderCollector::~FinalOverriderCollector() {
602 for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
603 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
611 FinalOverriderCollector Collector;
612 Collector.Collect(
this,
false,
nullptr, FinalOverriders);
617 for (
auto &OM : FinalOverriders) {
618 for (
auto &SO : OM.second) {
620 if (Overriding.size() < 2)
624 if (!M.InVirtualSubobject)
634 OP.Method->getParent()->isVirtuallyDerivedFrom(
635 M.InVirtualSubobject))
641 std::remove_if(Overriding.begin(), Overriding.end(), IsHidden),
655 for (
const auto &I : RD->
bases()) {
656 assert(!I.getType()->isDependentType() &&
657 "Cannot get indirect primary bases for class with dependent bases.");
660 cast<CXXRecordDecl>(I.getType()->castAs<
RecordType>()->getDecl());
664 if (BaseDecl->getNumVBases())
677 for (
const auto &I :
bases()) {
678 assert(!I.getType()->isDependentType() &&
679 "Cannot get indirect primary bases for class with dependent bases.");
682 cast<CXXRecordDecl>(I.getType()->castAs<
RecordType>()->getDecl());
686 if (BaseDecl->getNumVBases())
Defines the clang::ASTContext interface.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
void setOrigin(CXXRecordDecl *Rec)
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
QualType getType() const
Retrieves the type of the base class.
method_range methods() const
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
void swap(CXXBasePaths &Other)
Swap this data structure's contents with another CXXBasePaths object.
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
MapType::iterator iterator
bool isPrimaryBaseVirtual() const
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
DeclContext::lookup_result Decls
The set of declarations found inside this base class subobject.
void clear()
Clear the base-paths results.
MapType::const_iterator const_iterator
bool isFindingAmbiguities() const
Whether we are finding multiple paths to detect ambiguities.
method_iterator end_overridden_methods() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool isRecordingPaths() const
Whether we are recording paths.
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
static DeclarationName getFromOpaquePtr(void *P)
bool forallBases(ForallBasesCallback *BaseMatches, void *UserData, bool AllowShortCircuit=true) const
Determines if the given callback holds for all the direct or indirect base classes of this type...
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding)
The set of methods that override a given virtual method in each subobject where it occurs...
RecordDecl * getDecl() const
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
bool isDetectingVirtual() const
Whether we are detecting virtual bases.
std::vector< bool > & Stack
static bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget)
NamedDecl ** decl_iterator
int SubobjectNumber
Identifies which base class subobject (of type Base->getType()) this base path element refers to...
static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData)
Base-class lookup callback that determines whether there exists a member with the given name that can...
bool isDependentType() const
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...
DeclContextLookupResult slice(size_t N) const
RecordDecl * getDefinition() const
const CXXBaseSpecifier * Base
The base specifier that states the link from a derived class to a base class, which will be followed ...
SmallVectorImpl< UniqueVirtualMethod >::const_iterator overriding_const_iterator
method_iterator begin_overridden_methods() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
A set of all the primary bases for a class.
bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData)
Function type used by lookupInBases() to determine whether a specific base class subobject matches th...
ASTContext & getASTContext() const LLVM_READONLY
Represents a static or instance method of a struct/union/class.
static bool FindBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *BaseRecord)
Base-class lookup callback that determines whether the given base class specifier refers to a specifi...
lookup_result lookup(DeclarationName Name) const
bool isFileContext() const
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is virtually derived from the class Base.
Represents an element in a path from a derived class to a base class.
bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, CXXBasePaths &Paths) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
static void AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, CXXIndirectPrimaryBaseSet &Bases)
A mapping from each virtual member function to its set of final overriders.
bool isAmbiguous(CanQualType BaseType)
Determine whether the path from the most-derived type to the given base type is ambiguous (i...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool isCurrentInstantiation(const DeclContext *CurContext) const
Determine whether this dependent class is a current instantiation, when viewed from within the given ...
static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *BaseRecord)
Base-class lookup callback that determines whether the given base class specifier refers to a specifi...
static AccessSpecifier MergeAccess(AccessSpecifier PathAccess, AccessSpecifier DeclAccess)
Calculates the access of a decl that is reached along a path.
llvm::iterator_range< decl_iterator > decl_range
Represents a base class of a C++ class.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Represents a C++ struct/union/class.
AccessSpecifier Access
The access along this inheritance path. This is only calculated when recording paths. AS_none is a special value used to indicate a path which permits no legal access.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC...
static bool FindTagMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *Name)
Base-class lookup callback that determines whether there exists a tag with the given name...
bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is provably not derived from the type Base.
void replaceAll(UniqueVirtualMethod Overriding)
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
bool isPolymorphic() const
const CXXRecordDecl * Class
The record decl of the class that the base is a base of.
std::list< CXXBasePath >::iterator paths_iterator
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *Name)
Base-class lookup callback that determines whether there exists a member with the given name...