[AST] Turn the callbacks of lookupInBases and forallBases into a function_ref
This lets us pass functors (and lambdas) without void * tricks. On the
downside we can't pass CXXRecordDecl's Find* members (which are now type
safe) to lookupInBases directly, but a lambda trampoline is a small
price to pay. No functionality change intended.
llvm-svn: 243217
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 50890fb..3bd4a23 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6268,77 +6268,75 @@
return true;
}
-/// \brief Data used with FindHiddenVirtualMethod
namespace {
- struct FindHiddenVirtualMethodData {
- Sema *S;
- CXXMethodDecl *Method;
- llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
- SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
- };
-}
+struct FindHiddenVirtualMethod {
+ 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;
-}
-
-/// \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,
@@ -6361,9 +6359,9 @@
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.
@@ -6374,11 +6372,11 @@
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,
@@ -8468,40 +8466,26 @@
// 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(),