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_PARSE = DIAG_START_LEX + 300,
|
||||||
DIAG_START_AST = DIAG_START_PARSE + 300,
|
DIAG_START_AST = DIAG_START_PARSE + 300,
|
||||||
DIAG_START_SEMA = DIAG_START_AST + 100,
|
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
|
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<
|
def err_cannot_form_pointer_to_member_of_reference_type : Error<
|
||||||
"cannot form a pointer-to-member to member %0 of reference type %1">;
|
"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 "
|
def warn_condition_is_assignment : Warning<"using the result of an "
|
||||||
"assignment as a condition without parentheses">,
|
"assignment as a condition without parentheses">,
|
||||||
InGroup<Parentheses>;
|
InGroup<Parentheses>;
|
||||||
|
|
|
@ -5086,6 +5086,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
|
||||||
AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs,
|
AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs,
|
||||||
CandidateSet, /*SuppressUserConversions=*/false);
|
CandidateSet, /*SuppressUserConversions=*/false);
|
||||||
|
|
||||||
|
if (RequireCompleteType(LParenLoc, Object->getType(),
|
||||||
|
PartialDiagnostic(diag::err_incomplete_object_call)
|
||||||
|
<< Object->getSourceRange()))
|
||||||
|
return true;
|
||||||
|
|
||||||
// C++ [over.call.object]p2:
|
// C++ [over.call.object]p2:
|
||||||
// In addition, for each conversion function declared in T of the
|
// In addition, for each conversion function declared in T of the
|
||||||
// form
|
// form
|
||||||
|
@ -5103,33 +5108,30 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
|
||||||
// functions for each conversion function declared in an
|
// functions for each conversion function declared in an
|
||||||
// accessible base class provided the function is not hidden
|
// accessible base class provided the function is not hidden
|
||||||
// within T by another intervening declaration.
|
// 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)) {
|
// Skip over templated conversion functions; they aren't
|
||||||
// FIXME: Look in base classes for more conversion operators!
|
// surrogates.
|
||||||
OverloadedFunctionDecl *Conversions
|
if (ConvTemplate)
|
||||||
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
|
continue;
|
||||||
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
|
// Strip the reference type (if any) and then the pointer type (if
|
||||||
// surrogates.
|
// any) to get down to what might be a function type.
|
||||||
if (ConvTemplate)
|
QualType ConvType = Conv->getConversionType().getNonReferenceType();
|
||||||
continue;
|
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
|
||||||
|
ConvType = ConvPtrType->getPointeeType();
|
||||||
|
|
||||||
// Strip the reference type (if any) and then the pointer type (if
|
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
|
||||||
// any) to get down to what might be a function type.
|
AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform overload resolution.
|
// Perform overload resolution.
|
||||||
|
|
|
@ -40,3 +40,10 @@ void g() {
|
||||||
(b.*mfp)(); // expected-error {{calling function with incomplete return type 'struct A'}}
|
(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