Rename Sema::IsOverload to Sema::CheckOverload. Teach it to ignore unresolved

using value decls;  we optimistically assume they won't turn into conflicts.
Teach it to tell the caller *why* the function doesn't overload with the returned
decl;  this will be useful for using hiding.

llvm-svn: 90939
This commit is contained in:
John McCall 2009-12-09 03:35:25 +00:00
parent 31c7e88667
commit daa3d6bb50
3 changed files with 67 additions and 41 deletions

View File

@ -832,8 +832,22 @@ public:
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
/// C++ Overloading.
bool IsOverload(FunctionDecl *New, LookupResult &OldDecls,
NamedDecl *&OldDecl);
enum OverloadKind {
/// This is a legitimate overload: the existing declarations are
/// functions or function templates with different signatures.
Ovl_Overload,
/// This is not an overload because the signature exactly matches
/// an existing declaration.
Ovl_Match,
/// This is not an overload because the lookup results contain a
/// non-function.
Ovl_NonFunction
};
OverloadKind CheckOverload(FunctionDecl *New,
LookupResult &OldDecls,
NamedDecl *&OldDecl);
bool IsOverload(FunctionDecl *New, FunctionDecl *Old);
ImplicitConversionSequence

View File

@ -3165,34 +3165,44 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD,
// there's no more work to do here; we'll just add the new
// function to the scope.
if (!getLangOptions().CPlusPlus &&
AllowOverloadingOfFunction(Previous, Context)) {
OverloadableAttrRequired = true;
// Functions marked "overloadable" must have a prototype (that
// we can't get through declaration merging).
if (!NewFD->getType()->getAs<FunctionProtoType>()) {
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_no_prototype)
<< NewFD;
Redeclaration = true;
// Turn this into a variadic function with no parameters.
QualType R = Context.getFunctionType(
NewFD->getType()->getAs<FunctionType>()->getResultType(),
0, 0, true, 0);
NewFD->setType(R);
return NewFD->setInvalidDecl();
}
}
NamedDecl *OldDecl = 0;
if (!Previous.empty()) {
if (!AllowOverloadingOfFunction(Previous, Context)) {
Redeclaration = true;
OldDecl = Previous.getFoundDecl();
} else if (!IsOverload(NewFD, Previous, OldDecl)) {
if (!isUsingDecl(OldDecl))
if (!AllowOverloadingOfFunction(Previous, Context)) {
Redeclaration = true;
OldDecl = Previous.getFoundDecl();
} else {
if (!getLangOptions().CPlusPlus) {
OverloadableAttrRequired = true;
// Functions marked "overloadable" must have a prototype (that
// we can't get through declaration merging).
if (!NewFD->getType()->getAs<FunctionProtoType>()) {
Diag(NewFD->getLocation(),
diag::err_attribute_overloadable_no_prototype)
<< NewFD;
Redeclaration = true;
// Turn this into a variadic function with no parameters.
QualType R = Context.getFunctionType(
NewFD->getType()->getAs<FunctionType>()->getResultType(),
0, 0, true, 0);
NewFD->setType(R);
return NewFD->setInvalidDecl();
}
}
switch (CheckOverload(NewFD, Previous, OldDecl)) {
case Ovl_Match:
// FIXME: hide or conflict with using shadow decls as appropriate
Redeclaration = !isa<UsingShadowDecl>(OldDecl);
break;
case Ovl_NonFunction:
Redeclaration = true;
break;
case Ovl_Overload:
Redeclaration = false;
break;
}
}

View File

@ -262,9 +262,9 @@ void ImplicitConversionSequence::DebugPrint() const {
// New and Old cannot be overloaded, e.g., if New has the same
// signature as some function in Old (C++ 1.3.10) or if the Old
// declarations aren't functions (or function templates) at all. When
// it does return false and Old is an overload set, MatchedDecl will
// be set to point to the FunctionDecl that New cannot be overloaded
// with.
// it does return false, MatchedDecl will point to the decl that New
// cannot be overloaded with. This decl may be a UsingShadowDecl on
// top of the underlying declaration.
//
// Example: Given the following input:
//
@ -286,31 +286,33 @@ void ImplicitConversionSequence::DebugPrint() const {
// identical (return types of functions are not part of the
// signature), IsOverload returns false and MatchedDecl will be set to
// point to the FunctionDecl for #2.
bool
Sema::IsOverload(FunctionDecl *New, LookupResult &Old, NamedDecl *&Match) {
Sema::OverloadKind
Sema::CheckOverload(FunctionDecl *New, LookupResult &Old, NamedDecl *&Match) {
for (LookupResult::iterator I = Old.begin(), E = Old.end();
I != E; ++I) {
NamedDecl *OldD = (*I)->getUnderlyingDecl();
if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
if (!IsOverload(New, OldT->getTemplatedDecl())) {
Match = OldT;
return false;
Match = *I;
return Ovl_Match;
}
} else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) {
if (!IsOverload(New, OldF)) {
Match = OldF;
return false;
Match = *I;
return Ovl_Match;
}
} else {
} else if (!isa<UnresolvedUsingValueDecl>(OldD)) {
// (C++ 13p1):
// Only function declarations can be overloaded; object and type
// declarations cannot be overloaded.
Match = OldD;
return false;
// But we permit unresolved using value decls and diagnose the error
// during template instantiation.
Match = *I;
return Ovl_NonFunction;
}
}
return true;
return Ovl_Overload;
}
bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) {