[cfe-commits] r64270 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/SemaTemplate.cpp test/SemaTemplate/temp_arg_nontype.cpp

Douglas Gregor dgregor at apple.com
Tue Feb 10 16:44:30 PST 2009


Author: dgregor
Date: Tue Feb 10 18:44:29 2009
New Revision: 64270

URL: http://llvm.org/viewvc/llvm-project?rev=64270&view=rev
Log:
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.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=64270&r1=64269&r2=64270&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Tue Feb 10 18:44:29 2009
@@ -531,6 +531,11 @@
      "non-type template argument of type %0 is not an integral constant expression")
 DIAG(err_template_arg_not_convertible, ERROR,
      "non-type template argument of type %0 cannot be converted to a value of type %1")
+DIAG(err_template_arg_no_ref_bind, ERROR,
+     "non-type template parameter of reference type %0 cannot bind to template argument of type %1") 
+DIAG(err_template_arg_ref_bind_ignores_quals, ERROR,
+     "reference binding of non-type template parameter of type %0 to template argument of type %1 ignores qualifiers")
+
 
 DIAG(err_unexpected_typedef, ERROR,
      "unexpected type name %0: expected expression")

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=64270&r1=64269&r2=64270&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Feb 10 18:44:29 2009
@@ -897,10 +897,10 @@
   }
 
   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 @@
     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;

Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp?rev=64270&r1=64269&r2=64270&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Tue Feb 10 18:44:29 2009
@@ -67,3 +67,15 @@
 // FIXME: expected-error{{expected unqualified-id}}
 // FIXME: the first error includes the string <overloaded function
 // type>, which makes Doug slightly unhappy.
+
+
+struct Y { } y;
+
+volatile X * X_volatile_ptr;
+template<X const &AnX> struct A4; // expected-note 2{{template parameter is declared here}}
+A4<*X_ptr> *a15_1; // okay
+A4<*X_volatile_ptr> *a15_2; // expected-error{{reference binding of non-type template parameter of type 'class X const &' to template argument of type 'class X volatile' ignores qualifiers}} \
+                  // FIXME: expected-error{{expected unqualified-id}}
+A4<y> *15_3; //  expected-error{{non-type template parameter of reference type 'class X const &' cannot bind to template argument of type 'struct Y'}}\
+                  // FIXME: expected-error{{expected unqualified-id}}
+





More information about the cfe-commits mailing list