23 #include "llvm/ADT/DenseMap.h" 24 #include "llvm/ADT/STLExtras.h" 25 #include "llvm/ADT/SetVector.h" 26 #include "llvm/ADT/SmallVector.h" 27 #include "llvm/ADT/iterator_range.h" 28 #include "llvm/Support/Casting.h" 34 using namespace clang;
38 void CXXBasePaths::ComputeDeclsFound() {
39 assert(NumDeclsFound == 0 && !DeclsFound &&
40 "Already computed the set of declarations");
44 Decls.insert(Path->Decls.front());
46 NumDeclsFound = Decls.size();
47 DeclsFound = llvm::make_unique<NamedDecl *[]>(NumDeclsFound);
48 std::copy(Decls.begin(), Decls.end(), DeclsFound.get());
52 if (NumDeclsFound == 0)
65 IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[BaseType];
66 return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1;
72 ClassSubobjects.clear();
73 VisitedDependentRecords.clear();
75 DetectedVirtual =
nullptr;
81 std::swap(Origin, Other.Origin);
82 Paths.swap(Other.Paths);
83 ClassSubobjects.swap(Other.ClassSubobjects);
84 VisitedDependentRecords.swap(Other.VisitedDependentRecords);
85 std::swap(FindAmbiguities, Other.FindAmbiguities);
86 std::swap(RecordPaths, Other.RecordPaths);
87 std::swap(DetectVirtual, Other.DetectVirtual);
88 std::swap(DetectedVirtual, Other.DetectedVirtual);
94 return isDerivedFrom(Base, Paths);
102 Paths.
setOrigin(const_cast<CXXRecordDecl*>(
this));
105 return lookupInBases(
107 return FindBaseClass(Specifier, Path, BaseDecl);
122 Paths.
setOrigin(const_cast<CXXRecordDecl*>(
this));
125 return lookupInBases(
127 return FindVirtualBaseClass(Specifier, Path, BaseDecl);
141 assert(isDependentContext());
144 if (CurContext->
Equals(
this))
151 bool AllowShortCircuit)
const {
155 bool AllMatches =
true;
157 for (
const auto &I : Record->
bases()) {
160 if (AllowShortCircuit)
return false;
170 if (AllowShortCircuit)
return false;
175 Queue.push_back(Base);
176 if (!BaseMatches(Base)) {
177 if (AllowShortCircuit)
return false;
185 Record = Queue.pop_back_val();
191 bool CXXBasePaths::lookupInBases(
ASTContext &Context,
194 bool LookupInDependent) {
195 bool FoundPath =
false;
199 bool IsFirstStep = ScratchPath.empty();
201 for (
const auto &BaseSpec : Record->
bases()) {
217 IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType];
218 bool VisitBase =
true;
219 bool SetVirtual =
false;
220 if (BaseSpec.isVirtual()) {
221 VisitBase = !Subobjects.IsVirtBase;
222 Subobjects.IsVirtBase =
true;
230 ++Subobjects.NumberOfNonVirtBases;
235 Element.
Base = &BaseSpec;
236 Element.
Class = Record;
237 if (BaseSpec.isVirtual())
241 ScratchPath.push_back(Element);
259 ScratchPath.
Access = BaseSpec.getAccessSpecifier();
262 BaseSpec.getAccessSpecifier());
266 bool FoundPathThroughBase =
false;
268 if (BaseMatches(&BaseSpec, ScratchPath)) {
270 FoundPath = FoundPathThroughBase =
true;
273 Paths.push_back(ScratchPath);
279 }
else if (VisitBase) {
281 if (LookupInDependent) {
282 BaseRecord =
nullptr;
286 if (
auto *RT = BaseSpec.getType()->getAs<
RecordType>())
287 BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
292 BaseRecord = TD->getTemplatedDecl();
296 VisitedDependentRecords.count(BaseRecord)) {
297 BaseRecord =
nullptr;
299 VisitedDependentRecords.insert(BaseRecord);
303 BaseRecord = cast<CXXRecordDecl>(
304 BaseSpec.getType()->castAs<
RecordType>()->getDecl());
307 lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
316 FoundPath = FoundPathThroughBase =
true;
325 ScratchPath.pop_back();
329 if (SetVirtual && !FoundPathThroughBase) {
330 DetectedVirtual =
nullptr;
335 ScratchPath.
Access = AccessToHere;
342 bool LookupInDependent)
const {
344 if (!Paths.lookupInBases(getASTContext(),
this, BaseMatches,
363 Paths.Paths.remove_if([&Paths](
const CXXBasePath &Path) {
365 if (!PE.Base->isVirtual())
370 VBase = cast<CXXRecordDecl>(Record->getDecl());
381 HidingP.back().Base->getType()->getAs<
RecordType>())
382 HidingClass = cast<CXXRecordDecl>(Record->getDecl());
400 "User data for FindBaseClass is not canonical!");
402 ->getCanonicalDecl() == BaseRecord;
409 "User data for FindBaseClass is not canonical!");
412 ->getCanonicalDecl() == BaseRecord;
424 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS_Tag))
438 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS))
465 const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
482 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS_OMPReduction))
497 if (Path.
Decls.
front()->isInIdentifierNamespace(IDNS_OMPMapper))
515 if (isa<TypedefNameDecl>(Path.
Decls.
front()) ||
516 Path.
Decls.
front()->isInIdentifierNamespace(IDNS_Tag))
526 std::vector<const NamedDecl *> Results;
529 if (!DirectResult.
empty()) {
530 for (
const NamedDecl *ND : DirectResult) {
532 Results.push_back(ND);
542 Specifier, Path, Name);
548 Results.push_back(ND);
556 = Overrides[OverriddenSubobject];
557 if (llvm::find(SubobjectOverrides, Overriding) == SubobjectOverrides.end())
558 SubobjectOverrides.push_back(Overriding);
564 MEnd = I->second.end();
574 I->second.push_back(Overriding);
580 class FinalOverriderCollector {
583 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
586 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
591 ~FinalOverriderCollector();
600 void FinalOverriderCollector::Collect(
const CXXRecordDecl *RD,
604 unsigned SubobjectNumber = 0;
611 const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
615 if (Overriders.empty() && !
Base.isVirtual()) {
618 Collect(BaseDecl,
false, InVirtualSubobject, Overriders);
629 if (
Base.isVirtual()) {
631 BaseOverriders = MyVirtualOverriders;
632 if (!MyVirtualOverriders) {
638 BaseOverriders = MyVirtualOverriders;
640 Collect(BaseDecl,
true, BaseDecl, *MyVirtualOverriders);
643 Collect(BaseDecl,
false, InVirtualSubobject, ComputedBaseOverriders);
647 for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
648 OMEnd = BaseOverriders->end();
652 Overriders[CanonOM].add(OM->second);
657 for (
auto *M : RD->
methods()) {
663 using OverriddenMethodsRange =
664 llvm::iterator_range<CXXMethodDecl::method_iterator>;
667 if (OverriddenMethods.begin() == OverriddenMethods.end()) {
674 Overriders[CanonM].add(SubobjectNumber,
676 InVirtualSubobject));
687 while (!Stack.empty()) {
700 Overriders[CanonOM].replaceAll(
702 InVirtualSubobject));
705 if (OverriddenMethods.begin() == OverriddenMethods.end())
710 Stack.push_back(OverriddenMethods);
716 Overriders[CanonM].add(SubobjectNumber,
718 InVirtualSubobject));
722 FinalOverriderCollector::~FinalOverriderCollector() {
723 for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
724 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
732 FinalOverriderCollector Collector;
733 Collector.Collect(
this,
false,
nullptr, FinalOverriders);
738 for (
auto &OM : FinalOverriders) {
739 for (
auto &SO : OM.second) {
741 if (Overriding.size() < 2)
745 if (!M.InVirtualSubobject)
755 OP.Method->getParent()->isVirtuallyDerivedFrom(
756 M.InVirtualSubobject))
762 std::remove_if(Overriding.begin(), Overriding.end(), IsHidden),
776 for (
const auto &I : RD->
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())
798 for (
const auto &I : bases()) {
799 assert(!I.getType()->isDependentType() &&
800 "Cannot get indirect primary bases for class with dependent bases.");
803 cast<CXXRecordDecl>(I.getType()->castAs<
RecordType>()->getDecl());
807 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.
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
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.
static bool FindOMPMapperMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name)
Base-class lookup callback that determines whether there exists an OpenMP declare mapper member with ...
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
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)
This represents a decl that may have 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.