[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