24 #include "llvm/ADT/DenseMap.h" 25 #include "llvm/ADT/STLExtras.h" 26 #include "llvm/ADT/SetVector.h" 27 #include "llvm/ADT/SmallVector.h" 28 #include "llvm/ADT/iterator_range.h" 29 #include "llvm/Support/Casting.h" 35 using namespace clang;
39 void CXXBasePaths::ComputeDeclsFound() {
40 assert(NumDeclsFound == 0 && !DeclsFound &&
41 "Already computed the set of declarations");
43 llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8>> Decls;
45 Decls.insert(Path->Decls.front());
47 NumDeclsFound = Decls.size();
48 DeclsFound = llvm::make_unique<NamedDecl *[]>(NumDeclsFound);
49 std::copy(Decls.begin(), Decls.end(), DeclsFound.get());
53 if (NumDeclsFound == 0)
66 std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
67 return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
73 ClassSubobjects.clear();
74 VisitedDependentRecords.clear();
76 DetectedVirtual =
nullptr;
82 std::swap(Origin, Other.Origin);
83 Paths.swap(Other.Paths);
84 ClassSubobjects.swap(Other.ClassSubobjects);
85 VisitedDependentRecords.swap(Other.VisitedDependentRecords);
86 std::swap(FindAmbiguities, Other.FindAmbiguities);
87 std::swap(RecordPaths, Other.RecordPaths);
88 std::swap(DetectVirtual, Other.DetectVirtual);
89 std::swap(DetectedVirtual, Other.DetectedVirtual);
95 return isDerivedFrom(Base, Paths);
103 Paths.
setOrigin(const_cast<CXXRecordDecl*>(
this));
107 return lookupInBases(
109 return FindBaseClass(Specifier, Path, BaseDecl);
124 Paths.
setOrigin(const_cast<CXXRecordDecl*>(
this));
128 return lookupInBases(
130 return FindVirtualBaseClass(Specifier, Path, BaseDecl);
144 assert(isDependentContext());
147 if (CurContext->
Equals(
this))
154 bool AllowShortCircuit)
const {
158 bool AllMatches =
true;
160 for (
const auto &I : Record->
bases()) {
163 if (AllowShortCircuit)
return false;
173 if (AllowShortCircuit)
return false;
178 Queue.push_back(Base);
179 if (!BaseMatches(Base)) {
180 if (AllowShortCircuit)
return false;
188 Record = Queue.pop_back_val();
194 bool CXXBasePaths::lookupInBases(
ASTContext &Context,
197 bool LookupInDependent) {
202 bool IsFirstStep = ScratchPath.empty();
204 for (
const auto &BaseSpec : Record->
bases()) {
220 std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
221 bool VisitBase =
true;
222 bool SetVirtual =
false;
223 if (BaseSpec.isVirtual()) {
224 VisitBase = !Subobjects.first;
225 Subobjects.first =
true;
238 Element.
Base = &BaseSpec;
239 Element.
Class = Record;
240 if (BaseSpec.isVirtual())
244 ScratchPath.push_back(Element);
262 ScratchPath.
Access = BaseSpec.getAccessSpecifier();
265 BaseSpec.getAccessSpecifier());
269 bool FoundPathThroughBase =
false;
271 if (BaseMatches(&BaseSpec, ScratchPath)) {
273 FoundPath = FoundPathThroughBase =
true;
276 Paths.push_back(ScratchPath);
282 }
else if (VisitBase) {
284 if (LookupInDependent) {
285 BaseRecord =
nullptr;
289 if (
auto *RT = BaseSpec.getType()->getAs<
RecordType>())
290 BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
295 BaseRecord = TD->getTemplatedDecl();
299 VisitedDependentRecords.count(BaseRecord)) {
300 BaseRecord =
nullptr;
302 VisitedDependentRecords.insert(BaseRecord);
306 BaseRecord = cast<CXXRecordDecl>(
307 BaseSpec.getType()->castAs<
RecordType>()->getDecl());
310 lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
319 FoundPath = FoundPathThroughBase =
true;
328 ScratchPath.pop_back();
332 if (SetVirtual && !FoundPathThroughBase) {
333 DetectedVirtual =
nullptr;
338 ScratchPath.
Access = AccessToHere;
345 bool LookupInDependent)
const {
347 if (!Paths.lookupInBases(getASTContext(),
this, BaseMatches,
366 Paths.Paths.remove_if([&Paths](
const CXXBasePath &Path) {
368 if (!PE.Base->isVirtual())
373 VBase = cast<CXXRecordDecl>(Record->getDecl());
384 HidingP.back().Base->getType()->getAs<
RecordType>())
385 HidingClass = cast<CXXRecordDecl>(Record->getDecl());
403 "User data for FindBaseClass is not canonical!");
405 ->getCanonicalDecl() == BaseRecord;
412 "User data for FindBaseClass is not canonical!");
415 ->getCanonicalDecl() == BaseRecord;
427 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS_Tag))
441 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS))
468 const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
485 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS_OMPReduction))
503 if (isa<TypedefNameDecl>(Path.
Decls.
front()) ||
504 Path.
Decls.
front()->isInIdentifierNamespace(IDNS_Tag))
513 llvm::function_ref<
bool(
const NamedDecl *ND)> Filter) {
514 std::vector<const NamedDecl *> Results;
517 if (!DirectResult.
empty()) {
518 for (
const NamedDecl *ND : DirectResult) {
520 Results.push_back(ND);
530 Specifier, Path, Name);
536 Results.push_back(ND);
544 = Overrides[OverriddenSubobject];
545 if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(),
546 Overriding) == SubobjectOverrides.end())
547 SubobjectOverrides.push_back(Overriding);
553 MEnd = I->second.end();
563 I->second.push_back(Overriding);
569 class FinalOverriderCollector {
572 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
575 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
580 ~FinalOverriderCollector();
589 void FinalOverriderCollector::Collect(
const CXXRecordDecl *RD,
593 unsigned SubobjectNumber = 0;
600 const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
604 if (Overriders.empty() && !
Base.isVirtual()) {
607 Collect(BaseDecl,
false, InVirtualSubobject, Overriders);
618 if (
Base.isVirtual()) {
620 BaseOverriders = MyVirtualOverriders;
621 if (!MyVirtualOverriders) {
627 BaseOverriders = MyVirtualOverriders;
629 Collect(BaseDecl,
true, BaseDecl, *MyVirtualOverriders);
632 Collect(BaseDecl,
false, InVirtualSubobject, ComputedBaseOverriders);
636 for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
637 OMEnd = BaseOverriders->end();
641 = cast<CXXMethodDecl>(OM->first->getCanonicalDecl());
642 Overriders[CanonOM].add(OM->second);
647 for (
auto *M : RD->
methods()) {
652 CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl());
653 using OverriddenMethodsRange =
654 llvm::iterator_range<CXXMethodDecl::method_iterator>;
657 if (OverriddenMethods.begin() == OverriddenMethods.end()) {
664 Overriders[CanonM].add(SubobjectNumber,
666 InVirtualSubobject));
677 while (!Stack.empty()) {
690 Overriders[CanonOM].replaceAll(
692 InVirtualSubobject));
695 if (OverriddenMethods.begin() == OverriddenMethods.end())
700 Stack.push_back(OverriddenMethods);
706 Overriders[CanonM].add(SubobjectNumber,
708 InVirtualSubobject));
712 FinalOverriderCollector::~FinalOverriderCollector() {
713 for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
714 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
722 FinalOverriderCollector Collector;
723 Collector.Collect(
this,
false,
nullptr, FinalOverriders);
728 for (
auto &OM : FinalOverriders) {
729 for (
auto &SO : OM.second) {
731 if (Overriding.size() < 2)
735 if (!M.InVirtualSubobject)
745 OP.Method->getParent()->isVirtuallyDerivedFrom(
746 M.InVirtualSubobject))
752 std::remove_if(Overriding.begin(), Overriding.end(), IsHidden),
766 for (
const auto &I : RD->
bases()) {
767 assert(!I.getType()->isDependentType() &&
768 "Cannot get indirect primary bases for class with dependent bases.");
771 cast<CXXRecordDecl>(I.getType()->castAs<
RecordType>()->getDecl());
775 if (BaseDecl->getNumVBases())
788 for (
const auto &I : bases()) {
789 assert(!I.getType()->isDependentType() &&
790 "Cannot get indirect primary bases for class with dependent bases.");
793 cast<CXXRecordDecl>(I.getType()->castAs<
RecordType>()->getDecl());
797 if (BaseDecl->getNumVBases())
Defines the clang::ASTContext interface.
static const Decl * getCanonicalDecl(const Decl *D)
void setOrigin(CXXRecordDecl *Rec)
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not...
A (possibly-)qualified type.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
llvm::iterator_range< decl_iterator > decl_range
C Language Family Type Representation.
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
Defines the C++ template declaration subclasses.
void swap(CXXBasePaths &Other)
Swap this data structure's contents with another CXXBasePaths object.
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
SmallVectorImpl< UniqueVirtualMethod >::const_iterator overriding_const_iterator
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...
std::list< CXXBasePath >::iterator paths_iterator
DeclContext::lookup_result Decls
The set of declarations found inside this base class subobject.
const T * getAs() const
Member-template getAs<specific type>'.
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.
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...
bool hasDefinition() const
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.
bool isRecordingPaths() const
Whether we are recording paths.
RecordDecl - Represents a struct/union/class.
bool isFindingAmbiguities() const
Whether we are finding multiple paths to detect ambiguities.
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.
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known...
RecordDecl * getDefinition() const
getDefinition - Returns the RecordDecl that actually defines this struct/union/class.
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC...
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding)
NamedDecl ** decl_iterator
The set of methods that override a given virtual method in each subobject where it occurs...
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
DeclContextLookupResult slice(size_t N) const
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
static bool findOrdinaryMember(RecordDecl *BaseRecord, CXXBasePath &Path, DeclarationName Name)
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
int SubobjectNumber
Identifies which base class subobject (of type Base->getType()) this base path element refers to...
const T * castAs() const
Member-template castAs<specific type>.
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
overridden_method_range overridden_methods() const
bool isFileContext() const
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...
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
Represents a C++ template name within the type system.
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
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...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
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.
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...
RecordDecl * getDecl() const
const CXXBaseSpecifier * Base
The base specifier that states the link from a derived class to a base class, which will be followed ...
Members, declared with object declarations within tag definitions.
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.
llvm::function_ref< bool(const CXXRecordDecl *BaseDefinition)> ForallBasesCallback
Function type used by forallBases() as a callback.
bool isDetectingVirtual() const
Whether we are detecting virtual bases.
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...
Represents an element in a path from a derived class to a base class.
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is virtually derived from the class Base.
bool isCurrentInstantiation(const DeclContext *CurContext) const
Determine whether this dependent class is a current instantiation, when viewed from within the given ...
Dataflow Directional Tag Classes.
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)
MapType::iterator iterator
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...
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.
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...
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
MapType::const_iterator const_iterator
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.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
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 isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Represents a type template specialization; the template must be a class template, a type alias templa...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
void replaceAll(UniqueVirtualMethod Overriding)
NamedDecl - This represents a decl with a name.
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...
method_range methods() const
QualType getType() const
Retrieves the type of the base class.