diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-11 01:18:59 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-11 01:18:59 +0000 |
commit | b86b0579c5805c8ecaedd2d676e06bf8c2bf7f79 (patch) | |
tree | cd2d3f24f128e332692ca70d293b918d5b20338e /lib/Sema/SemaTemplate.cpp | |
parent | 77a60115e3edc4db99666cb77fba073d03f71212 (diff) |
Add semantic checking for template arguments that correspond to
non-type template parameters that are references to functions or
pointers to member functions. Did a little bit of refactoring so that
these two cases, along with the handling of non-type template
parameters that are pointers to functions, are handled by the same
path.
Also, tweaked FixOverloadedFunctionReference to cope with member
function pointers. This is a necessary step for getting all of the fun
member pointer conversions working outside of template arguments, too.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64277 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 163 |
1 files changed, 90 insertions, 73 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d4ba0c5edb..eb7db25d6e 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -896,58 +896,45 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return false; } - if (const PointerType *ParamPtrType = ParamType->getAsPointerType()) { - if (ParamPtrType->getPointeeType()->isObjectType()) { - // -- for a non-type template-parameter of type pointer to - // object, qualification conversions (4.4) and the - // array-to-pointer conversion (4.2) are applied. - if (ArgType->isArrayType()) { - ArgType = Context.getArrayDecayedType(ArgType); - ImpCastExprToType(Arg, ArgType); - } - - if (IsQualificationConversion(ArgType, ParamType)) { - ArgType = ParamType; - ImpCastExprToType(Arg, ParamType); - } - - if (!hasSameUnqualifiedType(ArgType, ParamType)) { - // We can't perform this conversion. - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_convertible) - << Arg->getType() << Param->getType() << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } - - // FIXME: Check the restrictions in p1! - return false; - } - - assert(ParamPtrType->getPointeeType()->isFunctionType() && - "Only function pointers remain"); - // -- For a non-type template-parameter of type pointer to - // function, only the function-to-pointer conversion (4.3) is - // applied. If the template-argument represents a set of - // overloaded functions (or a pointer to such), the matching - // function is selected from the set (13.4). - if (hasSameUnqualifiedType(ArgType, ParamType)) { + // Handle pointer-to-function, reference-to-function, and + // pointer-to-member-function all in (roughly) the same way. + if (// -- For a non-type template-parameter of type pointer to + // function, only the function-to-pointer conversion (4.3) is + // applied. If the template-argument represents a set of + // overloaded functions (or a pointer to such), the matching + // function is selected from the set (13.4). + (ParamType->isPointerType() && + ParamType->getAsPointerType()->getPointeeType()->isFunctionType()) || + // -- For a non-type template-parameter of type reference to + // function, no conversions apply. If the template-argument + // represents a set of overloaded functions, the matching + // function is selected from the set (13.4). + (ParamType->isReferenceType() && + ParamType->getAsReferenceType()->getPointeeType()->isFunctionType()) || + // -- For a non-type template-parameter of type pointer to + // member function, no conversions apply. If the + // template-argument represents a set of overloaded member + // functions, the matching member function is selected from + // the set (13.4). + (ParamType->isMemberPointerType() && + ParamType->getAsMemberPointerType()->getPointeeType() + ->isFunctionType())) { + if (hasSameUnqualifiedType(ArgType, ParamType.getNonReferenceType())) { // We don't have to do anything: the types already match. - } - else if (ArgType->isFunctionType()) { + } else if (ArgType->isFunctionType() && ParamType->isPointerType()) { ArgType = Context.getPointerType(ArgType); ImpCastExprToType(Arg, ArgType); } else if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, true)) { FixOverloadedFunctionReference(Arg, Fn); ArgType = Arg->getType(); - if (ArgType->isFunctionType()) { + if (ArgType->isFunctionType() && ParamType->isPointerType()) { ArgType = Context.getPointerType(Arg->getType()); ImpCastExprToType(Arg, ArgType); } } - if (!hasSameUnqualifiedType(ArgType, ParamType)) { + if (!hasSameUnqualifiedType(ArgType, ParamType.getNonReferenceType())) { // We can't perform this conversion. Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) @@ -960,43 +947,73 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return false; } + if (const PointerType *ParamPtrType = ParamType->getAsPointerType()) { + // -- for a non-type template-parameter of type pointer to + // object, qualification conversions (4.4) and the + // array-to-pointer conversion (4.2) are applied. + assert(ParamPtrType->getPointeeType()->isObjectType() && + "Only object pointers allowed here"); + + if (ArgType->isArrayType()) { + ArgType = Context.getArrayDecayedType(ArgType); + ImpCastExprToType(Arg, ArgType); + } + + if (IsQualificationConversion(ArgType, ParamType)) { + ArgType = ParamType; + ImpCastExprToType(Arg, ParamType); + } + + if (!hasSameUnqualifiedType(ArgType, ParamType)) { + // We can't perform this conversion. + Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_convertible) + << Arg->getType() << Param->getType() << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + // FIXME: Check the restrictions in p1! + return false; + } + if (const ReferenceType *ParamRefType = ParamType->getAsReferenceType()) { - if (ParamRefType->getPointeeType()->isObjectType()) { - // -- For a non-type template-parameter of type reference to - // object, no conversions apply. The type referred to by the - // reference may be more cv-qualified than the (otherwise - // identical) type of the template-argument. The - // template-parameter is bound directly to the - // template-argument, which must be an lvalue. - if (!hasSameUnqualifiedType(ParamRefType->getPointeeType(), ArgType)) { - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_no_ref_bind) - << Param->getType() << Arg->getType() - << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } - - unsigned ParamQuals - = Context.getCanonicalType(ParamType).getCVRQualifiers(); - unsigned ArgQuals = Context.getCanonicalType(ArgType).getCVRQualifiers(); - - if ((ParamQuals | ArgQuals) != ParamQuals) { - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_ref_bind_ignores_quals) - << Param->getType() << Arg->getType() - << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } + // -- For a non-type template-parameter of type reference to + // object, no conversions apply. The type referred to by the + // reference may be more cv-qualified than the (otherwise + // identical) type of the template-argument. The + // template-parameter is bound directly to the + // template-argument, which must be an lvalue. + assert(ParamRefType->getPointeeType()->isObjectType() && + "Only object references allowed here"); + + if (!hasSameUnqualifiedType(ParamRefType->getPointeeType(), ArgType)) { + Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_no_ref_bind) + << Param->getType() << Arg->getType() + << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } - // FIXME: Check the restrictions in p1! - // CheckAddressConstantExpression(Lvalue) can be modified to do - // this. - return false; + unsigned ParamQuals + = Context.getCanonicalType(ParamType).getCVRQualifiers(); + unsigned ArgQuals = Context.getCanonicalType(ArgType).getCVRQualifiers(); + + if ((ParamQuals | ArgQuals) != ParamQuals) { + Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_ref_bind_ignores_quals) + << Param->getType() << Arg->getType() + << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + return true; } + + // FIXME: Check the restrictions in p1! + // CheckAddressConstantExpression(Lvalue) can be modified to do + // this. + return false; } - // FIXME: p5 has a lot more checks to perform! return false; |