зеркало из https://github.com/microsoft/clang.git
Implement the simple form of overload resolution used when taking the
address of an overloaded function (which may involve both functions and function templates). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75069 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
599788806a
Коммит
00aeb52314
|
@ -666,6 +666,10 @@ def err_ovl_surrogate_cand : Note<"conversion candidate of type %0">;
|
||||||
def err_member_call_without_object : Error<
|
def err_member_call_without_object : Error<
|
||||||
"call to non-static member function without an object argument">;
|
"call to non-static member function without an object argument">;
|
||||||
|
|
||||||
|
// C++ Address of Overloaded Function
|
||||||
|
def err_addr_ovl_ambiguous : Error<
|
||||||
|
"address of overloaded function %0 is ambiguous">;
|
||||||
|
|
||||||
// C++ Template Declarations
|
// C++ Template Declarations
|
||||||
def err_template_param_shadow : Error<
|
def err_template_param_shadow : Error<
|
||||||
"declaration of %0 shadows template parameter">;
|
"declaration of %0 shadows template parameter">;
|
||||||
|
|
|
@ -3742,7 +3742,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
||||||
|
|
||||||
// Look through all of the overloaded functions, searching for one
|
// Look through all of the overloaded functions, searching for one
|
||||||
// whose type matches exactly.
|
// whose type matches exactly.
|
||||||
// FIXME: We still need to cope with duplicates, partial ordering, etc.
|
llvm::SmallPtrSet<FunctionDecl *, 4> Matches;
|
||||||
|
|
||||||
|
bool FoundNonTemplateFunction = false;
|
||||||
for (OverloadIterator FunEnd; Fun != FunEnd; ++Fun) {
|
for (OverloadIterator FunEnd; Fun != FunEnd; ++Fun) {
|
||||||
// C++ [over.over]p3:
|
// C++ [over.over]p3:
|
||||||
// Non-member functions and static member functions match
|
// Non-member functions and static member functions match
|
||||||
|
@ -3753,12 +3755,21 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
||||||
|
|
||||||
if (FunctionTemplateDecl *FunctionTemplate
|
if (FunctionTemplateDecl *FunctionTemplate
|
||||||
= dyn_cast<FunctionTemplateDecl>(*Fun)) {
|
= dyn_cast<FunctionTemplateDecl>(*Fun)) {
|
||||||
// C++ [temp.deduct.funcaddr]p1:
|
if (CXXMethodDecl *Method
|
||||||
// Template arguments can be deduced from the type specified when
|
= dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
|
||||||
// taking the address of an overloaded function (13.4). The function
|
// Skip non-static function templates when converting to pointer, and
|
||||||
// template’s function type and the specified type are used as the
|
// static when converting to member pointer.
|
||||||
// types of P and A, and the deduction is done as described in
|
if (Method->isStatic() == IsMember)
|
||||||
// 14.8.2.4.
|
continue;
|
||||||
|
} else if (IsMember)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// C++ [over.over]p2:
|
||||||
|
// If the name is a function template, template argument deduction is
|
||||||
|
// done (14.8.2.2), and if the argument deduction succeeds, the
|
||||||
|
// resulting template argument list is used to generate a single
|
||||||
|
// function template specialization, which is added to the set of
|
||||||
|
// overloaded functions considered.
|
||||||
FunctionDecl *Specialization = 0;
|
FunctionDecl *Specialization = 0;
|
||||||
TemplateDeductionInfo Info(Context);
|
TemplateDeductionInfo Info(Context);
|
||||||
if (TemplateDeductionResult Result
|
if (TemplateDeductionResult Result
|
||||||
|
@ -3770,7 +3781,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
||||||
} else {
|
} else {
|
||||||
assert(FunctionType
|
assert(FunctionType
|
||||||
== Context.getCanonicalType(Specialization->getType()));
|
== Context.getCanonicalType(Specialization->getType()));
|
||||||
return Specialization;
|
Matches.insert(
|
||||||
|
cast<FunctionDecl>(Context.getCanonicalDecl(Specialization)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3779,15 +3791,54 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
||||||
// when converting to member pointer.
|
// when converting to member pointer.
|
||||||
if (Method->isStatic() == IsMember)
|
if (Method->isStatic() == IsMember)
|
||||||
continue;
|
continue;
|
||||||
} else if (IsMember) // FIXME: member templates
|
} else if (IsMember)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Fun)) {
|
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Fun)) {
|
||||||
if (FunctionType == Context.getCanonicalType(FunDecl->getType()))
|
if (FunctionType == Context.getCanonicalType(FunDecl->getType())) {
|
||||||
return FunDecl;
|
Matches.insert(cast<FunctionDecl>(Context.getCanonicalDecl(*Fun)));
|
||||||
|
FoundNonTemplateFunction = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there were 0 or 1 matches, we're done.
|
||||||
|
if (Matches.empty())
|
||||||
|
return 0;
|
||||||
|
else if (Matches.size() == 1)
|
||||||
|
return *Matches.begin();
|
||||||
|
|
||||||
|
// C++ [over.over]p4:
|
||||||
|
// If more than one function is selected, [...]
|
||||||
|
llvm::SmallVector<FunctionDecl *, 4> RemainingMatches;
|
||||||
|
if (FoundNonTemplateFunction) {
|
||||||
|
// [...] any function template specializations in the set are eliminated
|
||||||
|
// if the set also contains a non-template function, [...]
|
||||||
|
for (llvm::SmallPtrSet<FunctionDecl *, 4>::iterator M = Matches.begin(),
|
||||||
|
MEnd = Matches.end();
|
||||||
|
M != MEnd; ++M)
|
||||||
|
if ((*M)->getPrimaryTemplate() == 0)
|
||||||
|
RemainingMatches.push_back(*M);
|
||||||
|
} else {
|
||||||
|
// [...] and any given function template specialization F1 is eliminated
|
||||||
|
// if the set contains a second function template specialization whose
|
||||||
|
// function template is more specialized than the function template of F1
|
||||||
|
// according to the partial ordering rules of 14.5.5.2.
|
||||||
|
// FIXME: Implement this!
|
||||||
|
RemainingMatches.append(Matches.begin(), Matches.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// [...] After such eliminations, if any, there shall remain exactly one
|
||||||
|
// selected function.
|
||||||
|
if (RemainingMatches.size() == 1)
|
||||||
|
return RemainingMatches.front();
|
||||||
|
|
||||||
|
// FIXME: We should probably return the same thing that BestViableFunction
|
||||||
|
// returns (even if we issue the diagnostics here).
|
||||||
|
Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
|
||||||
|
<< RemainingMatches[0]->getDeclName();
|
||||||
|
for (unsigned I = 0, N = RemainingMatches.size(); I != N; ++I)
|
||||||
|
Diag(RemainingMatches[I]->getLocation(), diag::err_ovl_candidate);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// RUN: clang-cc -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
template<typename T> T f0(T);
|
||||||
|
int f0(int); // expected-note{{candidate function}}
|
||||||
|
|
||||||
|
void test_f0() {
|
||||||
|
int (*fp0)(int) = f0;
|
||||||
|
int (*fp1)(int) = &f0;
|
||||||
|
float (*fp2)(float) = &f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace N {
|
||||||
|
int f0(int); // expected-note{{candidate function}}
|
||||||
|
}
|
||||||
|
|
||||||
|
int f0(int);
|
||||||
|
|
||||||
|
void test_f0_2() {
|
||||||
|
using namespace N;
|
||||||
|
int (*fp0)(int) = f0; // expected-error{{ambiguous}} \
|
||||||
|
// expected-error{{initializing}}
|
||||||
|
float (*fp1)(float) = f0;
|
||||||
|
}
|
|
@ -1689,12 +1689,10 @@ welcome!</p>
|
||||||
<tr>
|
<tr>
|
||||||
<td> 13.4 [over.over]</td>
|
<td> 13.4 [over.over]</td>
|
||||||
<td class="na" align="center">N/A</td>
|
<td class="na" align="center">N/A</td>
|
||||||
<td class="medium" align="center"></td>
|
<td class="advanced" align="center"></td>
|
||||||
<td class="basic" align="center"></td>
|
<td class="advanced" align="center"></td>
|
||||||
<td class="na" align="center">N/A</td>
|
<td class="na" align="center">N/A</td>
|
||||||
<td>Error messages need some work. Without templates or using
|
<td>No partial ordering of function templates.</td>
|
||||||
declarations, we don't have any ambiguities, so the semantic
|
|
||||||
analysis is incomplete.</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td> 13.5 [over.oper]</td>
|
<td> 13.5 [over.oper]</td>
|
||||||
|
@ -2102,10 +2100,10 @@ welcome!</p>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td> 14.8.2.2 [temp.deduct.funcaddr]</td>
|
<td> 14.8.2.2 [temp.deduct.funcaddr]</td>
|
||||||
<td class="broken" align="center"></td>
|
<td class="na" align="center">N/A</td>
|
||||||
<td class="broken" align="center"></td>
|
<td class="advanced" align="center"></td>
|
||||||
<td class="broken" align="center"></td>
|
<td class="advanced" align="center"></td>
|
||||||
<td class="broken" align="center"></td>
|
<td class="na" align="center">N/A</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче