diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-01-16 00:52:15 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-01-16 00:52:15 +0000 |
commit | b9df75f1b83d36be7bfbafc2f25d9fcf768874a3 (patch) | |
tree | 1c929dd57ccba7cc4cfd7849e8edf90fe0d9e113 | |
parent | ed6355d56cbeb1cd1a77cc46e0a519af25523ccb (diff) |
Apply adjustment to function- and array-typed non-type template
parameters (per C++ [temp.param]p8) when computing the type of a
reference to a non-type template parameter. Fixes <rdar://problem/13000548>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172585 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 13 | ||||
-rw-r--r-- | test/SemaTemplate/temp_arg_nontype.cpp | 15 |
2 files changed, 28 insertions, 0 deletions
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<FunctionDecl>(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 <int& I> struct PR10766 { static int *ip; }; template <int& I> int* PR10766<I>::ip = &I; + +namespace rdar13000548 { + template<typename R, R F(int)> + 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<int, g>::f(); // expected-note{{in instantiation of}} + } + +} |