]> granicus.if.org Git - clang/commitdiff
After substituting a template argument for a non-type template
authorDouglas Gregor <dgregor@apple.com>
Fri, 30 Apr 2010 21:46:38 +0000 (21:46 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 30 Apr 2010 21:46:38 +0000 (21:46 +0000)
parameter with pointer-to-member type, we may have to perform a
qualification conversion, since the pointee type of the parameter
might be more qualified than the pointee type of the argument we form
from the declaration. Fixes PR6986.

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

lib/Sema/SemaTemplate.cpp
test/SemaTemplate/instantiate-non-type-template-parameter.cpp

index db9ed7e1efce8799e84bfbd1791bf6b184be66e0..56410a2cfa4ff90897002f7b0e65f4da78709025 100644 (file)
@@ -3061,9 +3061,21 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
         return ExprError();
       
       RefExpr = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(RefExpr));
+      
+      // We might need to perform a trailing qualification conversion, since
+      // the element type on the parameter could be more qualified than the
+      // element type in the expression we constructed.
+      if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(),
+                                    ParamType.getUnqualifiedType())) {
+        Expr *RefE = RefExpr.takeAs<Expr>();
+        ImpCastExprToType(RefE, ParamType.getUnqualifiedType(),
+                          CastExpr::CK_NoOp);
+        RefExpr = Owned(RefE);
+      }
+      
       assert(!RefExpr.isInvalid() &&
              Context.hasSameType(((Expr*) RefExpr.get())->getType(),
-                                 ParamType));
+                                 ParamType.getUnqualifiedType()));
       return move(RefExpr);
     }
   }
index 414e62b13a032803ce30c5207769483e694c0931..cbadcde2c1c157591be477f238dba3c0b69f46e3 100644 (file)
@@ -9,6 +9,28 @@ public:
   }
 };
 
-int main(int argc, char *argv[]) {
+void test_stringswitch(int argc, char *argv[]) {
   (void)StringSwitch<int>();
 }
+
+namespace PR6986 {
+  template<class Class,typename Type,Type Class::*> 
+  struct non_const_member_base
+  {
+  };
+
+  template<class Class,typename Type,Type Class::*PtrToMember> 
+  struct member: non_const_member_base<Class,Type,PtrToMember>
+  {
+  };
+
+  struct test_class
+  {
+    int int_member;
+  };
+  typedef member< test_class,const int,&test_class::int_member > ckey_m;
+  void test()
+  {
+    ckey_m m;
+  }
+}