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.

llvm-svn: 102777
This commit is contained in:
Douglas Gregor 2010-04-30 21:46:38 +00:00
parent 4d4dcc8ed7
commit fabf95d066
2 changed files with 36 additions and 2 deletions

View 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);
}
}

View 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;
}
}