From: Anders Carlsson Date: Wed, 11 Mar 2009 16:27:10 +0000 (+0000) Subject: Add parser support for static_assert. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=511d7aba3b12853fdb88729a0313b80a60eab8ad;p=clang Add parser support for static_assert. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66661 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticParseKinds.def b/include/clang/Basic/DiagnosticParseKinds.def index ab56766a0f..5b7b7771f8 100644 --- a/include/clang/Basic/DiagnosticParseKinds.def +++ b/include/clang/Basic/DiagnosticParseKinds.def @@ -142,6 +142,8 @@ DIAG(err_expected_semi_after_expr, ERROR, "expected ';' after expression") DIAG(err_expected_semi_after_method_proto, ERROR, "expected ';' after method prototype") +DIAG(err_expected_semi_after_static_assert, ERROR, + "expected ';' after static_assert") DIAG(err_expected_semi_for, ERROR, "expected ';' in 'for' statement specifier") DIAG(err_expected_colon_after, ERROR, diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 906e50e439..0a736f13a1 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -884,6 +884,15 @@ public: virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method) { } + virtual DeclTy *ActOnStaticAssertDeclaration(SourceLocation LParenLoc, + ExprArg AssertExpr, + SourceLocation CommaLoc, + ExprArg AssertMessageExpr, + SourceLocation RParenLoc) { + return 0; + } + + //===------------------------- C++ Expressions --------------------------===// /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 977e07fae6..6972c52a35 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -989,6 +989,7 @@ private: DeclTy *ParseUsingDirectiveOrDeclaration(unsigned Context); DeclTy *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc); DeclTy *ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc); + DeclTy *ParseStaticAssertDeclaration(); //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 5bf9783cfb..56a1decb59 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -225,6 +225,7 @@ void Parser::FuzzyParseMicrosoftDeclSpec() { /// [C++] namespace-definition /// [C++] using-directive /// [C++] using-declaration [TODO] +// [C++0x] static_assert-declaration /// others... [FIXME] /// Parser::DeclTy *Parser::ParseDeclaration(unsigned Context) { @@ -236,6 +237,8 @@ Parser::DeclTy *Parser::ParseDeclaration(unsigned Context) { return ParseNamespace(Context); case tok::kw_using: return ParseUsingDirectiveOrDeclaration(Context); + case tok::kw_static_assert: + return ParseStaticAssertDeclaration(); default: return ParseSimpleDeclaration(Context); } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index ef57737675..b21ac778ba 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -217,6 +217,55 @@ Parser::DeclTy *Parser::ParseUsingDeclaration(unsigned Context, return 0; } +/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion. +/// +/// static_assert-declaration: +/// static_assert ( constant-expression , string-literal ) ; +/// +Parser::DeclTy *Parser::ParseStaticAssertDeclaration() { + assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration"); + SourceLocation StaticAssertLoc = ConsumeToken(); + + if (Tok.isNot(tok::l_paren)) { + Diag(Tok, diag::err_expected_lparen); + return 0; + } + + SourceLocation LParenLoc = ConsumeParen(); + + OwningExprResult AssertExpr(ParseConstantExpression()); + if (AssertExpr.isInvalid()) { + SkipUntil(tok::semi); + return 0; + } + + if (Tok.isNot(tok::comma)) { + Diag(Tok, diag::err_expected_comma); + SkipUntil(tok::semi); + return 0; + } + + SourceLocation CommaLoc = ConsumeToken(); + + if (Tok.isNot(tok::string_literal)) { + Diag(Tok, diag::err_expected_string_literal); + SkipUntil(tok::semi); + return 0; + } + + OwningExprResult AssertMessage(ParseStringLiteralExpression()); + if (AssertMessage.isInvalid()) + return 0; + + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + + ExpectAndConsume(tok::semi, diag::err_expected_semi_after_static_assert); + + return Actions.ActOnStaticAssertDeclaration(LParenLoc, move(AssertExpr), + CommaLoc, move(AssertMessage), + RParenLoc); +} + /// ParseClassName - Parse a C++ class-name, which names a class. Note /// that we only check that the result names a type; semantic analysis /// will need to verify that the type names a class. The result is @@ -568,7 +617,7 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const /// function-definition ';'[opt] /// ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO] /// using-declaration [TODO] -/// [C++0x] static_assert-declaration [TODO] +/// [C++0x] static_assert-declaration /// template-declaration [TODO] /// [GNU] '__extension__' member-declaration /// @@ -588,6 +637,10 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const /// '=' constant-expression /// Parser::DeclTy *Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { + // static_assert-declaration + if (Tok.is(tok::kw_static_assert)) + return ParseStaticAssertDeclaration(); + // Handle: member-declaration ::= '__extension__' member-declaration if (Tok.is(tok::kw___extension__)) { // __extension__ silences extension warnings in the subexpression. diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 06c136df91..176529ce9c 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -29,7 +29,7 @@ using namespace clang; /// namespace-alias-definition /// using-declaration /// using-directive -/// [C++0x] static_assert-declaration [TODO] +/// [C++0x] static_assert-declaration /// /// asm-definition: /// 'asm' '(' string-literal ')' ';' @@ -46,9 +46,6 @@ using namespace clang; /// 'using' 'namespace' '::'[opt] nested-name-specifier[opt] /// namespace-name ';' /// -/// [C++0x] static_assert-declaration: [TODO] -/// [C++0x] static_assert '(' constant-expression ',' string-literal ')' ';' -/// bool Parser::isCXXDeclarationStatement() { switch (Tok.getKind()) { // asm-definition @@ -59,6 +56,9 @@ bool Parser::isCXXDeclarationStatement() { // using-directive case tok::kw_using: return true; + case tok::kw_static_assert: + // static_assert-declaration + return true; default: // simple-declaration return isCXXSimpleDeclaration(); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index b66b4f34ce..5666051fe5 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -408,6 +408,7 @@ Parser::DeclTy *Parser::ParseExternalDeclaration() { case tok::kw_typedef: case tok::kw_template: case tok::kw_export: // As in 'export template' + case tok::kw_static_assert: // A function definition cannot start with a these keywords. return ParseDeclaration(Declarator::FileContext); default: