void ComputeDeclsFound();
- bool lookupInBases(ASTContext &Context,
- const CXXRecordDecl *Record,
- CXXRecordDecl::BaseMatchesCallback *BaseMatches,
- void *UserData);
+ bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record,
+ CXXRecordDecl::BaseMatchesCallback BaseMatches);
+
public:
typedef std::list<CXXBasePath>::iterator paths_iterator;
typedef std::list<CXXBasePath>::const_iterator const_paths_iterator;
/// \param BaseDefinition the definition of the base class
///
/// \returns true if this base matched the search criteria
- typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition,
- void *UserData);
+ typedef llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>
+ ForallBasesCallback;
/// \brief Determines if the given callback holds for all the direct
/// or indirect base classes of this type.
/// class of this type, or if \p AllowShortCircuit is true then until a call
/// returns false.
///
- /// \param UserData Passed as the second argument of every call to
- /// \p BaseMatches.
- ///
/// \param AllowShortCircuit if false, forces the callback to be called
/// for every base class, even if a dependent or non-matching base was
/// found.
- bool forallBases(ForallBasesCallback *BaseMatches, void *UserData,
+ bool forallBases(ForallBasesCallback BaseMatches,
bool AllowShortCircuit = true) const;
/// \brief Function type used by lookupInBases() to determine whether a
/// \param Path the current path, from the most-derived class down to the
/// base named by the \p Specifier.
///
- /// \param UserData a single pointer to user-specified data, provided to
- /// lookupInBases().
- ///
/// \returns true if this base matched the search criteria, false otherwise.
- typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *UserData);
+ typedef llvm::function_ref<bool(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path)> BaseMatchesCallback;
/// \brief Look for entities within the base classes of this C++ class,
/// transitively searching all base class subobjects.
/// \param BaseMatches callback function used to determine whether a given
/// base matches the user-defined search criteria.
///
- /// \param UserData user data pointer that will be provided to \p BaseMatches.
- ///
/// \param Paths used to record the paths from this class to its base class
/// subobjects that match the search criteria.
///
/// \returns true if there exists any path from this class to a base class
/// subobject that matches the search criteria.
- bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData,
+ bool lookupInBases(BaseMatchesCallback BaseMatches,
CXXBasePaths &Paths) const;
/// \brief Base-class lookup callback that determines whether the given
///
/// This callback can be used with \c lookupInBases() to determine whether
/// a given derived class has is a base class subobject of a particular type.
- /// The user data pointer should refer to the canonical CXXRecordDecl of the
+ /// The base record pointer should refer to the canonical CXXRecordDecl of the
/// base class that we are searching for.
static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *BaseRecord);
+ CXXBasePath &Path, const CXXRecordDecl *BaseRecord);
/// \brief Base-class lookup callback that determines whether the
/// given base class specifier refers to a specific class
///
/// This callback can be used with \c lookupInBases() to determine
/// whether a given derived class has is a virtual base class
- /// subobject of a particular type. The user data pointer should
+ /// subobject of a particular type. The base record pointer should
/// refer to the canonical CXXRecordDecl of the base class that we
/// are searching for.
static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *BaseRecord);
+ CXXBasePath &Path,
+ const CXXRecordDecl *BaseRecord);
/// \brief Base-class lookup callback that determines whether there exists
/// a tag with the given name.
///
/// This callback can be used with \c lookupInBases() to find tag members
- /// of the given name within a C++ class hierarchy. The user data pointer
- /// is an opaque \c DeclarationName pointer.
+ /// of the given name within a C++ class hierarchy.
static bool FindTagMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *Name);
+ CXXBasePath &Path, DeclarationName Name);
/// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name.
///
/// This callback can be used with \c lookupInBases() to find members
- /// of the given name within a C++ class hierarchy. The user data pointer
- /// is an opaque \c DeclarationName pointer.
+ /// of the given name within a C++ class hierarchy.
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *Name);
+ CXXBasePath &Path, DeclarationName Name);
/// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name that can be used in a nested-name-specifier.
///
- /// This callback can be used with \c lookupInBases() to find membes of
+ /// This callback can be used with \c lookupInBases() to find members of
/// the given name within a C++ class hierarchy that can occur within
/// nested-name-specifiers.
static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *UserData);
+ DeclarationName Name);
/// \brief Retrieve the final overriders for each virtual member
/// function in the class hierarchy where this class is the
return false;
Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
- return lookupInBases(&FindBaseClass,
- const_cast<CXXRecordDecl*>(Base->getCanonicalDecl()),
- Paths);
+
+ const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
+ return lookupInBases(
+ [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ return FindBaseClass(Specifier, Path, BaseDecl);
+ },
+ Paths);
}
bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const {
Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
- const void *BasePtr = static_cast<const void*>(Base->getCanonicalDecl());
- return lookupInBases(&FindVirtualBaseClass,
- const_cast<void *>(BasePtr),
- Paths);
-}
-
-static bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) {
- // OpaqueTarget is a CXXRecordDecl*.
- return Base->getCanonicalDecl() != (const CXXRecordDecl*) OpaqueTarget;
+ const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
+ return lookupInBases(
+ [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ return FindVirtualBaseClass(Specifier, Path, BaseDecl);
+ },
+ Paths);
}
bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const {
- return forallBases(BaseIsNot,
- const_cast<CXXRecordDecl *>(Base->getCanonicalDecl()));
+ const CXXRecordDecl *TargetDecl = Base->getCanonicalDecl();
+ return forallBases([TargetDecl](const CXXRecordDecl *Base) {
+ return Base->getCanonicalDecl() != TargetDecl;
+ });
}
bool
return false;
}
-bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
- void *OpaqueData,
+bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
bool AllowShortCircuit) const {
SmallVector<const CXXRecordDecl*, 8> Queue;
}
Queue.push_back(Base);
- if (!BaseMatches(Base, OpaqueData)) {
+ if (!BaseMatches(Base)) {
if (AllowShortCircuit) return false;
AllMatches = false;
continue;
return AllMatches;
}
-bool CXXBasePaths::lookupInBases(ASTContext &Context,
- const CXXRecordDecl *Record,
- CXXRecordDecl::BaseMatchesCallback *BaseMatches,
- void *UserData) {
+bool CXXBasePaths::lookupInBases(
+ ASTContext &Context, const CXXRecordDecl *Record,
+ CXXRecordDecl::BaseMatchesCallback BaseMatches) {
bool FoundPath = false;
// The access of the path down to this record.
// Track whether there's a path involving this specific base.
bool FoundPathThroughBase = false;
- if (BaseMatches(&BaseSpec, ScratchPath, UserData)) {
+ if (BaseMatches(&BaseSpec, ScratchPath)) {
// We've found a path that terminates at this base.
FoundPath = FoundPathThroughBase = true;
if (isRecordingPaths()) {
CXXRecordDecl *BaseRecord
= cast<CXXRecordDecl>(BaseSpec.getType()->castAs<RecordType>()
->getDecl());
- if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) {
+ if (lookupInBases(Context, BaseRecord, BaseMatches)) {
// C++ [class.member.lookup]p2:
// A member name f in one sub-object B hides a member name f in
// a sub-object A if A is a base class sub-object of B. Any
return FoundPath;
}
-bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
- void *UserData,
+bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches,
CXXBasePaths &Paths) const {
// If we didn't find anything, report that.
- if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, UserData))
+ if (!Paths.lookupInBases(getASTContext(), this, BaseMatches))
return false;
// If we're not recording paths or we won't ever find ambiguities,
bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *BaseRecord) {
+ const CXXRecordDecl *BaseRecord) {
assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord &&
"User data for FindBaseClass is not canonical!");
return Specifier->getType()->castAs<RecordType>()->getDecl()
bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *BaseRecord) {
+ const CXXRecordDecl *BaseRecord) {
assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord &&
"User data for FindBaseClass is not canonical!");
return Specifier->isVirtual() &&
bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *Name) {
+ DeclarationName Name) {
RecordDecl *BaseRecord =
Specifier->getType()->castAs<RecordType>()->getDecl();
- DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
- for (Path.Decls = BaseRecord->lookup(N);
+ for (Path.Decls = BaseRecord->lookup(Name);
!Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
if (Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag))
bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *Name) {
+ DeclarationName Name) {
RecordDecl *BaseRecord =
Specifier->getType()->castAs<RecordType>()->getDecl();
const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member;
- DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
- for (Path.Decls = BaseRecord->lookup(N);
+ for (Path.Decls = BaseRecord->lookup(Name);
!Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
if (Path.Decls.front()->isInIdentifierNamespace(IDNS))
bool CXXRecordDecl::
FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *Name) {
+ DeclarationName Name) {
RecordDecl *BaseRecord =
Specifier->getType()->castAs<RecordType>()->getDecl();
- DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
- for (Path.Decls = BaseRecord->lookup(N);
+ for (Path.Decls = BaseRecord->lookup(Name);
!Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
// FIXME: Refactor the "is it a nested-name-specifier?" check
}
}
-/// Callback function for CXXRecordDecl::forallBases that acknowledges
-/// that it saw a base class.
-static bool SawBase(const CXXRecordDecl *, void *) {
- return true;
-}
-
bool CXXRecordDecl::hasAnyDependentBases() const {
if (!isDependentContext())
return false;
- return !forallBases(SawBase, nullptr);
+ return !forallBases([](const CXXRecordDecl *) { return true; });
}
bool CXXRecordDecl::isTriviallyCopyable() const {
} // end namespace
-static bool BaseInSet(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *BasesSet) {
- BasesSetVectorTy *Bases = (BasesSetVectorTy *)BasesSet;
- return Bases->count(Specifier->getType()->getAsCXXRecordDecl());
-}
-
// Let's study one class hierarchy as an example:
// struct A {
// virtual void f();
return Overrider.Offset;
CXXBasePaths Paths;
- Overrider.Method->getParent()->lookupInBases(BaseInSet, &Collector.Bases,
- Paths);
+ Overrider.Method->getParent()->lookupInBases(
+ [&Collector](const CXXBaseSpecifier *Specifier, CXXBasePath &) {
+ return Collector.Bases.count(
+ Specifier->getType()->getAsCXXRecordDecl());
+ },
+ Paths);
// This will hold the smallest this offset among overridees of MD.
// This implies that an offset of a non-virtual base will dominate an offset
return false;
}
-/// \brief Data used with FindOverriddenMethod
-struct FindOverriddenMethodData {
+namespace {
+struct FindOverriddenMethod {
Sema *S;
CXXMethodDecl *Method;
-};
-/// \brief Member lookup function that determines whether a given C++
-/// method overrides a method in a base class, to be used with
-/// CXXRecordDecl::lookupInBases().
-static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *UserData) {
- RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+ /// Member lookup function that determines whether a given C++
+ /// method overrides a method in a base class, to be used with
+ /// CXXRecordDecl::lookupInBases().
+ bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ RecordDecl *BaseRecord =
+ Specifier->getType()->getAs<RecordType>()->getDecl();
- FindOverriddenMethodData *Data
- = reinterpret_cast<FindOverriddenMethodData*>(UserData);
-
- DeclarationName Name = Data->Method->getDeclName();
-
- // FIXME: Do we care about other names here too?
- if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
- // We really want to find the base class destructor here.
- QualType T = Data->S->Context.getTypeDeclType(BaseRecord);
- CanQualType CT = Data->S->Context.getCanonicalType(T);
-
- Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT);
- }
-
- for (Path.Decls = BaseRecord->lookup(Name);
- !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false))
- return true;
+ DeclarationName Name = Method->getDeclName();
+
+ // FIXME: Do we care about other names here too?
+ if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+ // We really want to find the base class destructor here.
+ QualType T = S->Context.getTypeDeclType(BaseRecord);
+ CanQualType CT = S->Context.getCanonicalType(T);
+
+ Name = S->Context.DeclarationNames.getCXXDestructorName(CT);
+ }
+
+ for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
+ Path.Decls = Path.Decls.slice(1)) {
+ NamedDecl *D = Path.Decls.front();
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (MD->isVirtual() && !S->IsOverload(Method, MD, false))
+ return true;
+ }
}
+
+ return false;
}
-
- return false;
-}
+};
+
+enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
+} // end anonymous namespace
-namespace {
- enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
-}
/// \brief Report an error regarding overriding, along with any relevant
/// overriden methods.
///
bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
// Look for methods in base classes that this method might override.
CXXBasePaths Paths;
- FindOverriddenMethodData Data;
- Data.Method = MD;
- Data.S = this;
+ FindOverriddenMethod FOM;
+ FOM.Method = MD;
+ FOM.S = this;
bool hasDeletedOverridenMethods = false;
bool hasNonDeletedOverridenMethods = false;
bool AddedAny = false;
- if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
+ if (DC->lookupInBases(FOM, Paths)) {
for (auto *I : Paths.found_decls()) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
// Else check if any base classes have a capability.
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
CXXBasePaths BPaths(false, false);
- if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &P,
- void *) {
- return BS->getType()->getAs<RecordType>()
- ->getDecl()->hasAttr<CapabilityAttr>();
- }, nullptr, BPaths))
+ if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &) {
+ const auto *Type = BS->getType()->getAs<RecordType>();
+ return Type->getDecl()->hasAttr<CapabilityAttr>();
+ }, BPaths))
return true;
}
return false;
return true;
}
-/// \brief Data used with FindHiddenVirtualMethod
namespace {
- struct FindHiddenVirtualMethodData {
- Sema *S;
- CXXMethodDecl *Method;
- llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
- SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
- };
-}
-
-/// \brief Check whether any most overriden method from MD in Methods
-static bool CheckMostOverridenMethods(const CXXMethodDecl *MD,
- const llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
- if (MD->size_overridden_methods() == 0)
- return Methods.count(MD->getCanonicalDecl());
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods();
- I != E; ++I)
- if (CheckMostOverridenMethods(*I, Methods))
- return true;
- return false;
-}
+struct FindHiddenVirtualMethod {
+ Sema *S;
+ CXXMethodDecl *Method;
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
+ SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
-/// \brief Member lookup function that determines whether a given C++
-/// method overloads virtual methods in a base class without overriding any,
-/// to be used with CXXRecordDecl::lookupInBases().
-static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *UserData) {
- RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
-
- FindHiddenVirtualMethodData &Data
- = *static_cast<FindHiddenVirtualMethodData*>(UserData);
-
- DeclarationName Name = Data.Method->getDeclName();
- assert(Name.getNameKind() == DeclarationName::Identifier);
-
- bool foundSameNameMethod = false;
- SmallVector<CXXMethodDecl *, 8> overloadedMethods;
- for (Path.Decls = BaseRecord->lookup(Name);
- !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- MD = MD->getCanonicalDecl();
- foundSameNameMethod = true;
- // Interested only in hidden virtual methods.
- if (!MD->isVirtual())
- continue;
- // If the method we are checking overrides a method from its base
- // don't warn about the other overloaded methods. Clang deviates from GCC
- // by only diagnosing overloads of inherited virtual functions that do not
- // override any other virtual functions in the base. GCC's
- // -Woverloaded-virtual diagnoses any derived function hiding a virtual
- // function from a base class. These cases may be better served by a
- // warning (not specific to virtual functions) on call sites when the call
- // would select a different function from the base class, were it visible.
- // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example.
- if (!Data.S->IsOverload(Data.Method, MD, false))
+private:
+ /// Check whether any most overriden method from MD in Methods
+ static bool CheckMostOverridenMethods(
+ const CXXMethodDecl *MD,
+ const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) {
+ if (MD->size_overridden_methods() == 0)
+ return Methods.count(MD->getCanonicalDecl());
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods();
+ I != E; ++I)
+ if (CheckMostOverridenMethods(*I, Methods))
return true;
- // Collect the overload only if its hidden.
- if (!CheckMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods))
- overloadedMethods.push_back(MD);
- }
+ return false;
}
- if (foundSameNameMethod)
- Data.OverloadedMethods.append(overloadedMethods.begin(),
- overloadedMethods.end());
- return foundSameNameMethod;
-}
+public:
+ /// Member lookup function that determines whether a given C++
+ /// method overloads virtual methods in a base class without overriding any,
+ /// to be used with CXXRecordDecl::lookupInBases().
+ bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ RecordDecl *BaseRecord =
+ Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ DeclarationName Name = Method->getDeclName();
+ assert(Name.getNameKind() == DeclarationName::Identifier);
+
+ bool foundSameNameMethod = false;
+ SmallVector<CXXMethodDecl *, 8> overloadedMethods;
+ for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
+ Path.Decls = Path.Decls.slice(1)) {
+ NamedDecl *D = Path.Decls.front();
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ MD = MD->getCanonicalDecl();
+ foundSameNameMethod = true;
+ // Interested only in hidden virtual methods.
+ if (!MD->isVirtual())
+ continue;
+ // If the method we are checking overrides a method from its base
+ // don't warn about the other overloaded methods. Clang deviates from
+ // GCC by only diagnosing overloads of inherited virtual functions that
+ // do not override any other virtual functions in the base. GCC's
+ // -Woverloaded-virtual diagnoses any derived function hiding a virtual
+ // function from a base class. These cases may be better served by a
+ // warning (not specific to virtual functions) on call sites when the
+ // call would select a different function from the base class, were it
+ // visible.
+ // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example.
+ if (!S->IsOverload(Method, MD, false))
+ return true;
+ // Collect the overload only if its hidden.
+ if (!CheckMostOverridenMethods(MD, OverridenAndUsingBaseMethods))
+ overloadedMethods.push_back(MD);
+ }
+ }
+
+ if (foundSameNameMethod)
+ OverloadedMethods.append(overloadedMethods.begin(),
+ overloadedMethods.end());
+ return foundSameNameMethod;
+ }
+};
+} // end anonymous namespace
/// \brief Add the most overriden methods from MD to Methods
static void AddMostOverridenMethods(const CXXMethodDecl *MD,
CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases.
/*bool RecordPaths=*/false,
/*bool DetectVirtual=*/false);
- FindHiddenVirtualMethodData Data;
- Data.Method = MD;
- Data.S = this;
+ FindHiddenVirtualMethod FHVM;
+ FHVM.Method = MD;
+ FHVM.S = this;
// Keep the base methods that were overriden or introduced in the subclass
// by 'using' in a set. A base method not in this set is hidden.
if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I))
ND = shad->getTargetDecl();
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
- AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods);
+ AddMostOverridenMethods(MD, FHVM.OverridenAndUsingBaseMethods);
}
- if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths))
- OverloadedMethods = Data.OverloadedMethods;
+ if (DC->lookupInBases(FHVM, Paths))
+ OverloadedMethods = FHVM.OverloadedMethods;
}
void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
// in the UsingDecl and UsingShadowDecl so that these checks didn't
// need to be repeated.
- struct UserData {
- llvm::SmallPtrSet<const CXXRecordDecl*, 4> Bases;
-
- static bool collect(const CXXRecordDecl *Base, void *OpaqueData) {
- UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
- Data->Bases.insert(Base);
- return true;
- }
-
- bool hasDependentBases(const CXXRecordDecl *Class) {
- return !Class->forallBases(collect, this);
- }
-
- /// Returns true if the base is dependent or is one of the
- /// accumulated base classes.
- static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) {
- UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
- return !Data->Bases.count(Base);
- }
-
- bool mightShareBases(const CXXRecordDecl *Class) {
- return Bases.count(Class) || !Class->forallBases(doesNotContain, this);
- }
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> Bases;
+ auto Collect = [&Bases](const CXXRecordDecl *Base) {
+ Bases.insert(Base);
+ return true;
};
- UserData Data;
-
- // Returns false if we find a dependent base.
- if (Data.hasDependentBases(cast<CXXRecordDecl>(CurContext)))
+ // Collect all bases. Return false if we find a dependent base.
+ if (!cast<CXXRecordDecl>(CurContext)->forallBases(Collect))
return false;
- // Returns false if the class has a dependent base or if it or one
+ // Returns true if the base is dependent or is one of the accumulated base
+ // classes.
+ auto IsNotBase = [&Bases](const CXXRecordDecl *Base) {
+ return !Bases.count(Base);
+ };
+
+ // Return false if the class has a dependent base or if it or one
// of its bases is present in the base set of the current context.
- if (Data.mightShareBases(cast<CXXRecordDecl>(NamedContext)))
+ if (Bases.count(cast<CXXRecordDecl>(NamedContext)) ||
+ !cast<CXXRecordDecl>(NamedContext)->forallBases(IsNotBase))
return false;
Diag(SS.getRange().getBegin(),
using namespace sema;
typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet;
-static bool BaseIsNotInSet(const CXXRecordDecl *Base, void *BasesPtr) {
- const BaseSet &Bases = *reinterpret_cast<const BaseSet*>(BasesPtr);
- return !Bases.count(Base->getCanonicalDecl());
-}
/// Determines if the given class is provably not derived from all of
/// the prospective base classes.
static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record,
const BaseSet &Bases) {
- void *BasesPtr = const_cast<void*>(reinterpret_cast<const void*>(&Bases));
- return BaseIsNotInSet(Record, BasesPtr) &&
- Record->forallBases(BaseIsNotInSet, BasesPtr);
+ auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) {
+ return !Bases.count(Base->getCanonicalDecl());
+ };
+ return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet);
}
enum IMAKind {
/// \brief Callback that looks for any member of a class with the given name.
static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *Name) {
+ CXXBasePath &Path, DeclarationName Name) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
- DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
- Path.Decls = BaseRecord->lookup(N);
+ Path.Decls = BaseRecord->lookup(Name);
return !Path.Decls.empty();
}
Paths.setOrigin(LookupRec);
// Look for this member in our base classes
- CXXRecordDecl::BaseMatchesCallback *BaseCallback = nullptr;
+ bool (*BaseCallback)(const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
+ DeclarationName Name) = nullptr;
switch (R.getLookupKind()) {
case LookupObjCImplicitSelfParam:
case LookupOrdinaryName:
break;
}
- if (!LookupRec->lookupInBases(BaseCallback,
- R.getLookupName().getAsOpaquePtr(), Paths))
+ DeclarationName Name = R.getLookupName();
+ if (!LookupRec->lookupInBases(
+ [=](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ return BaseCallback(Specifier, Path, Name);
+ },
+ Paths))
return false;
R.setNamingClass(LookupRec);
CXXCatchStmt *getFoundHandler() const { return FoundHandler; }
CanQualType getFoundHandlerType() const { return FoundHandlerType; }
- static bool FindPublicBasesOfType(const CXXBaseSpecifier *S, CXXBasePath &,
- void *User) {
- auto &PBOT = *reinterpret_cast<CatchTypePublicBases *>(User);
+ bool operator()(const CXXBaseSpecifier *S, CXXBasePath &) {
if (S->getAccessSpecifier() == AccessSpecifier::AS_public) {
- CatchHandlerType Check(S->getType(), PBOT.CheckAgainstPointer);
- auto M = PBOT.TypesToCheck;
+ CatchHandlerType Check(S->getType(), CheckAgainstPointer);
+ auto M = TypesToCheck;
auto I = M.find(Check);
if (I != M.end()) {
- PBOT.FoundHandler = I->second;
- PBOT.FoundHandlerType = PBOT.Ctx.getCanonicalType(S->getType());
+ FoundHandler = I->second;
+ FoundHandlerType = Ctx.getCanonicalType(S->getType());
return true;
}
}
CXXBasePaths Paths;
Paths.setOrigin(RD);
CatchTypePublicBases CTPB(Context, HandledTypes, HandlerCHT.isPointer());
- if (RD->lookupInBases(CatchTypePublicBases::FindPublicBasesOfType, &CTPB,
- Paths)) {
+ if (RD->lookupInBases(CTPB, Paths)) {
const CXXCatchStmt *Problem = CTPB.getFoundHandler();
if (!Paths.isAmbiguous(CTPB.getFoundHandlerType())) {
Diag(H->getExceptionDecl()->getTypeSpecStartLoc(),
return true;
CXXBasePaths Paths(false, false, false);
- if (RD->lookupInBases(&CXXRecordDecl::FindOrdinaryMember,
- DeclName.getAsOpaquePtr(),
- Paths))
+ if (RD->lookupInBases(
+ [DeclName](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ return CXXRecordDecl::FindOrdinaryMember(Specifier, Path, DeclName);
+ },
+ Paths))
return true;
return false;