Ignore qualified templated functions for -Winfinite-recursion. This treats

functions like Foo<5>::run() the same way as run<5>() for this warning.

llvm-svn: 198470
This commit is contained in:
Richard Trieu 2014-01-04 01:57:42 +00:00
parent 83f1149b30
commit 658eb68e82
2 changed files with 35 additions and 0 deletions

View File

@ -116,6 +116,18 @@ static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
const CallExpr *CE = dyn_cast<CallExpr>(I->getAs<CFGStmt>()->getStmt());
if (CE && CE->getCalleeDecl() &&
CE->getCalleeDecl()->getCanonicalDecl() == FD) {
// Skip function calls which are qualified with a templated class.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
CE->getCallee()->IgnoreParenImpCasts())) {
if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
isa<TemplateSpecializationType>(NNS->getAsType())) {
continue;
}
}
}
if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) {
if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
!MCE->getMethodDecl()->isVirtual()) {

View File

@ -127,3 +127,26 @@ int DoStuff() {
return 0;
}
int stuff = DoStuff<0, 1>();
template<int x>
struct Wrapper {
static int run() {
// Similar to the above, Wrapper<0>::run() will discard the if statement.
if (x == 1)
return 0;
return Wrapper<x/2>::run();
}
static int run2() { // expected-warning{{call itself}}
return run2();
}
};
template <int x>
int test_wrapper() {
if (x != 0)
return Wrapper<x>::run() +
Wrapper<x>::run2(); // expected-note{{instantiation}}
return 0;
}
int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}}