mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 23:46:06 +00:00
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:
parent
e13ce180f2
commit
ad01851f32
@ -1480,6 +1480,23 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
|
|||||||
&& "Cannot be a type or scope token!");
|
&& "Cannot be a type or scope token!");
|
||||||
|
|
||||||
if (Tok.is(tok::kw_typename)) {
|
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".
|
// Parse a C++ typename-specifier, e.g., "typename T::type".
|
||||||
//
|
//
|
||||||
// typename-specifier:
|
// typename-specifier:
|
||||||
@ -1498,7 +1515,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
|
|||||||
// Attempt to recover by skipping the invalid 'typename'
|
// Attempt to recover by skipping the invalid 'typename'
|
||||||
if (Tok.is(tok::annot_decltype) ||
|
if (Tok.is(tok::annot_decltype) ||
|
||||||
(!TryAnnotateTypeOrScopeToken(EnteringContext, NeedType) &&
|
(!TryAnnotateTypeOrScopeToken(EnteringContext, NeedType) &&
|
||||||
Tok.isAnnotation())) {
|
Tok.isAnnotation())) {
|
||||||
unsigned DiagID = diag::err_expected_qualified_after_typename;
|
unsigned DiagID = diag::err_expected_qualified_after_typename;
|
||||||
// MS compatibility: MSVC permits using known types with typename.
|
// MS compatibility: MSVC permits using known types with typename.
|
||||||
// e.g. "typedef typename T* pointer_type"
|
// e.g. "typedef typename T* pointer_type"
|
||||||
|
@ -152,7 +152,9 @@ void missing_template_keyword(){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AAAA { };
|
class AAAA {
|
||||||
|
typedef int D;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class SimpleTemplate {};
|
class SimpleTemplate {};
|
||||||
@ -174,6 +176,12 @@ void redundant_typename() {
|
|||||||
int k = typename var;// expected-error {{expected a qualified name after '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;
|
||||||
__interface MicrosoftInterface {
|
__interface MicrosoftInterface {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user