]> granicus.if.org Git - clang/commitdiff
Add parser support for static_assert.
authorAnders Carlsson <andersca@mac.com>
Wed, 11 Mar 2009 16:27:10 +0000 (16:27 +0000)
committerAnders Carlsson <andersca@mac.com>
Wed, 11 Mar 2009 16:27:10 +0000 (16:27 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66661 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.def
include/clang/Parse/Action.h
include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseTentative.cpp
lib/Parse/Parser.cpp

index ab56766a0f953e842f98d63dbac716b900d27346..5b7b7771f824800d20dece3744b8ac6bccfc756d 100644 (file)
@@ -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,
index 906e50e4397d7b38f15bc33f76aabe671f5abdb3..0a736f13a12ff8564acec33f715d13ef6c1cc8d0 100644 (file)
@@ -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.
index 977e07fae6140a4d8af9c58a2f8b722f609804cc..6972c52a350a829de713b849fbe8ff8270c7da87 100644 (file)
@@ -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.
index 5bf9783cfbeebe705bae394aee0e109155a64bb8..56a1decb596d4f694ac09a01c947465ab87857ee 100644 (file)
@@ -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);
   }
index ef577376753520bd46a565f13c96c9208e0811bb..b21ac778ba5cecd2e42a4ae8efd82fa3cda9e416 100644 (file)
@@ -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.
index 06c136df91874bb4f53565058a27adb9a9e3b442..176529ce9c536bc4e4f4f16c0331f0e95867ae66 100644 (file)
@@ -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();
index b66b4f34ce5a81d5b8acb6670cbaa547ca299f77..5666051fe59639e1807942f8c8323a0f7911e3d7 100644 (file)
@@ -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: