summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2013-09-03 22:36:22 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2013-09-03 22:36:22 +0000
commitad01851f32c626a3c6038aa997b5b416d6ad5cac (patch)
treebc196567b6931884968e1c4c9909550d9e8e8afa /clang
parente13ce180f257205ffb205d823bbfd0c8d7e4ea72 (diff)
downloadbcm5719-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.cpp19
-rw-r--r--clang/test/Parser/MicrosoftExtensions.cpp10
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 {
OpenPOWER on IntegriCloud