[cfe-commits] r154053 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp test/CodeGenCXX/mangle-template.cpp test/SemaCXX/cxx98-compat.cpp

Richard Smith richard at metafoo.co.uk
Wed Apr 4 14:54:43 PDT 2012


On Wed, Apr 4, 2012 at 2:44 PM, Nico Weber <thakis at chromium.org> wrote:

> Hi Richard,
>
> (below)
>
> On Wed, Apr 4, 2012 at 2:11 PM, Richard Smith
> <richard-llvm at metafoo.co.uk> wrote:
> > Author: rsmith
> > Date: Wed Apr  4 16:11:30 2012
> > New Revision: 154053
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=154053&view=rev
> > Log:
> > Implement C++11 [temp.arg.nontype]'s permission to use the address of an
> object
> > or function with internal linkage as a non-type template argument.
> >
> > Modified:
> >    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> >    cfe/trunk/lib/Sema/SemaTemplate.cpp
> >    cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
> >    cfe/trunk/test/CodeGenCXX/mangle-template.cpp
> >    cfe/trunk/test/SemaCXX/cxx98-compat.cpp
> >
> > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=154053&r1=154052&r2=154053&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr  4
> 16:11:30 2012
> > @@ -2361,11 +2361,18 @@
> >   "non-type template argument refers to non-static data member %0">;
> >  def err_template_arg_method : Error<
> >   "non-type template argument refers to non-static member function %0">;
> > -def err_template_arg_function_not_extern : Error<
> > -  "non-type template argument refers to function %0 with internal
> linkage">;
> > -def err_template_arg_object_not_extern : Error<
> > -  "non-type template argument refers to object %0 that does not have
> external "
> > -  "linkage">;
> > +def err_template_arg_object_no_linkage : Error<
> > +  "non-type template argument refers to %select{function|object}0 %1
> that "
> > +  "does not have linkage">;
> > +def warn_cxx98_compat_template_arg_object_internal : Warning<
> > +  "non-type template argument referring to %select{function|object}0 %1
> with "
> > +  "internal linkage is incompatible with C++98">,
> > +  InGroup<CXX98Compat>, DefaultIgnore;
> > +def ext_template_arg_object_internal : ExtWarn<
> > +  "non-type template argument referring to %select{function|object}0 %1
> with "
> > +  "internal linkage is a C++11 extension">, InGroup<CXX11>;
> > +def err_template_arg_thread_local : Error<
> > +  "non-type template argument refers to thread-local object">;
> >  def note_template_arg_internal_object : Note<
> >   "non-type template argument refers to %select{function|object}0 here">;
> >  def note_template_arg_refers_here : Note<
> >
> > Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=154053&r1=154052&r2=154053&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Apr  4 16:11:30 2012
> > @@ -3550,10 +3550,10 @@
> >     return true;
> >   }
> >
> > -  NamedDecl *Entity = 0;
> > +  NamedDecl *Entity = DRE->getDecl();
> >
> >   // Cannot refer to non-static data members
> > -  if (FieldDecl *Field = dyn_cast<FieldDecl>(DRE->getDecl())) {
> > +  if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) {
> >     S.Diag(Arg->getLocStart(), diag::err_template_arg_field)
> >       << Field << Arg->getSourceRange();
> >     S.Diag(Param->getLocation(), diag::note_template_param_here);
> > @@ -3561,28 +3561,44 @@
> >   }
> >
> >   // Cannot refer to non-static member functions
> > -  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(DRE->getDecl()))
> > +  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Entity)) {
> >     if (!Method->isStatic()) {
> >       S.Diag(Arg->getLocStart(), diag::err_template_arg_method)
> >         << Method << Arg->getSourceRange();
> >       S.Diag(Param->getLocation(), diag::note_template_param_here);
> >       return true;
> >     }
> > +  }
> >
> > -  // Functions must have external linkage.
> > -  if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) {
> > -    if (!isExternalLinkage(Func->getLinkage())) {
> > -      S.Diag(Arg->getLocStart(),
> > -             diag::err_template_arg_function_not_extern)
> > -        << Func << Arg->getSourceRange();
> > -      S.Diag(Func->getLocation(),
> diag::note_template_arg_internal_object)
> > -        << true;
> > -      return true;
> > -    }
> > +  FunctionDecl *Func = dyn_cast<FunctionDecl>(Entity);
> > +  VarDecl *Var = dyn_cast<VarDecl>(Entity);
> > +
> > +  // A non-type template argument must refer to an object or function.
> > +  if (!Func && !Var) {
> > +    // We found something, but we don't know specifically what it is.
> > +    S.Diag(Arg->getLocStart(),
> diag::err_template_arg_not_object_or_func)
> > +      << Arg->getSourceRange();
> > +    S.Diag(DRE->getDecl()->getLocation(),
> diag::note_template_arg_refers_here);
> > +    return true;
> > +  }
> >
> > -    // Okay: we've named a function with external linkage.
> > -    Entity = Func;
> > +  // Address / reference template args must have external linkage in
> C++98.
> > +  if (Entity->getLinkage() == InternalLinkage) {
> > +    S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus0x ?
> > +             diag::warn_cxx98_compat_template_arg_object_internal :
> > +             diag::ext_template_arg_object_internal)
> > +      << !Func << Entity << Arg->getSourceRange();
> > +    S.Diag(Entity->getLocation(),
> diag::note_template_arg_internal_object)
> > +      << !Func;
> > +  } else if (Entity->getLinkage() == NoLinkage) {
> > +    S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage)
> > +      << !Func << Entity << Arg->getSourceRange();
> > +    S.Diag(Entity->getLocation(),
> diag::note_template_arg_internal_object)
> > +      << !Func;
> > +    return true;
> > +  }
> >
> > +  if (Func) {
> >     // If the template parameter has pointer type, the function decays.
> >     if (ParamType->isPointerType() && !AddressTaken)
> >       ArgType = S.Context.getPointerType(Func->getType());
> > @@ -3605,16 +3621,7 @@
> >
> >       ArgType = Func->getType();
> >     }
> > -  } else if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
> > -    if (!isExternalLinkage(Var->getLinkage())) {
> > -      S.Diag(Arg->getLocStart(),
> > -             diag::err_template_arg_object_not_extern)
> > -        << Var << Arg->getSourceRange();
> > -      S.Diag(Var->getLocation(),
> diag::note_template_arg_internal_object)
> > -        << true;
> > -      return true;
> > -    }
> > -
> > +  } else {
> >     // A value of reference type is not an object.
> >     if (Var->getType()->isReferenceType()) {
> >       S.Diag(Arg->getLocStart(),
> > @@ -3624,8 +3631,14 @@
> >       return true;
> >     }
> >
> > -    // Okay: we've named an object with external linkage
> > -    Entity = Var;
> > +    // A template argument must have static storage duration.
> > +    // FIXME: Ensure this works for thread_local as well as __thread.
> > +    if (Var->isThreadSpecified()) {
> > +      S.Diag(Arg->getLocStart(), diag::err_template_arg_thread_local)
> > +        << Arg->getSourceRange();
> > +      S.Diag(Var->getLocation(), diag::note_template_arg_refers_here);
> > +      return true;
> > +    }
> >
> >     // If the template parameter has pointer type, we must have taken
> >     // the address of this object.
> > @@ -3672,13 +3685,6 @@
> >         S.Diag(Param->getLocation(), diag::note_template_param_here);
> >       }
> >     }
> > -  } else {
> > -    // We found something else, but we don't know specifically what it
> is.
> > -    S.Diag(Arg->getLocStart(),
> > -           diag::err_template_arg_not_object_or_func)
> > -      << Arg->getSourceRange();
> > -    S.Diag(DRE->getDecl()->getLocation(),
> diag::note_template_arg_refers_here);
> > -    return true;
> >   }
> >
> >   bool ObjCLifetimeConversion;
> >
> > Modified: cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
> > URL:
> 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
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp (original)
> > +++ cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp Wed Apr  4
> 16:11:30 2012
> > @@ -1,6 +1,6 @@
> >  // RUN: %clang_cc1 -fsyntax-only -verify %s
> >
> > -// C++0x [temp.arg.nontype]p1:
> > +// C++11 [temp.arg.nontype]p1:
> >  //
> >  //   A template-argument for a non-type, non-template
> template-parameter shall
> >  //   be one of:
> > @@ -19,27 +19,65 @@
> >   template <typename T, int (T::* M)(int)> X5<T, M>::X5() { }
> >  }
> >
> > -//   -- the address of an object or function with external linkage,
> including
> > -//      function templates and function template-ids but excluding
> non-static
> > -//      class members, expressed as & id-expression where the & is
> optional if
> > -//      the name refers to a function or array, or if the corresponding
> > -//      template-parameter is a reference; or
> > +//   -- a constant expression that designates the address of an object
> with
> > +//      static storage duration and external or internal linkage or a
> function
> > +//      with external or internal linkage, including function templates
> and
> > +//      function template-ids, but excluting non-static class members,
> expressed
> > +//      (ignoring parentheses) as & id-expression, except that the &
> may be
> > +//      omitted if the name refers to a function or array and shall be
> omitted
> > +//      if the corresopnding template-parameter is a reference; or
> >  namespace addr_of_obj_or_func {
> > -  template <int* p> struct X0 { };
> > +  template <int* p> struct X0 { }; // expected-note 4{{here}}
> >   template <int (*fp)(int)> struct X1 { };
> > -  // FIXME: Add reference template parameter tests.
> > +  template <int &p> struct X2 { }; // expected-note 4{{here}}
> > +  template <const int &p> struct X2k { }; // expected-note {{here}}
> > +  template <int (&fp)(int)> struct X3 { }; // expected-note 4{{here}}
> >
> >   int i = 42;
> >   int iarr[10];
> >   int f(int i);
> > +  const int ki = 9; // expected-note 5{{here}}
> > +  __thread int ti = 100; // expected-note 2{{here}}
>
> Fails like this on mac:
>
> ******************** TEST 'Clang ::
> CXX/temp/temp.arg/temp.arg.nontype/p1.cpp' FAILED ********************
> Script:
> --
> /Volumes/MacintoshHD2/src/llvm-svn/Release+Asserts/bin/clang -cc1
> -internal-isystem
>
> /Volumes/MacintoshHD2/src/llvm-svn/Release+Asserts/bin/../lib/clang/3.1/include
> -fsyntax-only -verify
>
> /Volumes/MacintoshHD2/src/llvm-svn/tools/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
> --
> Exit Code: 1
> Command Output (stderr):
> --
> error: 'error' diagnostics expected but not seen:
>  Line 51: refers to thread-local object
>  Line 67: refers to thread-local object
> error: 'error' diagnostics seen but not expected:
>  Line 40: thread-local storage is unsupported for the current target
> error: 'note' diagnostics expected but not seen:
>  Line 40: here
>  Line 40: here
> 5 errors generated.
>

Thanks, does r154058 help?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120404/bc6b723d/attachment.html>


More information about the cfe-commits mailing list