]> granicus.if.org Git - clang/commitdiff
Apply adjustment to function- and array-typed non-type template
authorDouglas Gregor <dgregor@apple.com>
Wed, 16 Jan 2013 00:52:15 +0000 (00:52 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 16 Jan 2013 00:52:15 +0000 (00:52 +0000)
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

lib/Sema/SemaTemplate.cpp
test/SemaTemplate/temp_arg_nontype.cpp

index 67c9ae5e1fbec3ca378be2d0b89de794a840cc6f..9b56a204c001a8520748207e60d7e69c06b24b57 100644 (file)
@@ -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);
index 31947d2df5b7096b921412b49ebfe9b9813e33fa..59da9c667e54e0d5d7848c845df6a3d8a451e4aa 100644 (file)
@@ -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}}
+  }
+
+}