On Wed, Apr 4, 2012 at 2:54 PM, Richard Smith <[email protected]> wrote: > On Wed, Apr 4, 2012 at 2:44 PM, Nico Weber <[email protected]> wrote: >> >> Hi Richard, >> >> (below) >> >> On Wed, Apr 4, 2012 at 2:11 PM, Richard Smith >> <[email protected]> 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! _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
