[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

Nico Weber thakis at chromium.org
Wed Apr 4 15:00:55 PDT 2012


On Wed, Apr 4, 2012 at 2:54 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> 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?

Yes, thanks!




More information about the cfe-commits mailing list