Improve diagnostics and template instantiation behavior when calling

an overloaded function call operator.

llvm-svn: 84745
This commit is contained in:
Douglas Gregor 2009-10-21 06:18:39 +00:00
parent 05f77d5006
commit 74ba25ca5a
4 changed files with 37 additions and 26 deletions

View File

@ -44,7 +44,7 @@ namespace clang {
DIAG_START_PARSE = DIAG_START_LEX + 300,
DIAG_START_AST = DIAG_START_PARSE + 300,
DIAG_START_SEMA = DIAG_START_AST + 100,
DIAG_START_ANALYSIS = DIAG_START_SEMA + 1000,
DIAG_START_ANALYSIS = DIAG_START_SEMA + 1100,
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
};

View File

@ -1746,7 +1746,9 @@ def err_not_tag_in_scope : Error<
def err_cannot_form_pointer_to_member_of_reference_type : Error<
"cannot form a pointer-to-member to member %0 of reference type %1">;
def err_incomplete_object_call : Error<
"incomplete type in call to object of type %0">;
def warn_condition_is_assignment : Warning<"using the result of an "
"assignment as a condition without parentheses">,
InGroup<Parentheses>;

View File

@ -5086,6 +5086,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs,
CandidateSet, /*SuppressUserConversions=*/false);
if (RequireCompleteType(LParenLoc, Object->getType(),
PartialDiagnostic(diag::err_incomplete_object_call)
<< Object->getSourceRange()))
return true;
// C++ [over.call.object]p2:
// In addition, for each conversion function declared in T of the
// form
@ -5103,33 +5108,30 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// functions for each conversion function declared in an
// accessible base class provided the function is not hidden
// within T by another intervening declaration.
// FIXME: Look in base classes for more conversion operators!
OverloadedFunctionDecl *Conversions
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
for (OverloadedFunctionDecl::function_iterator
Func = Conversions->function_begin(),
FuncEnd = Conversions->function_end();
Func != FuncEnd; ++Func) {
CXXConversionDecl *Conv;
FunctionTemplateDecl *ConvTemplate;
GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
if (!RequireCompleteType(SourceLocation(), Object->getType(), 0)) {
// FIXME: Look in base classes for more conversion operators!
OverloadedFunctionDecl *Conversions
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
for (OverloadedFunctionDecl::function_iterator
Func = Conversions->function_begin(),
FuncEnd = Conversions->function_end();
Func != FuncEnd; ++Func) {
CXXConversionDecl *Conv;
FunctionTemplateDecl *ConvTemplate;
GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
// Skip over templated conversion functions; they aren't
// surrogates.
if (ConvTemplate)
continue;
// Skip over templated conversion functions; they aren't
// surrogates.
if (ConvTemplate)
continue;
// Strip the reference type (if any) and then the pointer type (if
// any) to get down to what might be a function type.
QualType ConvType = Conv->getConversionType().getNonReferenceType();
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
ConvType = ConvPtrType->getPointeeType();
// Strip the reference type (if any) and then the pointer type (if
// any) to get down to what might be a function type.
QualType ConvType = Conv->getConversionType().getNonReferenceType();
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
ConvType = ConvPtrType->getPointeeType();
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
}
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
}
// Perform overload resolution.

View File

@ -40,3 +40,10 @@ void g() {
(b.*mfp)(); // expected-error {{calling function with incomplete return type 'struct A'}}
}
struct C; // expected-note{{forward declaration}}
void test_incomplete_object_call(C& c) {
c(); // expected-error{{incomplete type in call to object of type}}
}