summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorDavid Blaikie <dblaikie@gmail.com>2012-10-19 00:53:08 +0000
committerDavid Blaikie <dblaikie@gmail.com>2012-10-19 00:53:08 +0000
commit282c92a7089f44429e878f880968c765e8e211cd (patch)
treed08ab8d03a23b34faad16b8324ede53144a7e013 /clang/lib/Sema/SemaDeclCXX.cpp
parentf20544aa5244084dd36bbbdf7ac02079cb9671a1 (diff)
downloadbcm5719-llvm-282c92a7089f44429e878f880968c765e8e211cd.tar.gz
bcm5719-llvm-282c92a7089f44429e878f880968c765e8e211cd.zip
Handle diamond inheritance in -Woverloaded-virtual.
llvm-svn: 166254
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp42
1 files changed, 29 insertions, 13 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 93b78c1316b..0adcfc15201 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4739,6 +4739,19 @@ namespace {
};
}
+/// \brief Check whether any most overriden method from MD in Methods
+static bool CheckMostOverridenMethods(const CXXMethodDecl *MD,
+ const llvm::SmallPtrSet<const CXXMethodDecl *, 8>& 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().
@@ -4770,12 +4783,7 @@ static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
if (!Data.S->IsOverload(Data.Method, MD, false))
return true;
// Collect the overload only if its hidden.
- bool Using = Data.OverridenAndUsingBaseMethods.count(MD);
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods();
- I != E && !Using; ++I)
- Using = Data.OverridenAndUsingBaseMethods.count(*I);
- if (!Using)
+ if (!CheckMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods))
overloadedMethods.push_back(MD);
}
}
@@ -4786,6 +4794,17 @@ static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
return foundSameNameMethod;
}
+/// \brief Add the most overriden methods from MD to Methods
+static void AddMostOverridenMethods(const CXXMethodDecl *MD,
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8>& Methods) {
+ if (MD->size_overridden_methods() == 0)
+ Methods.insert(MD->getCanonicalDecl());
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods();
+ I != E; ++I)
+ AddMostOverridenMethods(*I, Methods);
+}
+
/// \brief See if a method overloads virtual methods in a base class without
/// overriding any.
void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
@@ -4806,14 +4825,11 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
// by 'using' in a set. A base method not in this set is hidden.
for (DeclContext::lookup_result res = DC->lookup(MD->getDeclName());
res.first != res.second; ++res.first) {
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*res.first))
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods();
- I != E; ++I)
- Data.OverridenAndUsingBaseMethods.insert((*I)->getCanonicalDecl());
+ NamedDecl *ND = *res.first;
if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*res.first))
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(shad->getTargetDecl()))
- Data.OverridenAndUsingBaseMethods.insert(MD->getCanonicalDecl());
+ ND = shad->getTargetDecl();
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
+ AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods);
}
if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths) &&
OpenPOWER on IntegriCloud