From e421d32147c867e326fbf036781f57c873f7056e Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Tue, 30 Mar 2010 16:52:20 +0200 Subject: [PATCH] Postpone the parsing of function definitions. --- src/shared/cplusplus/CheckDeclaration.cpp | 32 ++++------- src/shared/cplusplus/CheckDeclaration.h | 1 + src/shared/cplusplus/CheckSpecifier.cpp | 7 +++ src/shared/cplusplus/Semantic.cpp | 66 +++++++++++++++++++++++ src/shared/cplusplus/Semantic.h | 25 +++++++++ 5 files changed, 108 insertions(+), 23 deletions(-) diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 508e2e798b4..01a10222c98 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -85,6 +85,13 @@ void CheckDeclaration::check(DeclarationAST *declaration, (void) switchScope(previousScope); } +void CheckDeclaration::check(CtorInitializerAST *ast, Scope *scope) +{ + Scope *previousScope = switchScope(scope); + accept(ast); + (void) switchScope(previousScope); +} + DeclarationAST *CheckDeclaration::switchDeclaration(DeclarationAST *declaration) { DeclarationAST *previousDeclaration = _declaration; @@ -352,29 +359,8 @@ bool CheckDeclaration::visit(FunctionDefinitionAST *ast) ast->symbol = fun; _scope->enterSymbol(fun); - if (! semantic()->skipFunctionBodies()) { - if (ast->ctor_initializer) { - bool looksLikeCtor = false; - if (ty.isValid() || ! fun->identity()) - looksLikeCtor = false; - else if (fun->identity()->isNameId() || fun->identity()->isTemplateNameId()) - looksLikeCtor = true; - - if (! looksLikeCtor) { - translationUnit()->error(ast->ctor_initializer->firstToken(), - "only constructors take base initializers"); - } - accept(ast->ctor_initializer); - } - - const int previousVisibility = semantic()->switchVisibility(Symbol::Public); - const int previousMethodKey = semantic()->switchMethodKey(Function::NormalMethod); - - semantic()->check(ast->function_body, fun->members()); - - semantic()->switchMethodKey(previousMethodKey); - semantic()->switchVisibility(previousVisibility); - } + if (! semantic()->skipFunctionBodies()) + semantic()->checkFunctionDefinition(ast); return false; } diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h index d2977a51f0a..d9d8cb0170f 100644 --- a/src/shared/cplusplus/CheckDeclaration.h +++ b/src/shared/cplusplus/CheckDeclaration.h @@ -62,6 +62,7 @@ public: virtual ~CheckDeclaration(); void check(DeclarationAST *declaration, Scope *scope, TemplateParameters *templateParameters); + void check(CtorInitializerAST *ast, Scope *scope); protected: DeclarationAST *switchDeclaration(DeclarationAST *declaration); diff --git a/src/shared/cplusplus/CheckSpecifier.cpp b/src/shared/cplusplus/CheckSpecifier.cpp index a0c4f36995b..f2c60c57de7 100644 --- a/src/shared/cplusplus/CheckSpecifier.cpp +++ b/src/shared/cplusplus/CheckSpecifier.cpp @@ -337,8 +337,13 @@ bool CheckSpecifier::visit(ClassSpecifierAST *ast) klass->setClassKey(Class::UnionKey); klass->setVisibility(semantic()->currentVisibility()); _scope->enterSymbol(klass); + + ClassSpecifierAST *previousClassSpecifier = semantic()->switchDeclaringClass(ast); + _fullySpecifiedType.setType(klass); + accept(ast->attribute_list); + if (_fullySpecifiedType.isDeprecated()) klass->setDeprecated(true); @@ -377,6 +382,8 @@ bool CheckSpecifier::visit(ClassSpecifierAST *ast) (void) semantic()->switchMethodKey(previousMethodKey); (void) semantic()->switchVisibility(previousVisibility); + (void) semantic()->switchDeclaringClass(previousClassSpecifier); + return false; } diff --git a/src/shared/cplusplus/Semantic.cpp b/src/shared/cplusplus/Semantic.cpp index ebd3aacec25..9dd1b9aca8c 100644 --- a/src/shared/cplusplus/Semantic.cpp +++ b/src/shared/cplusplus/Semantic.cpp @@ -52,6 +52,7 @@ #include "Scope.h" #include "Symbols.h" #include "Token.h" +#include "AST.h" #include "CheckSpecifier.h" #include "CheckDeclaration.h" #include "CheckDeclarator.h" @@ -61,6 +62,20 @@ using namespace CPlusPlus; +SemanticClient::SemanticClient(Semantic *semantic) + : _semantic(semantic) +{ +} + +SemanticClient::~SemanticClient() +{ +} + +Semantic *SemanticClient::semantic() const +{ + return _semantic; +} + class Semantic::Data { public: @@ -68,10 +83,12 @@ public: : semantic(semantic), translationUnit(translationUnit), control(translationUnit->control()), + semanticClient(0), skipFunctionBodies(false), visibility(Symbol::Public), ojbcVisibility(Symbol::Protected), methodKey(Function::NormalMethod), + declaringClass(0), checkSpecifier(0), checkDeclaration(0), checkDeclarator(0), @@ -93,16 +110,19 @@ public: Semantic *semantic; TranslationUnit *translationUnit; Control *control; + SemanticClient *semanticClient; bool skipFunctionBodies; int visibility; int ojbcVisibility; int methodKey; + ClassSpecifierAST *declaringClass; CheckSpecifier *checkSpecifier; CheckDeclaration *checkDeclaration; CheckDeclarator *checkDeclarator; CheckExpression *checkExpression; CheckStatement *checkStatement; CheckName *checkName; + std::vector<FunctionDefinitionAST *> functionsToProcess; }; Semantic::Semantic(TranslationUnit *translationUnit) @@ -119,6 +139,12 @@ Semantic::Semantic(TranslationUnit *translationUnit) Semantic::~Semantic() { delete d; } +SemanticClient *Semantic::semanticClient() const +{ return d->semanticClient; } + +void Semantic::setSemanticClient(SemanticClient *client) +{ d->semanticClient = client; } + TranslationUnit *Semantic::translationUnit() const { return d->translationUnit; } @@ -162,6 +188,27 @@ const Name *Semantic::check(NameAST *name, Scope *scope) const Name *Semantic::check(NestedNameSpecifierListAST *name, Scope *scope) { return d->checkName->check(name, scope); } +void Semantic::checkFunctionDefinition(FunctionDefinitionAST *ast) +{ + if (d->declaringClass != 0) + d->functionsToProcess.push_back(ast); + else + finishFunctionDefinition(ast); +} + +void Semantic::finishFunctionDefinition(FunctionDefinitionAST *ast) +{ + const int previousVisibility = switchVisibility(Symbol::Public); + const int previousMethodKey = switchMethodKey(Function::NormalMethod); + + Function *fun = ast->symbol; + d->checkDeclaration->check(ast->ctor_initializer, fun->scope()); + check(ast->function_body, fun->members()); + + switchMethodKey(previousMethodKey); + switchVisibility(previousVisibility); +} + bool Semantic::skipFunctionBodies() const { return d->skipFunctionBodies; } @@ -198,6 +245,25 @@ int Semantic::switchMethodKey(int methodKey) return previousMethodKey; } +ClassSpecifierAST *Semantic::declatingClass() const +{ return d->declaringClass; } + +ClassSpecifierAST *Semantic::switchDeclaringClass(ClassSpecifierAST *ast) +{ + ClassSpecifierAST *previous = d->declaringClass; + d->declaringClass = ast; + + if (! ast && ! d->functionsToProcess.empty()) { + const std::vector<FunctionDefinitionAST *> todo = d->functionsToProcess; + d->functionsToProcess.clear(); + + for (std::vector<FunctionDefinitionAST *>::const_iterator it = todo.begin(); it != todo.end(); ++it) + finishFunctionDefinition(*it); + } + + return previous; +} + int Semantic::visibilityForAccessSpecifier(int tokenKind) const { switch (tokenKind) { diff --git a/src/shared/cplusplus/Semantic.h b/src/shared/cplusplus/Semantic.h index a804a72328e..6aace93f757 100644 --- a/src/shared/cplusplus/Semantic.h +++ b/src/shared/cplusplus/Semantic.h @@ -55,6 +55,22 @@ namespace CPlusPlus { +class CPLUSPLUS_EXPORT SemanticClient +{ + SemanticClient(const SemanticClient &other); + void operator = (const SemanticClient &other); + +public: + SemanticClient(Semantic *semantic); + virtual ~SemanticClient(); + + Semantic *semantic() const; + +private: + Semantic *_semantic; +}; + + class CPLUSPLUS_EXPORT Semantic { Semantic(const Semantic &other); @@ -67,6 +83,9 @@ public: TranslationUnit *translationUnit() const; Control *control() const; + SemanticClient *semanticClient() const; + void setSemanticClient(SemanticClient *client); + FullySpecifiedType check(SpecifierListAST *specifier, Scope *scope, const FullySpecifiedType &type = FullySpecifiedType()); @@ -93,6 +112,9 @@ public: void check(ObjCMessageArgumentDeclarationAST *arg, Scope *scope); + void checkFunctionDefinition(FunctionDefinitionAST *ast); + void finishFunctionDefinition(FunctionDefinitionAST *ast); + bool skipFunctionBodies() const; void setSkipFunctionBodies(bool skipFunctionBodies); @@ -105,6 +127,9 @@ public: int currentMethodKey() const; int switchMethodKey(int methodKey); + ClassSpecifierAST *declatingClass() const; + ClassSpecifierAST *switchDeclaringClass(ClassSpecifierAST *ast); + int visibilityForClassKey(int tokenKind) const; int visibilityForAccessSpecifier(int tokenKind) const; int visibilityForObjCAccessSpecifier(int tokenKind) const; -- GitLab