Teach the allocation function overload handling to deal with templates, and

prevent a crash on templates when looking for an existing declaration of the
predefined global operators. This fixes PR5918.

Added an easy test case for the overload handling, but testing the crash is
a bit trickier. Created a new test that can use multiple runs with a define to
trigger which test case is used so we can test this type of issue.

llvm-svn: 95220
This commit is contained in:
Chandler Carruth 2010-02-03 11:02:14 +00:00
parent 7ceffab64d
commit 935384217d
3 changed files with 46 additions and 12 deletions

View File

@ -630,14 +630,19 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
Alloc != AllocEnd; ++Alloc) { Alloc != AllocEnd; ++Alloc) {
// Even member operator new/delete are implicitly treated as // Even member operator new/delete are implicitly treated as
// static, so don't use AddMemberCandidate. // static, so don't use AddMemberCandidate.
if (FunctionDecl *Fn =
dyn_cast<FunctionDecl>((*Alloc)->getUnderlyingDecl())) { if (FunctionTemplateDecl *FnTemplate =
AddOverloadCandidate(Fn, Alloc.getAccess(), Args, NumArgs, Candidates, dyn_cast<FunctionTemplateDecl>((*Alloc)->getUnderlyingDecl())) {
/*SuppressUserConversions=*/false); AddTemplateOverloadCandidate(FnTemplate, Alloc.getAccess(),
/*ExplicitTemplateArgs=*/0, Args, NumArgs,
Candidates,
/*SuppressUserConversions=*/false);
continue; continue;
} }
// FIXME: Handle function templates FunctionDecl *Fn = cast<FunctionDecl>((*Alloc)->getUnderlyingDecl());
AddOverloadCandidate(Fn, Alloc.getAccess(), Args, NumArgs, Candidates,
/*SuppressUserConversions=*/false);
} }
// Do the resolution. // Do the resolution.
@ -768,12 +773,16 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
DeclContext::lookup_iterator Alloc, AllocEnd; DeclContext::lookup_iterator Alloc, AllocEnd;
for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name); for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name);
Alloc != AllocEnd; ++Alloc) { Alloc != AllocEnd; ++Alloc) {
// FIXME: Do we need to check for default arguments here? // Only look at non-template functions, as it is the predefined,
FunctionDecl *Func = cast<FunctionDecl>(*Alloc); // non-templated allocation function we are trying to declare here.
if (Func->getNumParams() == 1 && if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
QualType InitialParamType =
Context.getCanonicalType( Context.getCanonicalType(
Func->getParamDecl(0)->getType().getUnqualifiedType()) == Argument) Func->getParamDecl(0)->getType().getUnqualifiedType());
return; // FIXME: Do we need to check for default arguments here?
if (Func->getNumParams() == 1 && InitialParamType == Argument)
return;
}
} }
} }

View File

@ -0,0 +1,18 @@
// RUN: %clang_cc1 -DTEMPLATE_OVERLOAD -fsyntax-only -verify %s
#include <stddef.h>
// Note that each test must be run separately so it can be the first operator
// new declaration in the file.
#if defined(TEMPLATE_OVERLOAD)
// Don't crash on global template operator new overloads.
template<typename T> void* operator new(size_t, T);
void test_template_overload() {
(void)new(0) double;
}
#endif
void test_predefined() {
(void)new double;
}

View File

@ -216,3 +216,10 @@ static void* f(void* g)
{ {
return new (g) X13(); return new (g) X13();
} }
namespace PR5918 { // Look for template operator new overloads.
struct S { template<typename T> static void* operator new(size_t, T); };
void test() {
(void)new(0) S;
}
}