diff options
author | Reid Kleckner <rnk@google.com> | 2015-10-17 00:19:04 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2015-10-17 00:19:04 +0000 |
commit | f438a020bfc1cfe0ecabd996e2f05fcc809955de (patch) | |
tree | 181dcb7d49bb4f2a08daea80939e9730430032b7 /clang/test/SemaCXX/using-decl-1.cpp | |
parent | 4f43e80ecef00cc150e177bb0cdf8a2685b264a0 (diff) | |
download | bcm5719-llvm-f438a020bfc1cfe0ecabd996e2f05fcc809955de.tar.gz bcm5719-llvm-f438a020bfc1cfe0ecabd996e2f05fcc809955de.zip |
Diagnose UnresolvedLookupExprs that resolve to instance members in static methods
During the initial template parse for this code, 'member' is unresolved
and we don't know anything about it:
struct A { int member };
template <typename T>
struct B : public T {
using T::member;
static void f() {
(void)member; // Could be static or non-static.
}
};
template class B<A>;
The pattern declaration contains an UnresolvedLookupExpr rather than an
UnresolvedMemberExpr because `f` is static, and `member` should never be
a field. However, if the code is invalid, it may become a field, in
which case we should diagnose it.
Reviewers: rjmccall, rsmith
Differential Revision: http://reviews.llvm.org/D6700
llvm-svn: 250592
Diffstat (limited to 'clang/test/SemaCXX/using-decl-1.cpp')
-rw-r--r-- | clang/test/SemaCXX/using-decl-1.cpp | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/clang/test/SemaCXX/using-decl-1.cpp b/clang/test/SemaCXX/using-decl-1.cpp index ca532692c1c..ac53b3758e4 100644 --- a/clang/test/SemaCXX/using-decl-1.cpp +++ b/clang/test/SemaCXX/using-decl-1.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -DCXX11 -fsyntax-only -verify -std=c++11 %s extern "C" { void f(bool); } @@ -327,3 +327,52 @@ namespace PR24033 { using PR24033::st; // expected-error {{target of using declaration conflicts with declaration already in scope}} } } + +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; + } +}; +// expected-note@+1 {{in instantiation of member function 'pr21923::Derived<int>::m_fn1' requested here}} +template class Derived<int>; + +#ifdef CXX11 +// 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(); + 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}} +} +#endif // CXX11 +} |