From: Douglas Gregor Date: Fri, 30 Apr 2010 21:46:38 +0000 (+0000) Subject: After substituting a template argument for a non-type template X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c0c8300329718b45df259c49310d3c2b377a6e0f;p=clang After substituting a template argument for a non-type template 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 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index db9ed7e1ef..56410a2cfa 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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(); + 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); } } diff --git a/test/SemaTemplate/instantiate-non-type-template-parameter.cpp b/test/SemaTemplate/instantiate-non-type-template-parameter.cpp index 414e62b13a..cbadcde2c1 100644 --- a/test/SemaTemplate/instantiate-non-type-template-parameter.cpp +++ b/test/SemaTemplate/instantiate-non-type-template-parameter.cpp @@ -9,6 +9,28 @@ public: } }; -int main(int argc, char *argv[]) { +void test_stringswitch(int argc, char *argv[]) { (void)StringSwitch(); } + +namespace PR6986 { + template + struct non_const_member_base + { + }; + + template + struct member: non_const_member_base + { + }; + + struct test_class + { + int int_member; + }; + typedef member< test_class,const int,&test_class::int_member > ckey_m; + void test() + { + ckey_m m; + } +}