diff options
| author | David Majnemer <david.majnemer@gmail.com> | 2013-09-03 22:36:22 +0000 |
|---|---|---|
| committer | David Majnemer <david.majnemer@gmail.com> | 2013-09-03 22:36:22 +0000 |
| commit | ad01851f32c626a3c6038aa997b5b416d6ad5cac (patch) | |
| tree | bc196567b6931884968e1c4c9909550d9e8e8afa /clang | |
| parent | e13ce180f257205ffb205d823bbfd0c8d7e4ea72 (diff) | |
| download | bcm5719-llvm-ad01851f32c626a3c6038aa997b5b416d6ad5cac.tar.gz bcm5719-llvm-ad01851f32c626a3c6038aa997b5b416d6ad5cac.zip | |
Parser: support Microsoft syntax for 'typename typedef'
Summary:
Transform the token sequence for:
typename typedef T U;
to:
typename T typedef U;
Raise a diagnostic when this happens but only if we succeeded handling
the typename.
Reviewers: rsmith, rnk
Reviewed By: rsmith
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1433
llvm-svn: 189867
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Parse/Parser.cpp | 19 | ||||
| -rw-r--r-- | clang/test/Parser/MicrosoftExtensions.cpp | 10 |
2 files changed, 27 insertions, 2 deletions
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 866572ceab9..378a239744f 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1480,6 +1480,23 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { && "Cannot be a type or scope token!"); if (Tok.is(tok::kw_typename)) { + // MSVC lets you do stuff like: + // typename typedef T_::D D; + // + // We will consume the typedef token here and put it back after we have + // parsed the first identifier, transforming it into something more like: + // typename T_::D typedef D; + if (getLangOpts().MicrosoftMode && NextToken().is(tok::kw_typedef)) { + Token TypedefToken; + PP.Lex(TypedefToken); + bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType); + PP.EnterToken(Tok); + Tok = TypedefToken; + if (!Result) + Diag(Tok.getLocation(), diag::warn_expected_qualified_after_typename); + return Result; + } + // Parse a C++ typename-specifier, e.g., "typename T::type". // // typename-specifier: @@ -1498,7 +1515,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { // Attempt to recover by skipping the invalid 'typename' if (Tok.is(tok::annot_decltype) || (!TryAnnotateTypeOrScopeToken(EnteringContext, NeedType) && - Tok.isAnnotation())) { + Tok.isAnnotation())) { unsigned DiagID = diag::err_expected_qualified_after_typename; // MS compatibility: MSVC permits using known types with typename. // e.g. "typedef typename T* pointer_type" diff --git a/clang/test/Parser/MicrosoftExtensions.cpp b/clang/test/Parser/MicrosoftExtensions.cpp index 1102fcbcec8..c2d749a288f 100644 --- a/clang/test/Parser/MicrosoftExtensions.cpp +++ b/clang/test/Parser/MicrosoftExtensions.cpp @@ -152,7 +152,9 @@ void missing_template_keyword(){ -class AAAA { }; +class AAAA { + typedef int D; +}; template <typename T> class SimpleTemplate {}; @@ -174,6 +176,12 @@ void redundant_typename() { int k = typename var;// expected-error {{expected a qualified name after 'typename'}} } +template <typename T> +struct TypenameWrongPlace { + typename typedef T::D D;// expected-warning {{expected a qualified name after 'typename'}} +}; + +extern TypenameWrongPlace<AAAA> PR16925; __interface MicrosoftInterface; __interface MicrosoftInterface { |

