18 #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();
60 VisitedDependentRecords.clear();
62 DetectedVirtual =
nullptr;
68 std::swap(Origin, Other.Origin);
69 Paths.swap(Other.Paths);
70 ClassSubobjects.swap(Other.ClassSubobjects);
71 VisitedDependentRecords.swap(Other.VisitedDependentRecords);
72 std::swap(FindAmbiguities, Other.FindAmbiguities);
73 std::swap(RecordPaths, Other.RecordPaths);
74 std::swap(DetectVirtual, Other.DetectVirtual);
75 std::swap(DetectedVirtual, Other.DetectedVirtual);
89 Paths.
setOrigin(const_cast<CXXRecordDecl*>(
this));
110 Paths.
setOrigin(const_cast<CXXRecordDecl*>(
this));
133 if (CurContext->
Equals(
this))
140 bool AllowShortCircuit)
const {
144 bool AllMatches =
true;
146 for (
const auto &
I : Record->
bases()) {
149 if (AllowShortCircuit)
return false;
159 if (AllowShortCircuit)
return false;
164 Queue.push_back(Base);
165 if (!BaseMatches(Base)) {
166 if (AllowShortCircuit)
return false;
174 Record = Queue.pop_back_val();
183 bool LookupInDependent) {
188 bool IsFirstStep = ScratchPath.empty();
190 for (
const auto &BaseSpec : Record->
bases()) {
206 std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
207 bool VisitBase =
true;
208 bool SetVirtual =
false;
209 if (BaseSpec.isVirtual()) {
210 VisitBase = !Subobjects.first;
211 Subobjects.first =
true;
224 Element.
Base = &BaseSpec;
225 Element.
Class = Record;
226 if (BaseSpec.isVirtual())
230 ScratchPath.push_back(Element);
248 ScratchPath.
Access = BaseSpec.getAccessSpecifier();
251 BaseSpec.getAccessSpecifier());
255 bool FoundPathThroughBase =
false;
257 if (BaseMatches(&BaseSpec, ScratchPath)) {
259 FoundPath = FoundPathThroughBase =
true;
262 Paths.push_back(ScratchPath);
268 }
else if (VisitBase) {
270 if (LookupInDependent) {
271 BaseRecord =
nullptr;
275 if (
auto *RT = BaseSpec.getType()->getAs<
RecordType>())
276 BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
281 BaseRecord = TD->getTemplatedDecl();
285 VisitedDependentRecords.count(BaseRecord)) {
286 BaseRecord =
nullptr;
288 VisitedDependentRecords.insert(BaseRecord);
292 BaseRecord = cast<CXXRecordDecl>(
293 BaseSpec.getType()->castAs<
RecordType>()->getDecl());
296 lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
305 FoundPath = FoundPathThroughBase =
true;
314 ScratchPath.pop_back();
318 if (SetVirtual && !FoundPathThroughBase) {
319 DetectedVirtual =
nullptr;
324 ScratchPath.
Access = AccessToHere;
331 bool LookupInDependent)
const {
352 Paths.Paths.remove_if([&Paths](
const CXXBasePath &Path) {
354 if (!PE.Base->isVirtual())
359 VBase = cast<CXXRecordDecl>(Record->getDecl());
370 HidingP.back().Base->getType()->getAs<
RecordType>())
371 HidingClass = cast<CXXRecordDecl>(Record->getDecl());
389 "User data for FindBaseClass is not canonical!");
391 ->getCanonicalDecl() == BaseRecord;
398 "User data for FindBaseClass is not canonical!");
401 ->getCanonicalDecl() == BaseRecord;
427 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS))
489 if (isa<TypedefNameDecl>(Path.
Decls.
front()) ||
499 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
500 std::vector<const NamedDecl *> Results;
503 if (!DirectResult.
empty()) {
504 for (
const NamedDecl *ND : DirectResult) {
506 Results.push_back(ND);
516 Specifier, Path, Name);
522 Results.push_back(ND);
530 = Overrides[OverriddenSubobject];
531 if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(),
532 Overriding) == SubobjectOverrides.end())
533 SubobjectOverrides.push_back(Overriding);
539 MEnd =
I->second.end();
549 I->second.push_back(Overriding);
555 class FinalOverriderCollector {
558 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
561 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
566 ~FinalOverriderCollector();
574 void FinalOverriderCollector::Collect(
const CXXRecordDecl *RD,
578 unsigned SubobjectNumber = 0;
585 const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
589 if (Overriders.empty() && !
Base.isVirtual()) {
592 Collect(BaseDecl,
false, InVirtualSubobject, Overriders);
603 if (
Base.isVirtual()) {
605 BaseOverriders = MyVirtualOverriders;
606 if (!MyVirtualOverriders) {
612 BaseOverriders = MyVirtualOverriders;
614 Collect(BaseDecl,
true, BaseDecl, *MyVirtualOverriders);
617 Collect(BaseDecl,
false, InVirtualSubobject, ComputedBaseOverriders);
621 for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
622 OMEnd = BaseOverriders->end();
626 = cast<CXXMethodDecl>(OM->first->getCanonicalDecl());
627 Overriders[CanonOM].add(OM->second);
632 for (
auto *M : RD->
methods()) {
637 CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl());
647 Overriders[CanonM].add(SubobjectNumber,
649 InVirtualSubobject));
659 typedef llvm::iterator_range<CXXMethodDecl::method_iterator>
664 while (!Stack.empty()) {
677 Overriders[CanonOM].replaceAll(
679 InVirtualSubobject));
694 Overriders[CanonM].add(SubobjectNumber,
696 InVirtualSubobject));
700 FinalOverriderCollector::~FinalOverriderCollector() {
701 for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
702 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
710 FinalOverriderCollector Collector;
711 Collector.Collect(
this,
false,
nullptr, FinalOverriders);
716 for (
auto &OM : FinalOverriders) {
717 for (
auto &SO : OM.second) {
719 if (Overriding.size() < 2)
723 if (!M.InVirtualSubobject)
733 OP.Method->getParent()->isVirtuallyDerivedFrom(
734 M.InVirtualSubobject))
740 std::remove_if(Overriding.begin(), Overriding.end(), IsHidden),
754 for (
const auto &
I : RD->
bases()) {
755 assert(!
I.getType()->isDependentType() &&
756 "Cannot get indirect primary bases for class with dependent bases.");
759 cast<CXXRecordDecl>(
I.getType()->castAs<
RecordType>()->getDecl());
763 if (BaseDecl->getNumVBases())
776 for (
const auto &
I :
bases()) {
777 assert(!
I.getType()->isDependentType() &&
778 "Cannot get indirect primary bases for class with dependent bases.");
781 cast<CXXRecordDecl>(
I.getType()->castAs<
RecordType>()->getDecl());
785 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.
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known...
Defines the C++ template declaration subclasses.
void swap(CXXBasePaths &Other)
Swap this data structure's contents with another CXXBasePaths object.
bool hasDefinition() const
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...
const NestedNameSpecifier * Specifier
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.
static bool FindOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name)
Base-class lookup callback that determines whether there exists a member with the given name...
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...
std::vector< const NamedDecl * > lookupDependentName(const DeclarationName &Name, llvm::function_ref< bool(const NamedDecl *ND)> Filter)
Performs an imprecise lookup of a dependent name in this class.
RecordDecl - Represents a struct/union/class.
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 ...
The results of name lookup within a DeclContext.
bool isRecordingPaths() const
Whether we are recording paths.
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
std::vector< const CXXMethodDecl * > OverriddenMethods
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...
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
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
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...
static bool findOrdinaryMember(RecordDecl *BaseRecord, CXXBasePath &Path, DeclarationName Name)
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...
This declaration is an OpenMP user defined reduction construction.
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.
Represents a C++ template name within the type system.
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
Members, declared with object declarations within tag definitions.
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.
ASTContext & getASTContext() const LLVM_READONLY
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)
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...
DeclarationName - The name of a declaration.
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 ...
Tags, declared with 'struct foo;' and referenced with 'struct foo'.
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...
Represents a type template specialization; the template must be a class template, a type alias templa...
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.
NamedDecl - This represents a decl with a name.
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