Author: rnk Date: Tue Oct 20 16:04:13 2015 New Revision: 250856 URL: http://llvm.org/viewvc/llvm-project?rev=250856&view=rev Log: Re-land r250592 without rejecting field refs in unevaluated contexts
This time, I went with the first approach from http://reviews.llvm.org/D6700, where clang actually attempts to form an implicit member reference from an UnresolvedLookupExpr. We know that there are only two possible outcomes at this point, a DeclRefExpr of the FieldDecl or an error, but its safer to reuse the existing machinery for this. Modified: cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/test/SemaTemplate/instantiate-using-decl.cpp Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=250856&r1=250855&r2=250856&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Tue Oct 20 16:04:13 2015 @@ -9127,9 +9127,20 @@ TreeTransform<Derived>::TransformUnresol SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc(); // If we have neither explicit template arguments, nor the template keyword, - // it's a normal declaration name. - if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) + // it's a normal declaration name or member reference. + if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) { + NamedDecl *D = R.getAsSingle<NamedDecl>(); + // In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an + // instance member. In other contexts, BuildPossibleImplicitMemberExpr will + // give a good diagnostic. + if (D && D->isCXXInstanceMember()) { + return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, + /*TemplateArgs=*/nullptr, + /*Scope=*/nullptr); + } + return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); + } // If we have template arguments, rebuild them, then rebuild the // templateid expression. Modified: cfe/trunk/test/SemaTemplate/instantiate-using-decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-using-decl.cpp?rev=250856&r1=250855&r2=250856&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/instantiate-using-decl.cpp (original) +++ cfe/trunk/test/SemaTemplate/instantiate-using-decl.cpp Tue Oct 20 16:04:13 2015 @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s namespace test0 { namespace N { } @@ -104,3 +105,65 @@ namespace PR16936 { x.f(); } } + +namespace pr21923 { +template <typename> struct Base { + int field; + void method(); +}; +template <typename Scalar> struct Derived : Base<Scalar> { + using Base<Scalar>::field; + using Base<Scalar>::method; + static void m_fn1() { + // expected-error@+1 {{invalid use of member 'field' in static member function}} + (void)field; + // expected-error@+1 {{invalid use of member 'field' in static member function}} + (void)&field; + // expected-error@+1 {{call to non-static member function without an object argument}} + (void)method; + // expected-error@+1 {{call to non-static member function without an object argument}} + (void)&method; + // expected-error@+1 {{call to non-static member function without an object argument}} + method(); + (void)&Base<Scalar>::field; + (void)&Base<Scalar>::method; + } +#if __cplusplus >= 201103L + // These usages are OK in C++11 due to the unevaluated context. + enum { TheSize = sizeof(field) }; + typedef decltype(field) U; +#else + // expected-error@+1 {{invalid use of non-static data member 'field'}} + enum { TheSize = sizeof(field) }; +#endif +}; + +#if __cplusplus < 201103L +// C++98 has an extra note for TheSize. +// expected-note@+2 {{requested here}} +#endif +template class Derived<int>; // expected-note {{requested here}} + +// This is interesting because we form an UnresolvedLookupExpr in the static +// function template and an UnresolvedMemberExpr in the instance function +// template. As a result, we get slightly different behavior. +struct UnresolvedTemplateNames { + template <typename> void maybe_static(); +#if __cplusplus < 201103L + // expected-warning@+2 {{default template arguments for a function template are a C++11 extension}} +#endif + template <typename T, typename T::type = 0> static void maybe_static(); + + template <typename T> + void instance_method() { (void)maybe_static<T>(); } + template <typename T> + static void static_method() { + // expected-error@+1 {{call to non-static member function without an object argument}} + (void)maybe_static<T>(); + } +}; +void force_instantiation(UnresolvedTemplateNames x) { + x.instance_method<int>(); + UnresolvedTemplateNames::static_method<int>(); // expected-note {{requested here}} +} +} // pr21923 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits