diff options
author | Reid Kleckner <rnk@google.com> | 2019-02-26 02:22:17 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2019-02-26 02:22:17 +0000 |
commit | 2bc58bd06dc4aeb2f10fb3bf56a69583b4ebf212 (patch) | |
tree | 532077a8783e9fcda229c22fc0750e809147864e /clang | |
parent | 2f055f026ad76f3503c7c40c40f4b71594adbe55 (diff) | |
download | bcm5719-llvm-2bc58bd06dc4aeb2f10fb3bf56a69583b4ebf212.tar.gz bcm5719-llvm-2bc58bd06dc4aeb2f10fb3bf56a69583b4ebf212.zip |
[MS] Fix for Bug 8446, template instantiation without a 'typename' keyword
Patch by Zahira Ammarguellat!
Differential Revision: https://reviews.llvm.org/D41950
llvm-svn: 354838
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 11 | ||||
-rw-r--r-- | clang/test/SemaTemplate/missing-typename.cpp | 102 |
2 files changed, 113 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index b2cd0bd0d3d..11f1aeb76ff 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1498,6 +1498,17 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // expression. *HasMissingTypename = true; return TPResult::Ambiguous; + } else { + // In MS mode, if HasMissingTypename is not provided, and the tokens + // are or the form *) or &) *> or &> &&>, this can't be an expression. + // The typename must be missing. + if (getLangOpts().MSVCCompat) { + if (((Tok.is(tok::amp) || Tok.is(tok::star)) && + (NextToken().is(tok::r_paren) || + NextToken().is(tok::greater))) || + (Tok.is(tok::ampamp) && NextToken().is(tok::greater))) + return TPResult::True; + } } } else { // Try to resolve the name. If it doesn't exist, assume it was diff --git a/clang/test/SemaTemplate/missing-typename.cpp b/clang/test/SemaTemplate/missing-typename.cpp new file mode 100644 index 00000000000..3f8282dcaff --- /dev/null +++ b/clang/test/SemaTemplate/missing-typename.cpp @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-unused +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-unused -fms-compatibility -DMSVC + +namespace PR8446_1 { +struct A { + typedef int BASE_VALUE; +}; + +void g(int &y) {} + +template <typename BASE_CLASS> +void f(int &rValue) { +#if MSVC +// expected-warning@+4 {{missing 'typename' prior to dependent type name 'BASE_CLASS::BASE_VALUE'}} +#else + // expected-error@+2 {{expected expression}} +#endif + return g((BASE_CLASS::BASE_VALUE &)rValue); +} + +int main() { + int x; + f<A>(x); + return 0; +} +} // namespace PR8446_1 + + +namespace PR8446_2 { +struct site_symmetry_ops {}; + +template <class wt> +struct class_ { + template <class A1> + void def(A1 const &a1) {} +}; + +template <class A1, class A2> +struct init { + init() {} +}; + +struct special_position_site_parameter { + typedef char scatterer_type; +}; + +template <class wt> +struct valued_asu_parameter_heir_wrapper { + static class_<wt> wrap(char const *name) { + return class_<wt>(); + } +}; + +template <class wt> +struct special_position_wrapper { + static void wrap(char const *name) { + valued_asu_parameter_heir_wrapper<wt>::wrap(name) +#if MSVC + // expected-warning@+4 {{missing 'typename' prior to dependent type name 'wt::scatterer_type'}} +#else + // expected-error@+2 {{expected expression}} +#endif + .def(init<site_symmetry_ops const &, wt::scatterer_type *>()); + } +}; + +void wrap_special_position() { + special_position_wrapper<special_position_site_parameter>::wrap("special_position_site_parameter"); +} +} // namespace PR8446_2 + +namespace PR8446_3 { +int g(int); +template <typename T> +int f1(int x) { + return g((T::InnerName & x) & x); +} + +template <typename T> +int f2(int x) { + return g((T::InnerName & 3) & x); +} + +template <typename T> +int f3(int x) { + return g((T::InnerName & (3))); +} + +template <typename T> +int f4(int x) { + return g((T::InnerName * 3) & x); +} +struct A { + static const int InnerName = 42; +}; +int main() { + f1<A>(0); + f2<A>(0); + f3<A>(0); + return f4<A>(0); +} +} // namespace PR8446_3 |