From f4163b8ba01cd1a4f5d91c83a3863939b7809375 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Sun, 14 Feb 2010 16:05:25 +0100 Subject: [PATCH] Added Objective-C @try block parsing. --- src/libs/cplusplus/ResolveExpression.cpp | 5 ++ src/libs/cplusplus/ResolveExpression.h | 1 + src/shared/cplusplus/AST.cpp | 61 +++++++++++++++- src/shared/cplusplus/AST.h | 92 ++++++++++++++++++++++++ src/shared/cplusplus/ASTClone.cpp | 49 +++++++++++++ src/shared/cplusplus/ASTMatch0.cpp | 32 +++++++++ src/shared/cplusplus/ASTMatcher.cpp | 87 ++++++++++++++++++++++ src/shared/cplusplus/ASTMatcher.h | 4 ++ src/shared/cplusplus/ASTVisit.cpp | 35 +++++++++ src/shared/cplusplus/ASTVisitor.h | 8 +++ src/shared/cplusplus/ASTfwd.h | 5 ++ src/shared/cplusplus/CheckExpression.cpp | 6 ++ src/shared/cplusplus/CheckExpression.h | 1 + src/shared/cplusplus/CheckStatement.cpp | 32 +++++++++ src/shared/cplusplus/CheckStatement.h | 3 + src/shared/cplusplus/Parser.cpp | 79 ++++++++++++++++++-- src/shared/cplusplus/Parser.h | 3 + tests/auto/cplusplus/ast/tst_ast.cpp | 20 +++++- 18 files changed, 515 insertions(+), 8 deletions(-) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 2425fef4226..e965c4053a9 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -322,6 +322,11 @@ bool ResolveExpression::visit(ThrowExpressionAST *) return false; } +bool ResolveExpression::visit(ObjCThrowExpressionAST *) +{ + return false; +} + bool ResolveExpression::visit(TypeIdAST *) { return false; diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index 3a367964223..25d1caefe5f 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -90,6 +90,7 @@ protected: virtual bool visit(NestedExpressionAST *ast); virtual bool visit(StringLiteralAST *ast); virtual bool visit(ThrowExpressionAST *ast); + virtual bool visit(ObjCThrowExpressionAST *ast); virtual bool visit(TypeIdAST *ast); virtual bool visit(UnaryExpressionAST *ast); virtual bool visit(CompoundLiteralAST *ast); diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 51f5ce0a5fc..40893f4ca59 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -1691,7 +1691,6 @@ unsigned ThisExpressionAST::lastToken() const return this_token + 1; } - unsigned ThrowExpressionAST::firstToken() const { return throw_token; @@ -1704,6 +1703,20 @@ unsigned ThrowExpressionAST::lastToken() const return throw_token + 1; } +unsigned ObjCThrowExpressionAST::firstToken() const +{ + return at_token; +} + +unsigned ObjCThrowExpressionAST::lastToken() const +{ + if (expression) + return expression->lastToken(); + if (throw_token) + return throw_token + 1; + return at_token + 1; +} + unsigned TranslationUnitAST::firstToken() const { if(declaration_list) @@ -2392,3 +2405,49 @@ unsigned ObjCSynchronizedStatementAST::lastToken() const if (synchronized_token) return synchronized_token + 1; return at_token + 1; } + +unsigned ObjCTryBlockStatementAST::firstToken() const +{ return at_token; } + +unsigned ObjCTryBlockStatementAST::lastToken() const +{ + if (finally_clause) + return finally_clause->lastToken(); + if (catch_clause_list) + return catch_clause_list->lastToken(); + if (statement) + return statement->lastToken(); + if (try_token) + return try_token + 1; + return at_token + 1; +} + +unsigned ObjCCatchClauseAST::firstToken() const +{ return at_token; } + +unsigned ObjCCatchClauseAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + if (rparen_token) + return rparen_token + 1; + if (exception_declaration) + return exception_declaration->lastToken(); + if (lparen_token) + return lparen_token + 1; + if (catch_token) + return catch_token + 1; + return at_token + 1; +} + +unsigned ObjCFinallyClauseAST::firstToken() const +{ return at_token; } + +unsigned ObjCFinallyClauseAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + if (finally_token) + return finally_token + 1; + return at_token + 1; +} diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index 76ec773226e..52498c7da54 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -218,11 +218,13 @@ public: virtual NewPlacementAST *asNewPlacement() { return 0; } virtual NewTypeIdAST *asNewTypeId() { return 0; } virtual NumericLiteralAST *asNumericLiteral() { return 0; } + virtual ObjCCatchClauseAST *asObjCCatchClause() { return 0; } virtual ObjCClassDeclarationAST *asObjCClassDeclaration() { return 0; } virtual ObjCClassForwardDeclarationAST *asObjCClassForwardDeclaration() { return 0; } virtual ObjCDynamicPropertiesDeclarationAST *asObjCDynamicPropertiesDeclaration() { return 0; } virtual ObjCEncodeExpressionAST *asObjCEncodeExpression() { return 0; } virtual ObjCFastEnumerationAST *asObjCFastEnumeration() { return 0; } + virtual ObjCFinallyClauseAST *asObjCFinallyClause() { return 0; } virtual ObjCInstanceVariablesDeclarationAST *asObjCInstanceVariablesDeclaration() { return 0; } virtual ObjCMessageArgumentAST *asObjCMessageArgument() { return 0; } virtual ObjCMessageArgumentDeclarationAST *asObjCMessageArgumentDeclaration() { return 0; } @@ -243,6 +245,8 @@ public: virtual ObjCSynchronizedStatementAST *asObjCSynchronizedStatement() { return 0; } virtual ObjCSynthesizedPropertiesDeclarationAST *asObjCSynthesizedPropertiesDeclaration() { return 0; } virtual ObjCSynthesizedPropertyAST *asObjCSynthesizedProperty() { return 0; } + virtual ObjCThrowExpressionAST *asObjCThrowExpression() { return 0; } + virtual ObjCTryBlockStatementAST *asObjCTryBlockStatement() { return 0; } virtual ObjCTypeNameAST *asObjCTypeName() { return 0; } virtual ObjCVisibilityDeclarationAST *asObjCVisibilityDeclaration() { return 0; } virtual OperatorAST *asOperator() { return 0; } @@ -2359,6 +2363,26 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +class CPLUSPLUS_EXPORT ObjCThrowExpressionAST: public ExpressionAST +{ +public: + unsigned at_token; + unsigned throw_token; + ExpressionAST *expression; + +public: + virtual ObjCThrowExpressionAST *asObjCThrowExpression() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ObjCThrowExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + class CPLUSPLUS_EXPORT TranslationUnitAST: public AST { public: @@ -3169,6 +3193,74 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +class CPLUSPLUS_EXPORT ObjCTryBlockStatementAST: public StatementAST +{ +public: + unsigned at_token; + unsigned try_token; + StatementAST *statement; + ObjCCatchClauseListAST *catch_clause_list; + ObjCFinallyClauseAST *finally_clause; + +public: + virtual ObjCTryBlockStatementAST *asObjCTryBlockStatement() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ObjCTryBlockStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CPLUSPLUS_EXPORT ObjCCatchClauseAST: public StatementAST +{ +public: + unsigned at_token; + unsigned catch_token; + unsigned lparen_token; + ExceptionDeclarationAST *exception_declaration; + unsigned rparen_token; + StatementAST *statement; + +public: // annotations + Block *symbol; + +public: + virtual ObjCCatchClauseAST *asObjCCatchClause() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ObjCCatchClauseAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CPLUSPLUS_EXPORT ObjCFinallyClauseAST: public StatementAST +{ +public: + unsigned at_token; + unsigned finally_token; + StatementAST *statement; + +public: + virtual ObjCFinallyClauseAST *asObjCFinallyClause() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ObjCFinallyClauseAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + } // end of namespace CPlusPlus diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index d4247ad1160..a909db03b7c 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -1108,6 +1108,16 @@ ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const return ast; } +ObjCThrowExpressionAST *ObjCThrowExpressionAST::clone(MemoryPool *pool) const +{ + ObjCThrowExpressionAST *ast = new (pool) ObjCThrowExpressionAST; + ast->at_token = at_token; + ast->throw_token = throw_token; + if (expression) + ast->expression = expression->clone(pool); + return ast; +} + TranslationUnitAST *TranslationUnitAST::clone(MemoryPool *pool) const { TranslationUnitAST *ast = new (pool) TranslationUnitAST; @@ -1564,3 +1574,42 @@ ObjCSynchronizedStatementAST *ObjCSynchronizedStatementAST::clone(MemoryPool *po return ast; } +ObjCTryBlockStatementAST *ObjCTryBlockStatementAST::clone(MemoryPool *pool) const +{ + ObjCTryBlockStatementAST *ast = new (pool) ObjCTryBlockStatementAST; + ast->at_token = at_token; + ast->try_token = try_token; + if (statement) + ast->statement = statement->clone(pool); + for (ObjCCatchClauseListAST *iter = catch_clause_list, **ast_iter = &ast->catch_clause_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) ObjCCatchClauseListAST((iter->value) ? iter->value->clone(pool) : 0); + if (finally_clause) + ast->finally_clause = finally_clause->clone(pool); + return ast; +} + +ObjCCatchClauseAST *ObjCCatchClauseAST::clone(MemoryPool *pool) const +{ + ObjCCatchClauseAST *ast = new (pool) ObjCCatchClauseAST; + ast->at_token = at_token; + ast->catch_token = catch_token; + ast->lparen_token = lparen_token; + if (exception_declaration) + ast->exception_declaration = exception_declaration->clone(pool); + ast->rparen_token = rparen_token; + if (statement) + ast->statement = statement->clone(pool); + return ast; +} + +ObjCFinallyClauseAST *ObjCFinallyClauseAST::clone(MemoryPool *pool) const +{ + ObjCFinallyClauseAST *ast = new (pool) ObjCFinallyClauseAST; + ast->at_token = at_token; + ast->finally_token = finally_token; + if (statement) + ast->statement = statement->clone(pool); + return ast; +} + diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp index a2fcf8e0b96..26a485a6c15 100644 --- a/src/shared/cplusplus/ASTMatch0.cpp +++ b/src/shared/cplusplus/ASTMatch0.cpp @@ -793,6 +793,14 @@ bool ThrowExpressionAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool ObjCThrowExpressionAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (ObjCThrowExpressionAST *_other = pattern->asObjCThrowExpression()) + return matcher->match(this, _other); + + return false; +} + bool TranslationUnitAST::match0(AST *pattern, ASTMatcher *matcher) { if (TranslationUnitAST *_other = pattern->asTranslationUnit()) @@ -1081,3 +1089,27 @@ bool ObjCSynchronizedStatementAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool ObjCTryBlockStatementAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (ObjCTryBlockStatementAST *_other = pattern->asObjCTryBlockStatement()) + return matcher->match(this, _other); + + return false; +} + +bool ObjCCatchClauseAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (ObjCCatchClauseAST *_other = pattern->asObjCCatchClause()) + return matcher->match(this, _other); + + return false; +} + +bool ObjCFinallyClauseAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (ObjCFinallyClauseAST *_other = pattern->asObjCFinallyClause()) + return matcher->match(this, _other); + + return false; +} + diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index 627fe3abf85..137b973e565 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -1848,6 +1848,23 @@ bool ASTMatcher::match(ThrowExpressionAST *node, ThrowExpressionAST *pattern) return true; } +bool ASTMatcher::match(ObjCThrowExpressionAST *node, ObjCThrowExpressionAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->at_token = node->at_token; + + pattern->throw_token = node->throw_token; + + if (! pattern->expression) + pattern->expression = node->expression; + else if (! AST::match(node->expression, pattern->expression, this)) + return false; + + return true; +} + bool ASTMatcher::match(TranslationUnitAST *node, TranslationUnitAST *pattern) { (void) node; @@ -2632,3 +2649,73 @@ bool ASTMatcher::match(ObjCSynchronizedStatementAST *node, ObjCSynchronizedState return true; } +bool ASTMatcher::match(ObjCTryBlockStatementAST *node, ObjCTryBlockStatementAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->at_token = node->at_token; + + pattern->try_token = node->try_token; + + if (! pattern->statement) + pattern->statement = node->statement; + else if (! AST::match(node->statement, pattern->statement, this)) + return false; + + if (! pattern->catch_clause_list) + pattern->catch_clause_list = node->catch_clause_list; + else if (! AST::match(node->catch_clause_list, pattern->catch_clause_list, this)) + return false; + + if (! pattern->finally_clause) + pattern->finally_clause = node->finally_clause; + else if (! AST::match(node->finally_clause, pattern->finally_clause, this)) + return false; + + return true; +} + +bool ASTMatcher::match(ObjCCatchClauseAST *node, ObjCCatchClauseAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->at_token = node->at_token; + + pattern->catch_token = node->catch_token; + + pattern->lparen_token = node->lparen_token; + + if (! pattern->exception_declaration) + pattern->exception_declaration = node->exception_declaration; + else if (! AST::match(node->exception_declaration, pattern->exception_declaration, this)) + return false; + + pattern->rparen_token = node->rparen_token; + + if (! pattern->statement) + pattern->statement = node->statement; + else if (! AST::match(node->statement, pattern->statement, this)) + return false; + + return true; +} + +bool ASTMatcher::match(ObjCFinallyClauseAST *node, ObjCFinallyClauseAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->at_token = node->at_token; + + pattern->finally_token = node->finally_token; + + if (! pattern->statement) + pattern->statement = node->statement; + else if (! AST::match(node->statement, pattern->statement, this)) + return false; + + return true; +} + diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h index c6466a4919f..38331077fb0 100644 --- a/src/shared/cplusplus/ASTMatcher.h +++ b/src/shared/cplusplus/ASTMatcher.h @@ -126,6 +126,7 @@ public: virtual bool match(TemplateTypeParameterAST *node, TemplateTypeParameterAST *pattern); virtual bool match(ThisExpressionAST *node, ThisExpressionAST *pattern); virtual bool match(ThrowExpressionAST *node, ThrowExpressionAST *pattern); + virtual bool match(ObjCThrowExpressionAST *node, ObjCThrowExpressionAST *pattern); virtual bool match(TranslationUnitAST *node, TranslationUnitAST *pattern); virtual bool match(TryBlockStatementAST *node, TryBlockStatementAST *pattern); virtual bool match(TypeConstructorCallAST *node, TypeConstructorCallAST *pattern); @@ -169,6 +170,9 @@ public: virtual bool match(ObjCDynamicPropertiesDeclarationAST *node, ObjCDynamicPropertiesDeclarationAST *pattern); virtual bool match(ObjCFastEnumerationAST *node, ObjCFastEnumerationAST *pattern); virtual bool match(ObjCSynchronizedStatementAST *node, ObjCSynchronizedStatementAST *pattern); + virtual bool match(ObjCTryBlockStatementAST *node, ObjCTryBlockStatementAST *pattern); + virtual bool match(ObjCCatchClauseAST *node, ObjCCatchClauseAST *pattern); + virtual bool match(ObjCFinallyClauseAST *node, ObjCFinallyClauseAST *pattern); }; } // end of namespace CPlusPlus diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index 8b53d99f7f3..6620551dfc8 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -831,6 +831,14 @@ void ThrowExpressionAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void ObjCThrowExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + visitor->endVisit(this); +} + void TranslationUnitAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { @@ -1147,3 +1155,30 @@ void ObjCSynchronizedStatementAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void ObjCTryBlockStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + accept(catch_clause_list, visitor); + accept(finally_clause, visitor); + } + visitor->endVisit(this); +} + +void ObjCCatchClauseAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(exception_declaration, visitor); + accept(statement, visitor); + } + visitor->endVisit(this); +} + +void ObjCFinallyClauseAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + } + visitor->endVisit(this); +} + diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index 72a3f4b736e..b07948f4127 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -235,6 +235,10 @@ public: virtual bool visit(ObjCDynamicPropertiesDeclarationAST *) { return true; } virtual bool visit(ObjCFastEnumerationAST *) { return true; } virtual bool visit(ObjCSynchronizedStatementAST *) { return true; } + virtual bool visit(ObjCTryBlockStatementAST *) { return true; } + virtual bool visit(ObjCCatchClauseAST *) { return true; } + virtual bool visit(ObjCFinallyClauseAST *) { return true; } + virtual bool visit(ObjCThrowExpressionAST *) { return true; } virtual void endVisit(AccessDeclarationAST *) { } virtual void endVisit(QtPropertyDeclarationAST *) { } @@ -369,6 +373,10 @@ public: virtual void endVisit(ObjCDynamicPropertiesDeclarationAST *) { } virtual void endVisit(ObjCFastEnumerationAST *) { } virtual void endVisit(ObjCSynchronizedStatementAST *) { } + virtual void endVisit(ObjCTryBlockStatementAST *) { } + virtual void endVisit(ObjCCatchClauseAST *) { } + virtual void endVisit(ObjCFinallyClauseAST *) { } + virtual void endVisit(ObjCThrowExpressionAST *) { } private: TranslationUnit *_translationUnit; diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index d2a1d317d81..97b74a0a02b 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -125,11 +125,13 @@ class NewInitializerAST; class NewPlacementAST; class NewTypeIdAST; class NumericLiteralAST; +class ObjCCatchClauseAST; class ObjCClassDeclarationAST; class ObjCClassForwardDeclarationAST; class ObjCDynamicPropertiesDeclarationAST; class ObjCEncodeExpressionAST; class ObjCFastEnumerationAST; +class ObjCFinallyClauseAST; class ObjCInstanceVariablesDeclarationAST; class ObjCMessageArgumentAST; class ObjCMessageArgumentDeclarationAST; @@ -150,6 +152,8 @@ class ObjCSelectorWithoutArgumentsAST; class ObjCSynchronizedStatementAST; class ObjCSynthesizedPropertiesDeclarationAST; class ObjCSynthesizedPropertyAST; +class ObjCThrowExpressionAST; +class ObjCTryBlockStatementAST; class ObjCTypeNameAST; class ObjCVisibilityDeclarationAST; class OperatorAST; @@ -224,6 +228,7 @@ typedef List ObjCSelectorArgumentListAST; typedef List ObjCPropertyAttributeListAST; typedef List ObjCMessageArgumentDeclarationListAST; typedef List ObjCSynthesizedPropertyListAST; +typedef List ObjCCatchClauseListAST; typedef ExpressionListAST TemplateArgumentListAST; diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp index 748fa9c9014..663f0c4f0bf 100644 --- a/src/shared/cplusplus/CheckExpression.cpp +++ b/src/shared/cplusplus/CheckExpression.cpp @@ -305,6 +305,12 @@ bool CheckExpression::visit(ThrowExpressionAST *ast) return false; } +bool CheckExpression::visit(ObjCThrowExpressionAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + bool CheckExpression::visit(TypeIdAST *ast) { FullySpecifiedType typeSpecTy = semantic()->check(ast->type_specifier_list, _scope); diff --git a/src/shared/cplusplus/CheckExpression.h b/src/shared/cplusplus/CheckExpression.h index 9cc1722d7c2..25b0a470240 100644 --- a/src/shared/cplusplus/CheckExpression.h +++ b/src/shared/cplusplus/CheckExpression.h @@ -90,6 +90,7 @@ protected: virtual bool visit(NestedExpressionAST *ast); virtual bool visit(StringLiteralAST *ast); virtual bool visit(ThrowExpressionAST *ast); + virtual bool visit(ObjCThrowExpressionAST *ast); virtual bool visit(TypeIdAST *ast); virtual bool visit(UnaryExpressionAST *ast); virtual bool visit(QtMethodAST *ast); diff --git a/src/shared/cplusplus/CheckStatement.cpp b/src/shared/cplusplus/CheckStatement.cpp index 26e4e7c835a..dac65892ecf 100644 --- a/src/shared/cplusplus/CheckStatement.cpp +++ b/src/shared/cplusplus/CheckStatement.cpp @@ -379,3 +379,35 @@ bool CheckStatement::visit(QtMemberDeclarationAST *ast) _exprType = FullySpecifiedType(); return false; } + +bool CheckStatement::visit(ObjCTryBlockStatementAST *ast) +{ + semantic()->check(ast->statement, _scope); + for (ObjCCatchClauseListAST *it = ast->catch_clause_list; it; it = it->next) { + semantic()->check(it->value, _scope); + } + _exprType = FullySpecifiedType(); + return false; +} + +bool CheckStatement::visit(ObjCCatchClauseAST *ast) +{ + Block *block = control()->newBlock(ast->at_token); + block->setStartOffset(tokenAt(ast->firstToken()).offset); + block->setEndOffset(tokenAt(ast->lastToken()).offset); + ast->symbol = block; + _scope->enterSymbol(block); + Scope *previousScope = switchScope(block->members()); + semantic()->check(ast->exception_declaration, _scope); + semantic()->check(ast->statement, _scope); + (void) switchScope(previousScope); + _exprType = FullySpecifiedType(); + return false; +} + +bool CheckStatement::visit(ObjCFinallyClauseAST *ast) +{ + semantic()->check(ast->statement, _scope); + _exprType = FullySpecifiedType(); + return false; +} diff --git a/src/shared/cplusplus/CheckStatement.h b/src/shared/cplusplus/CheckStatement.h index dc8447f37e4..dd77d5ba87c 100644 --- a/src/shared/cplusplus/CheckStatement.h +++ b/src/shared/cplusplus/CheckStatement.h @@ -90,6 +90,9 @@ protected: virtual bool visit(CatchClauseAST *ast); virtual bool visit(WhileStatementAST *ast); virtual bool visit(QtMemberDeclarationAST *ast); + virtual bool visit(ObjCTryBlockStatementAST *ast); + virtual bool visit(ObjCCatchClauseAST *ast); + virtual bool visit(ObjCFinallyClauseAST *ast); bool forEachFastEnum(unsigned firstToken, unsigned lastToken, diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index a6b6e0b1c81..62354e33046 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -362,8 +362,17 @@ bool Parser::skipUntilStatement() return true; case T_AT: - if (objCEnabled() && LA(2) == T_SYNCHRONIZED) - return true; + if (objCEnabled()) { + switch (LA(2)) { + case T_SYNCHRONIZED: + case T_TRY: + case T_THROW: + return true; + default: { + // INTENTIONAL FALL-THROUGH! + } + } + } default: consumeToken(); @@ -2442,8 +2451,12 @@ bool Parser::parseStatement(StatementAST *&node) } return true; case T_AT: - return objCEnabled() && LA(2) == T_SYNCHRONIZED - && parseObjCSynchronizedStatement(node); + if (objCEnabled()) { + if (LA(2) == T_SYNCHRONIZED) + return parseObjCSynchronizedStatement(node); + if (LA(2) == T_TRY) + return parseObjCTryBlockStatement(node); + } default: if (LA() == T_IDENTIFIER && LA(2) == T_COLON) @@ -3552,7 +3565,7 @@ bool Parser::parseObjCStringLiteral(ExpressionAST *&node) if (LA() != T_AT || LA(2) != T_STRING_LITERAL) return false; - StringLiteralAST **ast = 0; + StringLiteralAST **ast = reinterpret_cast (&node); while (LA()) { if (LA() == T_AT && LA(2) == T_STRING_LITERAL) { *ast = new (_pool) StringLiteralAST; @@ -4503,6 +4516,14 @@ bool Parser::parseThrowExpression(ExpressionAST *&node) node = ast; return true; } + if (LA() == T_AT && LA(2) == T_THROW) { + ObjCThrowExpressionAST *ast = new (_pool) ObjCThrowExpressionAST; + ast->at_token = consumeToken(); + ast->throw_token = consumeToken(); + parseAssignmentExpression(ast->expression); + node = ast; + return true; + } return false; } @@ -5373,3 +5394,51 @@ int Parser::peekAtQtContextKeyword() const const Identifier *id = tok().identifier; return classifyQtContextKeyword(id->chars(), id->size()); } + +bool Parser::parseObjCTryBlockStatement(StatementAST *&node) +{ + DEBUG_THIS_RULE(); + if (LA() == T_AT && LA(2) == T_TRY) { + ObjCTryBlockStatementAST *ast = new (_pool) ObjCTryBlockStatementAST; + ast->at_token = consumeToken(); + ast->try_token = consumeToken(); + parseCompoundStatement(ast->statement); + ObjCCatchClauseListAST **catch_clause_ptr = &ast->catch_clause_list; + while (parseObjCCatchClause(*catch_clause_ptr)) + catch_clause_ptr = &(*catch_clause_ptr)->next; + parseObjCFinallyClause(ast->finally_clause); + node = ast; + return true; + } + return false; +} + +bool Parser::parseObjCCatchClause(ObjCCatchClauseListAST *&node) +{ + DEBUG_THIS_RULE(); + if (LA() == T_AT && LA(2) == T_CATCH) { + ObjCCatchClauseAST *ast = new (_pool) ObjCCatchClauseAST; + ast->at_token = consumeToken(); + ast->catch_token = consumeToken(); + match(T_LPAREN, &ast->lparen_token); + parseExceptionDeclaration(ast->exception_declaration); + match(T_RPAREN, &ast->rparen_token); + parseCompoundStatement(ast->statement); + node = new (_pool) ObjCCatchClauseListAST(ast); + return true; + } + return false; +} + +bool Parser::parseObjCFinallyClause(ObjCFinallyClauseAST *&node) +{ + DEBUG_THIS_RULE(); + if (LA() == T_AT && LA(2) == T_FINALLY) { + node = new (_pool) ObjCFinallyClauseAST; + node->at_token = consumeToken(); + node->finally_token = consumeToken(); + parseCompoundStatement(node->statement); + return true; + } + return false; +} diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index ab4449ee743..4be9bdd903f 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -251,6 +251,9 @@ public: bool parseObjCTypeQualifiers(unsigned &type_qualifier); bool peekAtObjCContextKeyword(int kind); bool parseObjCContextKeyword(int kind, unsigned &in_token); + bool parseObjCTryBlockStatement(StatementAST *&node); + bool parseObjCCatchClause(ObjCCatchClauseListAST *&node); + bool parseObjCFinallyClause(ObjCFinallyClauseAST *&node); bool lookAtObjCSelector() const; diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 14e82b6e8b0..a97b3b29a81 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -79,6 +79,7 @@ private slots: void objc_protocol_forward_declaration_1(); void objc_protocol_definition_1(); void objc_method_attributes_1(); + void objc_exceptions(); // expressions with (square) brackets void normal_array_access(); @@ -784,6 +785,22 @@ void tst_AST::objc_method_attributes_1() QCOMPARE(unit->spell(unavailableAttr->identifier_token), "unavailable"); } +void tst_AST::objc_exceptions() +{ + const char *src = "\n" + "@try {@throw [NSException exceptionWithName:@\"FileNotFoundException\" reason:@\"Disk went wild.\" userInfo:nil];}\n" + "@catch (FileNotFoundException *e) { [e raise]; }\n" + "@catch (NSException *e) { @throw; }\n" + "@catch(...){}\n" + "@finally { }\n" + ; + + QSharedPointer unit(parseStatement(src)); + + AST *ast = unit->ast(); + QVERIFY(ast); +} + void tst_AST::normal_array_access() { QSharedPointer unit(parseDeclaration("\n" @@ -967,8 +984,7 @@ void tst_AST::objc_msg_send_expression_without_selector() "int f() {\n" " NSObject *obj = [[[NSObject alloc] init] autorelease];\n" " return [obj];\n" - "}", - true)); + "}", true)); AST *ast = unit->ast(); QVERIFY(ast);