]> granicus.if.org Git - clang/commitdiff
Parser support for C++ try-catch.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 21 Dec 2008 16:41:36 +0000 (16:41 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 21 Dec 2008 16:41:36 +0000 (16:41 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61312 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/PrintParserCallbacks.cpp
include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/Action.h
include/clang/Parse/DeclSpec.h
include/clang/Parse/Parser.h
lib/Parse/ParseStmt.cpp
lib/Sema/IdentifierResolver.cpp
lib/Sema/Sema.h
test/Parser/cxx-try.cpp [new file with mode: 0644]

index 02b33fcc0f7d099fc89098436a18118f337668bf..3f6562893c4e2e43d0a55f1bd8323a3db500dc2c 100644 (file)
@@ -404,7 +404,27 @@ namespace {
       llvm::cout << __FUNCTION__ << "\n";
       return 0;
     }
-  
+
+    // C++ Statements
+    virtual DeclTy *ActOnExceptionDeclarator(Scope *S, Declarator &D) {
+      llvm::cout << __FUNCTION__ << "\n";
+      return 0;
+    }
+
+    virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+                                                DeclTy *ExceptionDecl,
+                                                StmtArg HandlerBlock) {
+      llvm::cout << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
+                                              StmtArg TryBlock,
+                                              MultiStmtArg Handlers) {
+      llvm::cout << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
     //===--------------------------------------------------------------------===//
     // Expression Parsing Callbacks.
     //===--------------------------------------------------------------------===//
index df21d8d30e0798952d13cb3db4ec222cb390a19a..510f3ff916fd1523c6e77da969934fcde295308e 100644 (file)
@@ -605,6 +605,8 @@ DIAG(err_expected_member_or_base_name, ERROR,
      "expected class member or base class name")
 DIAG(ext_ellipsis_exception_spec, EXTENSION,
      "exception specification of '...' is a Microsoft extension")
+DIAG(err_expected_catch, ERROR,
+     "expected catch")
 
 /// C++ Templates
 DIAG(err_expected_template, ERROR,
index 3031206dd62c5625763a5befe8066ffa9c5fae2b..249f1224c7a368fbb0c1586cd3635d11cd219bd6 100644 (file)
@@ -478,7 +478,24 @@ public:
                                         StmtTy *SynchBody) {
     return 0;
   }
-  
+
+  // C++ Statements
+  virtual DeclTy *ActOnExceptionDeclarator(Scope *S, Declarator &D) {
+    return 0;
+  }
+
+  virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+                                              DeclTy *ExceptionDecl,
+                                              StmtArg HandlerBlock) {
+    return StmtEmpty();
+  }
+
+  virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
+                                            StmtArg TryBlock,
+                                            MultiStmtArg Handlers) {
+    return StmtEmpty();
+  }
+
   //===--------------------------------------------------------------------===//
   // Expression Parsing Callbacks.
   //===--------------------------------------------------------------------===//
index 4a97fd60ed2fccfd081ba1adf42aed963314cac2..8b2033bfbe0b26d44349eb7049e955aa7bc55c85 100644 (file)
@@ -646,7 +646,8 @@ public:
     BlockContext,        // Declaration within a block in a function.
     ForContext,          // Declaration within first part of a for loop.
     ConditionContext,    // Condition declaration in a C++ if/switch/while/for.
-    TemplateParamContext // Within a template parameter list.
+    TemplateParamContext,// Within a template parameter list.
+    CXXCatchContext      // C++ catch exception-declaration
   };
 
   /// DeclaratorKind - The kind of declarator this represents.
@@ -762,7 +763,7 @@ public:
   /// parameter lists.
   bool mayOmitIdentifier() const {
     return Context == TypeNameContext || Context == PrototypeContext ||
-           Context == TemplateParamContext;
+           Context == TemplateParamContext || Context == CXXCatchContext;
   }
 
   /// mayHaveIdentifier - Return true if the identifier is either optional or
index df6eca64325f8bacd5794abaab23c33fd5b636eb..fb1ebcf36e81903e56f8b75bd25707b06bc0d25a 100644 (file)
@@ -724,13 +724,23 @@ private:
   OwningStmtResult ParseReturnStatement();
   OwningStmtResult ParseAsmStatement(bool &msAsm);
   OwningStmtResult FuzzyParseMicrosoftAsmStatement();
+  bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
+                           llvm::SmallVectorImpl<ExprTy*> &Constraints,
+                           llvm::SmallVectorImpl<ExprTy*> &Exprs);
+
+  //===--------------------------------------------------------------------===//
+  // C++ 6: Statements and Blocks
+
+  OwningStmtResult ParseCXXTryBlock();
+  OwningStmtResult ParseCXXCatchBlock();
+
+  //===--------------------------------------------------------------------===//
+  // Objective-C Statements
+
   OwningStmtResult ParseObjCAtStatement(SourceLocation atLoc);
   OwningStmtResult ParseObjCTryStmt(SourceLocation atLoc);
   OwningStmtResult ParseObjCThrowStmt(SourceLocation atLoc);
   OwningStmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
-  bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
-                           llvm::SmallVectorImpl<ExprTy*> &Constraints,
-                           llvm::SmallVectorImpl<ExprTy*> &Exprs);
 
 
   //===--------------------------------------------------------------------===//
index c605bf235221af4c5ead4e35e7cb21936a454d55..81a9765555dad3fd4011bcab03cf3b20686e2074 100644 (file)
@@ -38,6 +38,7 @@ using namespace clang;
 ///         iteration-statement
 ///         jump-statement
 /// [C++]   declaration-statement
+/// [C++]   try-block
 /// [OBC]   objc-throw-statement
 /// [OBC]   objc-try-catch-statement
 /// [OBC]   objc-synchronized-statement
@@ -161,7 +162,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
     SemiError = "return statement";
     break;
 
-  case tok::kw_asm:
+  case tok::kw_asm: {
     bool msAsm = false;
     Res = ParseAsmStatement(msAsm);
     if (msAsm) return move(Res);
@@ -169,6 +170,10 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
     break;
   }
 
+  case tok::kw_try:                 // C++ 15: try-block
+    return ParseCXXTryBlock();
+  }
+
   // If we reached this code, the statement must end in a semicolon.
   if (Tok.is(tok::semi)) {
     ConsumeToken();
@@ -1243,3 +1248,89 @@ Parser::DeclTy *Parser::ParseFunctionStatementBody(DeclTy *Decl,
 
   return Actions.ActOnFinishFunctionBody(Decl, move_convert(FnBody));
 }
+
+/// ParseCXXTryBlock - Parse a C++ try-block.
+///
+///       try-block:
+///         'try' compound-statement handler-seq
+///
+///       handler-seq:
+///         handler handler-seq[opt]
+///
+Parser::OwningStmtResult Parser::ParseCXXTryBlock() {
+  assert(Tok.is(tok::kw_try) && "Expected 'try'");
+
+  SourceLocation TryLoc = ConsumeToken();
+  if (Tok.isNot(tok::l_brace))
+    return StmtError(Diag(Tok, diag::err_expected_lbrace));
+  OwningStmtResult TryBlock(ParseCompoundStatement());
+  if (TryBlock.isInvalid())
+    return move(TryBlock);
+
+  StmtVector Handlers(Actions);
+  if (Tok.isNot(tok::kw_catch))
+    return StmtError(Diag(Tok, diag::err_expected_catch));
+  while (Tok.is(tok::kw_catch)) {
+    OwningStmtResult Handler(ParseCXXCatchBlock());
+    if (!Handler.isInvalid())
+      Handlers.push_back(Handler.release());
+  }
+  // Don't bother creating the full statement if we don't have any usable
+  // handlers.
+  if (Handlers.empty())
+    return StmtError();
+
+  return Actions.ActOnCXXTryBlock(TryLoc, move_convert(TryBlock),
+                                  move_convert(Handlers));
+}
+
+/// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
+///
+///       handler:
+///         'catch' '(' exception-declaration ')' compound-statement
+///
+///       exception-declaration:
+///         type-specifier-seq declarator
+///         type-specifier-seq abstract-declarator
+///         type-specifier-seq
+///         '...'
+///
+Parser::OwningStmtResult Parser::ParseCXXCatchBlock() {
+  assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
+
+  SourceLocation CatchLoc = ConsumeToken();
+
+  SourceLocation LParenLoc = Tok.getLocation();
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+    return StmtError();
+
+  // C++ 3.3.2p3:
+  // The name in a catch exception-declaration is local to the handler and
+  // shall not be redeclared in the outermost block of the handler.
+  ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope);
+
+  // exception-declaration is equivalent to '...' or a parameter-declaration
+  // without default arguments.
+  DeclTy *ExceptionDecl = 0;
+  if (Tok.isNot(tok::ellipsis)) {
+    DeclSpec DS;
+    ParseDeclarationSpecifiers(DS);
+    Declarator ExDecl(DS, Declarator::CXXCatchContext);
+    ParseDeclarator(ExDecl);
+    ExceptionDecl = Actions.ActOnExceptionDeclarator(CurScope, ExDecl);
+  } else
+    ConsumeToken();
+
+  if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
+    return StmtError();
+
+  if (Tok.isNot(tok::l_brace))
+    return StmtError(Diag(Tok, diag::err_expected_lbrace));
+
+  OwningStmtResult Block(ParseCompoundStatement());
+  if (Block.isInvalid())
+    return move(Block);
+
+  return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl,
+                                    move_convert(Block));
+}
index 4441503528ad96cb067e47908bac4f2aa1a90487..027beede49124f3076af45c5115d03eea702c3d1 100644 (file)
@@ -151,6 +151,10 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
     if (S->isDeclScope(D))
       return true;
     if (LangOpt.CPlusPlus) {
+      // C++ 3.3.2p3:
+      // The name declared in a catch exception-declaration is local to the
+      // handler and shall not be redeclared in the outermost block of the
+      // handler.
       // C++ 3.3.2p4:
       // Names declared in the for-init-statement, and in the condition of if,
       // while, for, and switch statements are local to the if, while, for, or
index e5146a23bb5a5086cbd02952ac32ec4b12495feb..b620b70be07e416800ec27257f6f1e43ae9855fb 100644 (file)
@@ -631,7 +631,15 @@ public:
   virtual StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, 
                                                  ExprTy *SynchExpr, 
                                                  StmtTy *SynchBody);
-  
+
+  //virtual DeclTy *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+  //virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+  //                                            DeclTy *ExceptionDecl,
+  //                                            StmtArg HandlerBlock);
+  //virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
+  //                                          StmtArg TryBlock,
+  //                                          MultiStmtArg Handlers);
+
   //===--------------------------------------------------------------------===//
   // Expression Parsing Callbacks: SemaExpr.cpp.
 
diff --git a/test/Parser/cxx-try.cpp b/test/Parser/cxx-try.cpp
new file mode 100644 (file)
index 0000000..642c8f6
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: clang -fsyntax-only -verify %s
+
+void f()
+{
+  try {
+    ;
+  } catch(int i) {
+    ;
+  } catch(...) {
+  }
+}
+
+void g()
+{
+  try; // expected-error {{expected '{'}}
+
+  try {}
+  catch; // expected-error {{expected '('}}
+
+  try {}
+  catch (...); // expected-error {{expected '{'}}
+
+  try {}
+  catch {} // expected-error {{expected '('}}
+}