diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 67c9ae5e1f..9b56a204c0 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4560,6 +4560,16 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, } QualType T = VD->getType().getNonReferenceType(); + // C++ [temp.param]p8: + // + // A non-type template-parameter of type "array of T" or + // "function returning T" is adjusted to be of type "pointer to + // T" or "pointer to function returning T", respectively. + if (ParamType->isArrayType()) + ParamType = Context.getArrayDecayedType(ParamType); + else if (ParamType->isFunctionType()) + ParamType = Context.getPointerType(ParamType); + if (ParamType->isPointerType()) { // When the non-type template parameter is a pointer, take the // address of the declaration. @@ -4589,6 +4599,9 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, VK = VK_LValue; T = Context.getQualifiedType(T, TargetRef->getPointeeType().getQualifiers()); + } else if (isa(VD)) { + // References to functions are always lvalues. + VK = VK_LValue; } return BuildDeclRefExpr(VD, T, VK, Loc); diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp index 31947d2df5..59da9c667e 100644 --- a/test/SemaTemplate/temp_arg_nontype.cpp +++ b/test/SemaTemplate/temp_arg_nontype.cpp @@ -323,3 +323,18 @@ namespace PR10579 { template struct PR10766 { static int *ip; }; template int* PR10766::ip = &I; + +namespace rdar13000548 { + template + struct X { + typedef R (*fptype)(int); + static fptype f() { return &F; } // expected-error{{address expression must be an lvalue or a function designator}} + }; + + int g(int); + void test() + { + X::f(); // expected-note{{in instantiation of}} + } + +}