diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-08-14 23:34:52 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-08-14 23:34:52 +0000 |
commit | 062be331e29b88c72826ed04840e45a8df2b97aa (patch) | |
tree | 908f0e8ca7c959014281e6605569b0ffcc098782 /clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp | |
parent | 81db58e177c842b79de0c44767a8eb8695edf82f (diff) | |
download | bcm5719-llvm-062be331e29b88c72826ed04840e45a8df2b97aa.tar.gz bcm5719-llvm-062be331e29b88c72826ed04840e45a8df2b97aa.zip |
Limit our MSVC compat hack for nested names from dependent bases
Previously, any undeclared unqualified id starting a nested name
specifier in a dependent context would have its lookup retried during
template instantiation. Now we limit that retry hack to methods of a
class with dependent bases. Free function templates in particular are
no longer affected by this hack.
Also, diagnose this as a Microsoft extension. This has the downside that
template authors may see this warning *and* an error during
instantiation time about this identifier. Fixing that will probably
require formalizing some kind of "delayed" identifier, instead of our
ad-hoc solutions of forming dependent AST nodes when lookup fails.
Based on a patch by Kim Gräsman!
Differential Revision: http://reviews.llvm.org/D4854
llvm-svn: 215683
Diffstat (limited to 'clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp')
-rw-r--r-- | clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp index 40f73c0d9e6..4bdb97bbbd1 100644 --- a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp +++ b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp @@ -220,7 +220,8 @@ template <typename T> struct C : T { int *bar() { return &b; } // expected-error {{no member named 'b' in 'PR16014::C<PR16014::A>'}} expected-warning {{lookup into dependent bases}} int baz() { return T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} int T::*qux() { return &T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} - int T::*fuz() { return &U::a; } // expected-error {{use of undeclared identifier 'U'}} + int T::*fuz() { return &U::a; } // expected-error {{use of undeclared identifier 'U'}} \ + // expected-warning {{unqualified lookup into dependent bases of class template 'C'}} }; template struct B<A>; @@ -249,7 +250,8 @@ struct A : T { ::UndefClass::undef(); // expected-error {{no member named 'UndefClass' in the global namespace}} } void baz() { - B::qux(); // expected-error {{use of undeclared identifier 'B'}} + B::qux(); // expected-error {{use of undeclared identifier 'B'}} \ + // expected-warning {{unqualified lookup into dependent bases of class template 'A'}} } }; @@ -460,3 +462,11 @@ template <typename T> struct D : C<T> { int x = f<NameFromBase>(); }; } + +namespace function_template_undef_impl { +template<class T> +void f() { + Undef::staticMethod(); // expected-error {{use of undeclared identifier 'Undef'}} + UndefVar.method(); // expected-error {{use of undeclared identifier 'UndefVar'}} +} +} |