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 = llvm::make_unique<NamedDecl *[]>(NumDeclsFound);
35 std::copy(Decls.begin(), Decls.end(), DeclsFound.get());
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));
108 Paths.
setOrigin(const_cast<CXXRecordDecl*>(
this));
131 if (CurContext->
Equals(
this))
138 bool AllowShortCircuit)
const {
142 bool AllMatches =
true;
144 for (
const auto &
I : Record->
bases()) {
147 if (AllowShortCircuit)
return false;
157 if (AllowShortCircuit)
return false;
162 Queue.push_back(Base);
163 if (!BaseMatches(Base)) {
164 if (AllowShortCircuit)
return false;
172 Record = Queue.pop_back_val();
178 bool CXXBasePaths::lookupInBases(
185 bool IsFirstStep = ScratchPath.empty();
187 for (
const auto &BaseSpec : Record->
bases()) {
203 std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
204 bool VisitBase =
true;
205 bool SetVirtual =
false;
206 if (BaseSpec.isVirtual()) {
207 VisitBase = !Subobjects.first;
208 Subobjects.first =
true;
221 Element.
Base = &BaseSpec;
222 Element.
Class = Record;
223 if (BaseSpec.isVirtual())
227 ScratchPath.push_back(Element);
245 ScratchPath.
Access = BaseSpec.getAccessSpecifier();
248 BaseSpec.getAccessSpecifier());
252 bool FoundPathThroughBase =
false;
254 if (BaseMatches(&BaseSpec, ScratchPath)) {
256 FoundPath = FoundPathThroughBase =
true;
259 Paths.push_back(ScratchPath);
265 }
else if (VisitBase) {
267 = cast<CXXRecordDecl>(BaseSpec.getType()->castAs<
RecordType>()
269 if (lookupInBases(Context, BaseRecord, BaseMatches)) {
278 FoundPath = FoundPathThroughBase =
true;
287 ScratchPath.pop_back();
291 if (SetVirtual && !FoundPathThroughBase) {
292 DetectedVirtual =
nullptr;
297 ScratchPath.
Access = AccessToHere;
305 if (!Paths.lookupInBases(getASTContext(),
this, BaseMatches))
323 Paths.Paths.remove_if([&Paths](
const CXXBasePath &Path) {
325 if (!PE.Base->isVirtual())
330 VBase = cast<CXXRecordDecl>(Record->getDecl());
341 HidingP.back().Base->getType()->getAs<
RecordType>())
342 HidingClass = cast<CXXRecordDecl>(Record->getDecl());
360 "User data for FindBaseClass is not canonical!");
362 ->getCanonicalDecl() == BaseRecord;
369 "User data for FindBaseClass is not canonical!");
372 ->getCanonicalDecl() == BaseRecord;
384 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS_Tag))
397 const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member;
401 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS))
416 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS_OMPReduction))
434 if (isa<TypedefNameDecl>(Path.
Decls.
front()) ||
435 Path.
Decls.
front()->isInIdentifierNamespace(IDNS_Tag))
445 = Overrides[OverriddenSubobject];
446 if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(),
447 Overriding) == SubobjectOverrides.end())
448 SubobjectOverrides.push_back(Overriding);
454 MEnd =
I->second.end();
464 I->second.push_back(Overriding);
470 class FinalOverriderCollector {
473 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
476 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
481 ~FinalOverriderCollector();
489 void FinalOverriderCollector::Collect(
const CXXRecordDecl *RD,
493 unsigned SubobjectNumber = 0;
500 const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
504 if (Overriders.empty() && !
Base.isVirtual()) {
507 Collect(BaseDecl,
false, InVirtualSubobject, Overriders);
518 if (
Base.isVirtual()) {
520 BaseOverriders = MyVirtualOverriders;
521 if (!MyVirtualOverriders) {
527 BaseOverriders = MyVirtualOverriders;
529 Collect(BaseDecl,
true, BaseDecl, *MyVirtualOverriders);
532 Collect(BaseDecl,
false, InVirtualSubobject, ComputedBaseOverriders);
537 OMEnd = BaseOverriders->end();
541 = cast<CXXMethodDecl>(OM->first->getCanonicalDecl());
542 Overriders[CanonOM].add(OM->second);
547 for (
auto *M : RD->
methods()) {
552 CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl());
562 Overriders[CanonM].add(SubobjectNumber,
564 InVirtualSubobject));
574 typedef llvm::iterator_range<CXXMethodDecl::method_iterator>
579 while (!Stack.empty()) {
592 Overriders[CanonOM].replaceAll(
594 InVirtualSubobject));
609 Overriders[CanonM].add(SubobjectNumber,
611 InVirtualSubobject));
615 FinalOverriderCollector::~FinalOverriderCollector() {
617 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
625 FinalOverriderCollector Collector;
626 Collector.Collect(
this,
false,
nullptr, FinalOverriders);
631 for (
auto &OM : FinalOverriders) {
632 for (
auto &SO : OM.second) {
634 if (Overriding.size() < 2)
638 if (!M.InVirtualSubobject)
648 OP.Method->getParent()->isVirtuallyDerivedFrom(
649 M.InVirtualSubobject))
655 std::remove_if(Overriding.begin(), Overriding.end(), IsHidden),
669 for (
const auto &
I : RD->
bases()) {
670 assert(!
I.getType()->isDependentType() &&
671 "Cannot get indirect primary bases for class with dependent bases.");
674 cast<CXXRecordDecl>(
I.getType()->castAs<
RecordType>()->getDecl());
678 if (BaseDecl->getNumVBases())
691 for (
const auto &
I :
bases()) {
692 assert(!
I.getType()->isDependentType() &&
693 "Cannot get indirect primary bases for class with dependent bases.");
696 cast<CXXRecordDecl>(
I.getType()->castAs<
RecordType>()->getDecl());
700 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)
A (possibly-)qualified type.
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 forallBases(ForallBasesCallback BaseMatches, bool AllowShortCircuit=true) const
Determines if the given callback holds for all the direct or indirect base classes of this type...
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not...
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
static bool FindOMPReductionMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name)
Base-class lookup callback that determines whether there exists an OpenMP declare reduction member wi...
RecordDecl - Represents a struct/union/class.
bool isFindingAmbiguities() const
Whether we are finding multiple paths to detect ambiguities.
method_iterator end_overridden_methods() const
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
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
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
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...
CXXRecordDecl * getCanonicalDecl() override
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
detail::InMemoryDirectory::const_iterator I
bool isDetectingVirtual() const
Whether we are detecting virtual bases.
std::vector< bool > & Stack
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
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, DeclarationName Name)
Base-class lookup callback that determines whether there exists a member with the given name that can...
llvm::function_ref< bool(const CXXRecordDecl *BaseDefinition)> ForallBasesCallback
Function type used by forallBases() as a callback.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name)
Base-class lookup callback that determines whether there exists a member with the given name...
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
getDefinition - Returns the RecordDecl that actually defines this struct/union/class.
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
const TemplateArgument * 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.
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...
Represents a static or instance method of a struct/union/class.
const T * castAs() const
Member-template castAs<specific type>.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
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.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
static void AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, CXXIndirectPrimaryBaseSet &Bases)
DeclarationName - The name of a declaration.
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
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 AccessSpecifier MergeAccess(AccessSpecifier PathAccess, AccessSpecifier DeclAccess)
Calculates the access of a decl that is reached along a path.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
const T * getAs() const
Member-template getAs<specific type>'.
llvm::iterator_range< decl_iterator > decl_range
static bool FindTagMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name)
Base-class lookup callback that determines whether there exists a tag with the given name...
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.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC...
bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is provably not derived from the type Base.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
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
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
const CXXRecordDecl * Class
The record decl of the class that the base is a base of.
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...
std::list< CXXBasePath >::iterator paths_iterator