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
This commit is contained in:
David Majnemer 2013-09-03 22:36:22 +00:00
parent e13ce180f2
commit ad01851f32
2 changed files with 27 additions and 2 deletions

View File

@ -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"

View File

@ -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 {