r250856 - Re-land r250592 without rejecting field refs in unevaluated contexts
Reid Kleckner via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 20 14:04:13 PDT 2015
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 at +1 {{invalid use of member 'field' in static member function}}
+ (void)field;
+ // expected-error at +1 {{invalid use of member 'field' in static member function}}
+ (void)&field;
+ // expected-error at +1 {{call to non-static member function without an object argument}}
+ (void)method;
+ // expected-error at +1 {{call to non-static member function without an object argument}}
+ (void)&method;
+ // expected-error at +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 at +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 at +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 at +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 at +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
More information about the cfe-commits
mailing list