]> granicus.if.org Git - clang/commitdiff
When substituting a declaration non-type template argument for a
authorDouglas Gregor <dgregor@apple.com>
Mon, 8 Feb 2010 23:41:45 +0000 (23:41 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 8 Feb 2010 23:41:45 +0000 (23:41 +0000)
non-type template parameter that has reference type, augment the
qualifiers of the non-type template argument with those of the
referenced type. Fixes PR6250.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95607 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiate.cpp
test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp

index c8cc9dc98f45ee7c407dea2bf043273b0066f8a7..99c1de619817bfe14781a96f380f30ef4ccdc633 100644 (file)
@@ -701,7 +701,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
 
 Sema::OwningExprResult
 TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
-                                                   NonTypeTemplateParmDecl *NTTP) {
+                                               NonTypeTemplateParmDecl *NTTP) {
   // If the corresponding template argument is NULL or non-existent, it's
   // because we are performing instantiation from explicitly-specified
   // template arguments in a function template, but there were some
@@ -731,7 +731,8 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
     // Derive the type we want the substituted decl to have.  This had
     // better be non-dependent, or these checks will have serious problems.
     QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
-                                            E->getLocation(), DeclarationName());
+                                            E->getLocation(), 
+                                            DeclarationName());
     assert(!TargetType.isNull() && "type substitution failed for param type");
     assert(!TargetType->isDependentType() && "param type still dependent");
 
@@ -769,6 +770,8 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
       }
     }
 
+    QualType T = VD->getType().getNonReferenceType();
+
     if (TargetType->isPointerType()) {
       // C++03 [temp.arg.nontype]p5:
       //  - For a non-type template-parameter of type pointer to
@@ -779,8 +782,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
       //    applied.
 
       OwningExprResult RefExpr
-        = SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
-                                   E->getLocation());
+        = SemaRef.BuildDeclRefExpr(VD, T, E->getLocation());
       if (RefExpr.isInvalid())
         return SemaRef.ExprError();
 
@@ -799,10 +801,14 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
       return SemaRef.Owned(RefE);
     }
 
-    // FIXME: template parameters can add qualifiers to a reference.
-
-    return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
-                                    E->getLocation());
+    // If the non-type template parameter has reference type, qualify the
+    // resulting declaration reference with the extra qualifiers on the
+    // type that the reference refers to.
+    if (const ReferenceType *TargetRef = TargetType->getAs<ReferenceType>())
+      T = SemaRef.Context.getQualifiedType(T, 
+                                  TargetRef->getPointeeType().getQualifiers());
+    
+    return SemaRef.BuildDeclRefExpr(VD, T, E->getLocation());
   }
 
   assert(Arg.getKind() == TemplateArgument::Integral);
index f74e78f746da06ea3cfd6bf32f627d15aad8adca..458aff2f0232ab93334388e70784a2e8e81e28f5 100644 (file)
@@ -89,6 +89,22 @@ namespace reference_parameters {
     S3<vi> s3v;
     S3<cvi> s3cv;
   }
+  
+  namespace PR6250 {
+    template <typename T, const T &ref> void inc() {
+      ref++; // expected-error{{read-only variable is not assignable}}
+    }
+  
+    template<typename T, const T &ref> void bind() {
+      T &ref2 = ref; // expected-error{{drops qualifiers}}
+    }
+    
+    int counter;
+    void test() {
+      inc<int, counter>(); // expected-note{{instantiation of}}
+      bind<int, counter>(); // expected-note{{instantiation of}}
+    }
+  }
 }
 
 //     -- For a non-type template-parameter of type pointer to function, the