diff options
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 26 | ||||
-rw-r--r-- | test/Parser/cxx-typeof.cpp | 7 |
2 files changed, 29 insertions, 4 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index cd2dda2941..2a8ab3f8db 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1556,9 +1556,10 @@ void Parser::ParseBracketDeclarator(Declarator &D) { NumElements.Val, StartLoc)); } -/// [GNU] typeof-specifier: -/// typeof ( expressions ) -/// typeof ( type-name ) +/// [GNU] typeof-specifier: +/// typeof ( expressions ) +/// typeof ( type-name ) +/// [GNU/C++] typeof unary-expression /// void Parser::ParseTypeofSpecifier(DeclSpec &DS) { assert(Tok.is(tok::kw_typeof) && "Not a typeof specifier"); @@ -1566,9 +1567,26 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { SourceLocation StartLoc = ConsumeToken(); if (Tok.isNot(tok::l_paren)) { - Diag(Tok, diag::err_expected_lparen_after, BuiltinII->getName()); + if (!getLang().CPlusPlus) { + Diag(Tok, diag::err_expected_lparen_after, BuiltinII->getName()); + return; + } + + ExprResult Result = ParseCastExpression(true/*isUnaryExpression*/); + if (Result.isInvalid) + return; + + const char *PrevSpec = 0; + // Check for duplicate type specifiers. + if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec, + Result.Val)) + Diag(StartLoc, diag::err_invalid_decl_spec_combination, PrevSpec); + + // FIXME: Not accurate, the range gets one token more than it should. + DS.SetRangeEnd(Tok.getLocation()); return; } + SourceLocation LParenLoc = ConsumeParen(), RParenLoc; if (isTypeSpecifierQualifier()) { diff --git a/test/Parser/cxx-typeof.cpp b/test/Parser/cxx-typeof.cpp new file mode 100644 index 0000000000..7e09905d8f --- /dev/null +++ b/test/Parser/cxx-typeof.cpp @@ -0,0 +1,7 @@ +// RUN: clang -fsyntax-only -verify %s + +static void test() { + int *pi; + int x; + typeof pi[x] y; +} |