From 6ca5f5f5f886449f88d1ff7085f640c46bbc8fb2 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@nokia.com> Date: Thu, 4 Feb 2010 16:31:29 +0100 Subject: [PATCH] Added semantic checks for compound expressions. --- src/libs/cplusplus/ResolveExpression.cpp | 6 ++- src/shared/cplusplus/AST.h | 17 +++++--- src/shared/cplusplus/CheckExpression.cpp | 5 ++- src/shared/cplusplus/CheckStatement.cpp | 51 +++++++++++++++++------- src/shared/cplusplus/CheckStatement.h | 8 +++- src/shared/cplusplus/Parser.cpp | 8 ++++ src/shared/cplusplus/Semantic.cpp | 4 +- src/shared/cplusplus/Semantic.h | 2 +- 8 files changed, 74 insertions(+), 27 deletions(-) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index c6f8bd4b5b8..2425fef4226 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -295,7 +295,11 @@ bool ResolveExpression::visit(ThisExpressionAST *) bool ResolveExpression::visit(CompoundExpressionAST *ast) { - return true; // ### + CompoundStatementAST *cStmt = ast->compoundStatement; + if (cStmt && cStmt->statement_list) { + accept(cStmt->statement_list->lastValue()); + } + return false; } bool ResolveExpression::visit(NestedExpressionAST *ast) diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index c719f311608..1766891cd7b 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -80,6 +80,17 @@ public: } unsigned lastToken() const + { + _Tp lv = lastValue(); + + if (lv) + return lv->lastToken(); + + // ### assert(0); + return 0; + } + + _Tp lastValue() const { _Tp lastValue = 0; @@ -88,11 +99,7 @@ public: lastValue = it->value; } - if (lastValue) - return lastValue->lastToken(); - - // ### assert(0); - return 0; + return lastValue; } _Tp value; diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp index c971204c2e4..748fa9c9014 100644 --- a/src/shared/cplusplus/CheckExpression.cpp +++ b/src/shared/cplusplus/CheckExpression.cpp @@ -289,12 +289,13 @@ bool CheckExpression::visit(ThisExpressionAST *) bool CheckExpression::visit(CompoundExpressionAST *ast) { - return true; // ### + _fullySpecifiedType = semantic()->check(ast->compoundStatement, _scope); + return false; } bool CheckExpression::visit(NestedExpressionAST *ast) { - FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + _fullySpecifiedType = semantic()->check(ast->expression, _scope); return false; } diff --git a/src/shared/cplusplus/CheckStatement.cpp b/src/shared/cplusplus/CheckStatement.cpp index 41ccdf1c27a..26e4e7c835a 100644 --- a/src/shared/cplusplus/CheckStatement.cpp +++ b/src/shared/cplusplus/CheckStatement.cpp @@ -69,13 +69,22 @@ CheckStatement::CheckStatement(Semantic *semantic) CheckStatement::~CheckStatement() { } -void CheckStatement::check(StatementAST *statement, Scope *scope) +FullySpecifiedType CheckStatement::check(StatementAST *statement, Scope *scope) { + FullySpecifiedType previousExprType = switchExprType(FullySpecifiedType()); Scope *previousScope = switchScope(scope); StatementAST *previousStatement = switchStatement(statement); accept(statement); (void) switchStatement(previousStatement); (void) switchScope(previousScope); + return switchExprType(previousExprType); +} + +FullySpecifiedType CheckStatement::switchExprType(const FullySpecifiedType &type) +{ + const FullySpecifiedType &previousExprType = _exprType; + _exprType = type; + return previousExprType; } StatementAST *CheckStatement::switchStatement(StatementAST *statement) @@ -94,8 +103,8 @@ Scope *CheckStatement::switchScope(Scope *scope) bool CheckStatement::visit(CaseStatementAST *ast) { - FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); - semantic()->check(ast->statement, _scope); + (void) semantic()->check(ast->expression, _scope); + _exprType = semantic()->check(ast->statement, _scope); return false; } @@ -110,7 +119,7 @@ bool CheckStatement::visit(CompoundStatementAST *ast) StatementAST *previousStatement = 0; for (StatementListAST *it = ast->statement_list; it; it = it->next) { StatementAST *statement = it->value; - semantic()->check(statement, _scope); + _exprType = semantic()->check(statement, _scope); if (statement && previousStatement) { ExpressionStatementAST *expressionStatement = statement->asExpressionStatement(); @@ -128,13 +137,15 @@ bool CheckStatement::visit(CompoundStatementAST *ast) bool CheckStatement::visit(DeclarationStatementAST *ast) { semantic()->check(ast->declaration, _scope); + _exprType = FullySpecifiedType(); return false; } bool CheckStatement::visit(DoStatementAST *ast) { semantic()->check(ast->statement, _scope); - FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + (void) semantic()->check(ast->expression, _scope); + _exprType = FullySpecifiedType(); return false; } @@ -142,16 +153,18 @@ bool CheckStatement::visit(ExpressionOrDeclarationStatementAST *ast) { // translationUnit()->warning(ast->firstToken(), // "ambiguous expression or declaration statement"); - if (ast->declaration) + if (ast->declaration) { semantic()->check(ast->declaration, _scope); - else - semantic()->check(ast->expression, _scope); + _exprType = FullySpecifiedType(); + } else { + _exprType = semantic()->check(ast->expression, _scope); + } return false; } bool CheckStatement::visit(ExpressionStatementAST *ast) { - FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + _exprType = semantic()->check(ast->expression, _scope); return false; } @@ -181,13 +194,13 @@ bool CheckStatement::forEachFastEnum(unsigned firstToken, decl->setType(ty); _scope->enterSymbol(decl); } else { - FullySpecifiedType exprTy = semantic()->check(initializer, _scope); - (void) exprTy; + (void) semantic()->check(initializer, _scope); } - FullySpecifiedType exprTy = semantic()->check(expression, _scope); + (void) semantic()->check(expression, _scope); semantic()->check(statement, _scope); (void) switchScope(previousScope); + _exprType = FullySpecifiedType(); return false; } @@ -228,6 +241,7 @@ bool CheckStatement::visit(ForStatementAST *ast) FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); semantic()->check(ast->statement, _scope); (void) switchScope(previousScope); + _exprType = FullySpecifiedType(); return false; } @@ -243,33 +257,38 @@ bool CheckStatement::visit(IfStatementAST *ast) semantic()->check(ast->statement, _scope); semantic()->check(ast->else_statement, _scope); (void) switchScope(previousScope); + _exprType = FullySpecifiedType(); return false; } bool CheckStatement::visit(LabeledStatementAST *ast) { semantic()->check(ast->statement, _scope); + _exprType = FullySpecifiedType(); return false; } bool CheckStatement::visit(BreakStatementAST *) { + _exprType = FullySpecifiedType(); return false; } bool CheckStatement::visit(ContinueStatementAST *) { + _exprType = FullySpecifiedType(); return false; } bool CheckStatement::visit(GotoStatementAST *) { + _exprType = FullySpecifiedType(); return false; } bool CheckStatement::visit(ReturnStatementAST *ast) { - FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + _exprType = semantic()->check(ast->expression, _scope); return false; } @@ -284,6 +303,7 @@ bool CheckStatement::visit(SwitchStatementAST *ast) FullySpecifiedType condTy = semantic()->check(ast->condition, _scope); semantic()->check(ast->statement, _scope); (void) switchScope(previousScope); + _exprType = FullySpecifiedType(); return false; } @@ -293,6 +313,7 @@ bool CheckStatement::visit(TryBlockStatementAST *ast) for (CatchClauseListAST *it = ast->catch_clause_list; it; it = it->next) { semantic()->check(it->value, _scope); } + _exprType = FullySpecifiedType(); return false; } @@ -307,6 +328,7 @@ bool CheckStatement::visit(CatchClauseAST *ast) semantic()->check(ast->exception_declaration, _scope); semantic()->check(ast->statement, _scope); (void) switchScope(previousScope); + _exprType = FullySpecifiedType(); return false; } @@ -321,6 +343,7 @@ bool CheckStatement::visit(WhileStatementAST *ast) FullySpecifiedType condTy = semantic()->check(ast->condition, _scope); semantic()->check(ast->statement, _scope); (void) switchScope(previousScope); + _exprType = FullySpecifiedType(); return false; } @@ -353,6 +376,6 @@ bool CheckStatement::visit(QtMemberDeclarationAST *ast) symbol->setType(control()->pointerType(declTy)); _scope->enterSymbol(symbol); - + _exprType = FullySpecifiedType(); return false; } diff --git a/src/shared/cplusplus/CheckStatement.h b/src/shared/cplusplus/CheckStatement.h index 5c1b1ff02d8..dc8447f37e4 100644 --- a/src/shared/cplusplus/CheckStatement.h +++ b/src/shared/cplusplus/CheckStatement.h @@ -50,9 +50,9 @@ #define CPLUSPLUS_CHECKSTATEMENT_H #include "CPlusPlusForwardDeclarations.h" +#include "FullySpecifiedType.h" #include "SemanticCheck.h" - namespace CPlusPlus { class CPLUSPLUS_EXPORT CheckStatement: public SemanticCheck @@ -61,9 +61,10 @@ public: CheckStatement(Semantic *semantic); virtual ~CheckStatement(); - void check(StatementAST *statement, Scope *scope); + FullySpecifiedType check(StatementAST *statement, Scope *scope); protected: + FullySpecifiedType switchExprType(const FullySpecifiedType &type); StatementAST *switchStatement(StatementAST *statement); Scope *switchScope(Scope *scope); @@ -98,9 +99,12 @@ protected: ExpressionAST *expression, StatementAST *statement, Block *&symbol); + FullySpecifiedType checkCompoundStmt(CompoundStatementAST *stmt); + private: StatementAST *_statement; Scope *_scope; + FullySpecifiedType _exprType; }; } // end of namespace CPlusPlus diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 84a92a186aa..864ec779ab4 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -3446,6 +3446,14 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node) ast->compoundStatement = statement->asCompoundStatement(); match(T_RPAREN, &ast->rparen_token); node = ast; + if (ast->compoundStatement && ast->compoundStatement->statement_list) { + // check that the last statement is an expression-statement + StatementAST *lastStmt = ast->compoundStatement->statement_list->lastValue(); + if (!lastStmt || ! ast->asExpressionStatement()) + _translationUnit->error(cursor(), + "expected an expression statement before token `%s'", + tok().spell()); + } return true; } else { return parseNestedExpression(node); diff --git a/src/shared/cplusplus/Semantic.cpp b/src/shared/cplusplus/Semantic.cpp index 57ac5fe99f3..d8d6d6617e9 100644 --- a/src/shared/cplusplus/Semantic.cpp +++ b/src/shared/cplusplus/Semantic.cpp @@ -151,8 +151,8 @@ void Semantic::check(ObjCMessageArgumentDeclarationAST *arg, Scope *scope) FullySpecifiedType Semantic::check(ExpressionAST *expression, Scope *scope) { return d->checkExpression->check(expression, scope); } -void Semantic::check(StatementAST *statement, Scope *scope) -{ d->checkStatement->check(statement, scope); } +FullySpecifiedType Semantic::check(StatementAST *statement, Scope *scope) +{ return d->checkStatement->check(statement, scope); } const Name *Semantic::check(NameAST *name, Scope *scope) { return d->checkName->check(name, scope); } diff --git a/src/shared/cplusplus/Semantic.h b/src/shared/cplusplus/Semantic.h index 98c64505203..60f82b892e0 100644 --- a/src/shared/cplusplus/Semantic.h +++ b/src/shared/cplusplus/Semantic.h @@ -81,7 +81,7 @@ public: void check(DeclarationAST *declaration, Scope *scope, TemplateParameters *templateParameters = 0); - void check(StatementAST *statement, Scope *scope); + FullySpecifiedType check(StatementAST *statement, Scope *scope); const Name *check(NameAST *name, Scope *scope); -- GitLab