From 67ac9989e3ec53174b524ab8bc7d08185346cace Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Tue, 3 Sep 2013 22:36:22 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189867 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/Parser.cpp | 19 ++++++++++++++++++- test/Parser/MicrosoftExtensions.cpp | 10 +++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 866572ceab..378a239744 100644 --- a/lib/Parse/Parser.cpp +++ b/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/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp index 1102fcbcec..c2d749a288 100644 --- a/test/Parser/MicrosoftExtensions.cpp +++ b/test/Parser/MicrosoftExtensions.cpp @@ -152,7 +152,9 @@ void missing_template_keyword(){ -class AAAA { }; +class AAAA { + typedef int D; +}; template class SimpleTemplate {}; @@ -174,6 +176,12 @@ void redundant_typename() { int k = typename var;// expected-error {{expected a qualified name after 'typename'}} } +template +struct TypenameWrongPlace { + typename typedef T::D D;// expected-warning {{expected a qualified name after 'typename'}} +}; + +extern TypenameWrongPlace PR16925; __interface MicrosoftInterface; __interface MicrosoftInterface { -- 2.40.0