forked from OSchip/llvm-project
Improve diagnostics and template instantiation behavior when calling
an overloaded function call operator. llvm-svn: 84745
This commit is contained in:
parent
05f77d5006
commit
74ba25ca5a
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue