diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-11 00:44:29 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-11 00:44:29 +0000 |
commit | a9faa44162a5ccc922113e2efc8dc2ae86021835 (patch) | |
tree | 7db1a9001b1212dd0665b921345571c0ad18c147 /clang/lib/Sema/SemaTemplate.cpp | |
parent | 081e354f11aecedf97d4841070f1411b7fc8e45f (diff) | |
download | bcm5719-llvm-a9faa44162a5ccc922113e2efc8dc2ae86021835.tar.gz bcm5719-llvm-a9faa44162a5ccc922113e2efc8dc2ae86021835.zip |
Semantic checking for template arguments that correspond to non-type
template parameters that have reference type. Effectively, we're doing
a very limited form of reference binding here.
llvm-svn: 64270
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c78d8876dae..d4ba0c5edba 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -897,10 +897,10 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } 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. 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); @@ -960,6 +960,43 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, 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; + } + + // 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; |