<div class="gmail_quote">On Wed, Apr 4, 2012 at 2:44 PM, Nico Weber <span dir="ltr"><<a href="mailto:thakis@chromium.org">thakis@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Richard,<br>
<br>
(below)<br>
<div><div class="h5"><br>
On Wed, Apr 4, 2012 at 2:11 PM, Richard Smith<br>
<<a href="mailto:richard-llvm@metafoo.co.uk">richard-llvm@metafoo.co.uk</a>> wrote:<br>
> Author: rsmith<br>
> Date: Wed Apr  4 16:11:30 2012<br>
> New Revision: 154053<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=154053&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=154053&view=rev</a><br>
> Log:<br>
> Implement C++11 [temp.arg.nontype]'s permission to use the address of an object<br>
> or function with internal linkage as a non-type template argument.<br>
><br>
> Modified:<br>
>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
>    cfe/trunk/lib/Sema/SemaTemplate.cpp<br>
>    cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp<br>
>    cfe/trunk/test/CodeGenCXX/mangle-template.cpp<br>
>    cfe/trunk/test/SemaCXX/cxx98-compat.cpp<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=154053&r1=154052&r2=154053&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=154053&r1=154052&r2=154053&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr  4 16:11:30 2012<br>
> @@ -2361,11 +2361,18 @@<br>
>   "non-type template argument refers to non-static data member %0">;<br>
>  def err_template_arg_method : Error<<br>
>   "non-type template argument refers to non-static member function %0">;<br>
> -def err_template_arg_function_not_extern : Error<<br>
> -  "non-type template argument refers to function %0 with internal linkage">;<br>
> -def err_template_arg_object_not_extern : Error<<br>
> -  "non-type template argument refers to object %0 that does not have external "<br>
> -  "linkage">;<br>
> +def err_template_arg_object_no_linkage : Error<<br>
> +  "non-type template argument refers to %select{function|object}0 %1 that "<br>
> +  "does not have linkage">;<br>
> +def warn_cxx98_compat_template_arg_object_internal : Warning<<br>
> +  "non-type template argument referring to %select{function|object}0 %1 with "<br>
> +  "internal linkage is incompatible with C++98">,<br>
> +  InGroup<CXX98Compat>, DefaultIgnore;<br>
> +def ext_template_arg_object_internal : ExtWarn<<br>
> +  "non-type template argument referring to %select{function|object}0 %1 with "<br>
> +  "internal linkage is a C++11 extension">, InGroup<CXX11>;<br>
> +def err_template_arg_thread_local : Error<<br>
> +  "non-type template argument refers to thread-local object">;<br>
>  def note_template_arg_internal_object : Note<<br>
>   "non-type template argument refers to %select{function|object}0 here">;<br>
>  def note_template_arg_refers_here : Note<<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=154053&r1=154052&r2=154053&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=154053&r1=154052&r2=154053&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Apr  4 16:11:30 2012<br>
> @@ -3550,10 +3550,10 @@<br>
>     return true;<br>
>   }<br>
><br>
> -  NamedDecl *Entity = 0;<br>
> +  NamedDecl *Entity = DRE->getDecl();<br>
><br>
>   // Cannot refer to non-static data members<br>
> -  if (FieldDecl *Field = dyn_cast<FieldDecl>(DRE->getDecl())) {<br>
> +  if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) {<br>
>     S.Diag(Arg->getLocStart(), diag::err_template_arg_field)<br>
>       << Field << Arg->getSourceRange();<br>
>     S.Diag(Param->getLocation(), diag::note_template_param_here);<br>
> @@ -3561,28 +3561,44 @@<br>
>   }<br>
><br>
>   // Cannot refer to non-static member functions<br>
> -  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(DRE->getDecl()))<br>
> +  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Entity)) {<br>
>     if (!Method->isStatic()) {<br>
>       S.Diag(Arg->getLocStart(), diag::err_template_arg_method)<br>
>         << Method << Arg->getSourceRange();<br>
>       S.Diag(Param->getLocation(), diag::note_template_param_here);<br>
>       return true;<br>
>     }<br>
> +  }<br>
><br>
> -  // Functions must have external linkage.<br>
> -  if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) {<br>
> -    if (!isExternalLinkage(Func->getLinkage())) {<br>
> -      S.Diag(Arg->getLocStart(),<br>
> -             diag::err_template_arg_function_not_extern)<br>
> -        << Func << Arg->getSourceRange();<br>
> -      S.Diag(Func->getLocation(), diag::note_template_arg_internal_object)<br>
> -        << true;<br>
> -      return true;<br>
> -    }<br>
> +  FunctionDecl *Func = dyn_cast<FunctionDecl>(Entity);<br>
> +  VarDecl *Var = dyn_cast<VarDecl>(Entity);<br>
> +<br>
> +  // A non-type template argument must refer to an object or function.<br>
> +  if (!Func && !Var) {<br>
> +    // We found something, but we don't know specifically what it is.<br>
> +    S.Diag(Arg->getLocStart(), diag::err_template_arg_not_object_or_func)<br>
> +      << Arg->getSourceRange();<br>
> +    S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);<br>
> +    return true;<br>
> +  }<br>
><br>
> -    // Okay: we've named a function with external linkage.<br>
> -    Entity = Func;<br>
> +  // Address / reference template args must have external linkage in C++98.<br>
> +  if (Entity->getLinkage() == InternalLinkage) {<br>
> +    S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus0x ?<br>
> +             diag::warn_cxx98_compat_template_arg_object_internal :<br>
> +             diag::ext_template_arg_object_internal)<br>
> +      << !Func << Entity << Arg->getSourceRange();<br>
> +    S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)<br>
> +      << !Func;<br>
> +  } else if (Entity->getLinkage() == NoLinkage) {<br>
> +    S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage)<br>
> +      << !Func << Entity << Arg->getSourceRange();<br>
> +    S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)<br>
> +      << !Func;<br>
> +    return true;<br>
> +  }<br>
><br>
> +  if (Func) {<br>
>     // If the template parameter has pointer type, the function decays.<br>
>     if (ParamType->isPointerType() && !AddressTaken)<br>
>       ArgType = S.Context.getPointerType(Func->getType());<br>
> @@ -3605,16 +3621,7 @@<br>
><br>
>       ArgType = Func->getType();<br>
>     }<br>
> -  } else if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {<br>
> -    if (!isExternalLinkage(Var->getLinkage())) {<br>
> -      S.Diag(Arg->getLocStart(),<br>
> -             diag::err_template_arg_object_not_extern)<br>
> -        << Var << Arg->getSourceRange();<br>
> -      S.Diag(Var->getLocation(), diag::note_template_arg_internal_object)<br>
> -        << true;<br>
> -      return true;<br>
> -    }<br>
> -<br>
> +  } else {<br>
>     // A value of reference type is not an object.<br>
>     if (Var->getType()->isReferenceType()) {<br>
>       S.Diag(Arg->getLocStart(),<br>
> @@ -3624,8 +3631,14 @@<br>
>       return true;<br>
>     }<br>
><br>
> -    // Okay: we've named an object with external linkage<br>
> -    Entity = Var;<br>
> +    // A template argument must have static storage duration.<br>
> +    // FIXME: Ensure this works for thread_local as well as __thread.<br>
> +    if (Var->isThreadSpecified()) {<br>
> +      S.Diag(Arg->getLocStart(), diag::err_template_arg_thread_local)<br>
> +        << Arg->getSourceRange();<br>
> +      S.Diag(Var->getLocation(), diag::note_template_arg_refers_here);<br>
> +      return true;<br>
> +    }<br>
><br>
>     // If the template parameter has pointer type, we must have taken<br>
>     // the address of this object.<br>
> @@ -3672,13 +3685,6 @@<br>
>         S.Diag(Param->getLocation(), diag::note_template_param_here);<br>
>       }<br>
>     }<br>
> -  } else {<br>
> -    // We found something else, but we don't know specifically what it is.<br>
> -    S.Diag(Arg->getLocStart(),<br>
> -           diag::err_template_arg_not_object_or_func)<br>
> -      << Arg->getSourceRange();<br>
> -    S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);<br>
> -    return true;<br>
>   }<br>
><br>
>   bool ObjCLifetimeConversion;<br>
><br>
> Modified: cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp?rev=154053&r1=154052&r2=154053&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp?rev=154053&r1=154052&r2=154053&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp (original)<br>
> +++ cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp Wed Apr  4 16:11:30 2012<br>
> @@ -1,6 +1,6 @@<br>
>  // RUN: %clang_cc1 -fsyntax-only -verify %s<br>
><br>
> -// C++0x [temp.arg.nontype]p1:<br>
> +// C++11 [temp.arg.nontype]p1:<br>
>  //<br>
>  //   A template-argument for a non-type, non-template template-parameter shall<br>
>  //   be one of:<br>
> @@ -19,27 +19,65 @@<br>
>   template <typename T, int (T::* M)(int)> X5<T, M>::X5() { }<br>
>  }<br>
><br>
> -//   -- the address of an object or function with external linkage, including<br>
> -//      function templates and function template-ids but excluding non-static<br>
> -//      class members, expressed as & id-expression where the & is optional if<br>
> -//      the name refers to a function or array, or if the corresponding<br>
> -//      template-parameter is a reference; or<br>
> +//   -- a constant expression that designates the address of an object with<br>
> +//      static storage duration and external or internal linkage or a function<br>
> +//      with external or internal linkage, including function templates and<br>
> +//      function template-ids, but excluting non-static class members, expressed<br>
> +//      (ignoring parentheses) as & id-expression, except that the & may be<br>
> +//      omitted if the name refers to a function or array and shall be omitted<br>
> +//      if the corresopnding template-parameter is a reference; or<br>
>  namespace addr_of_obj_or_func {<br>
> -  template <int* p> struct X0 { };<br>
> +  template <int* p> struct X0 { }; // expected-note 4{{here}}<br>
>   template <int (*fp)(int)> struct X1 { };<br>
> -  // FIXME: Add reference template parameter tests.<br>
> +  template <int &p> struct X2 { }; // expected-note 4{{here}}<br>
> +  template <const int &p> struct X2k { }; // expected-note {{here}}<br>
> +  template <int (&fp)(int)> struct X3 { }; // expected-note 4{{here}}<br>
><br>
>   int i = 42;<br>
>   int iarr[10];<br>
>   int f(int i);<br>
> +  const int ki = 9; // expected-note 5{{here}}<br>
> +  __thread int ti = 100; // expected-note 2{{here}}<br>
<br>
</div></div>Fails like this on mac:<br>
<br>
******************** TEST 'Clang ::<br>
CXX/temp/temp.arg/temp.arg.nontype/p1.cpp' FAILED ********************<br>
Script:<br>
--<br>
/Volumes/MacintoshHD2/src/llvm-svn/Release+Asserts/bin/clang -cc1<br>
-internal-isystem<br>
/Volumes/MacintoshHD2/src/llvm-svn/Release+Asserts/bin/../lib/clang/3.1/include<br>
-fsyntax-only -verify<br>
/Volumes/MacintoshHD2/src/llvm-svn/tools/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp<br>
--<br>
Exit Code: 1<br>
Command Output (stderr):<br>
--<br>
error: 'error' diagnostics expected but not seen:<br>
  Line 51: refers to thread-local object<br>
  Line 67: refers to thread-local object<br>
error: 'error' diagnostics seen but not expected:<br>
  Line 40: thread-local storage is unsupported for the current target<br>
error: 'note' diagnostics expected but not seen:<br>
  Line 40: here<br>
  Line 40: here<br>
5 errors generated.<br></blockquote><div> </div><div>Thanks, does r154058 help?</div></div>