From f55d5500c5f46471861537dbcea09d737d4b064b Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 4 Jun 2009 11:32:01 +0200 Subject: [PATCH] Warn for undefined types (not finished yet). --- src/plugins/cpptools/cppmodelmanager.cpp | 121 ++++++++++++++++++++++- src/shared/cplusplus/CheckExpression.cpp | 15 ++- src/shared/cplusplus/CheckName.cpp | 4 + 3 files changed, 135 insertions(+), 5 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index e4daf77cb38..ee3b3680823 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -29,6 +29,7 @@ #include #include +#include #include "cppmodelmanager.h" #include "cpptoolsconstants.h" @@ -254,13 +255,23 @@ class Process; class CheckUndefinedSymbols: protected ASTVisitor { + QSet _types; + public: CheckUndefinedSymbols(Document::Ptr doc) : ASTVisitor(doc->control()), _process(0), _doc(doc) { } void setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding) - { _globalNamespaceBinding = globalNamespaceBinding; } + { + _globalNamespaceBinding = globalNamespaceBinding; + _types.clear(); + + if (_globalNamespaceBinding) { + QSet processed; + buildTypeMap(_globalNamespaceBinding.data(), &processed); + } + } void operator()(AST *ast, Process *process) { _process = process; accept(ast); } @@ -268,6 +279,114 @@ public: protected: using ASTVisitor::visit; + void addType(Name *name) + { + if (! name) + return; + + if (Identifier *id = name->identifier()) + _types.insert(QByteArray(id->chars(), id->size())); + } + + void buildTypeMap(Class *klass) + { + addType(klass->name()); + + for (unsigned i = 0; i < klass->memberCount(); ++i) { + Symbol *member = klass->memberAt(i); + + if (Class *klass = member->asClass()) { + buildTypeMap(klass); + } else if (Enum *e = member->asEnum()) { + addType(e->name()); + } else if (ForwardClassDeclaration *fwd = member->asForwardClassDeclaration()) { + addType(fwd->name()); + } else if (Declaration *decl = member->asDeclaration()) { + if (decl->isTypedef()) + addType(decl->name()); + } + } + } + + void buildTypeMap(NamespaceBinding *binding, QSet *processed) + { + if (! processed->contains(binding)) { + processed->insert(binding); + + foreach (Namespace *ns, binding->symbols) { + for (unsigned i = 0; i < ns->memberCount(); ++i) { + Symbol *member = ns->memberAt(i); + + if (Class *klass = member->asClass()) { + buildTypeMap(klass); + } else if (Enum *e = member->asEnum()) { + addType(e->name()); + } else if (ForwardClassDeclaration *fwd = member->asForwardClassDeclaration()) { + addType(fwd->name()); + } else if (Declaration *decl = member->asDeclaration()) { + if (decl->isTypedef()) + addType(decl->name()); + } + } + } + + foreach (NamespaceBinding *childBinding, binding->children) { + buildTypeMap(childBinding, processed); + } + } + } + + QList functionDeclarationStack; + + FunctionDeclaratorAST *currentFunctionDeclarator() const + { + if (functionDeclarationStack.isEmpty()) + return 0; + + return functionDeclarationStack.last(); + } + + virtual bool visit(FunctionDeclaratorAST *ast) + { + functionDeclarationStack.append(ast); + + return true; + } + + virtual void endVisit(FunctionDeclaratorAST *) + { + functionDeclarationStack.removeLast(); + } + + virtual bool visit(TypeofSpecifierAST *ast) + { + accept(ast->next); + return false; + } + + virtual bool visit(NamedTypeSpecifierAST *ast) + { + if (ast->name) { + if (! ast->name->name) { + unsigned line, col; + getTokenStartPosition(ast->firstToken(), &line, &col); + // qWarning() << _doc->fileName() << line << col; + } else if (Identifier *id = ast->name->name->identifier()) { + if (! _types.contains(QByteArray::fromRawData(id->chars(), id->size()))) { + if (FunctionDeclaratorAST *functionDeclarator = currentFunctionDeclarator()) { + if (functionDeclarator->as_cpp_initializer) + return true; + } + + Overview oo; + translationUnit()->warning(ast->firstToken(), "`%s' is not a type-name", + qPrintable(oo(ast->name->name))); + } + } + } + return true; + } + virtual bool visit(ClassSpecifierAST *ast) { if (ast->base_clause) { diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp index 8d0bf823e50..6e83ce47bf4 100644 --- a/src/shared/cplusplus/CheckExpression.cpp +++ b/src/shared/cplusplus/CheckExpression.cpp @@ -208,13 +208,20 @@ bool CheckExpression::visit(TemplateIdAST *ast) return false; } -bool CheckExpression::visit(NewExpressionAST *) +bool CheckExpression::visit(NewExpressionAST *ast) { // ### FIXME - //FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); - //FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope); - // ### process new-typeid + // ### process ast->new_placement + + FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope); + + if (ast->new_type_id) { + FullySpecifiedType ty = semantic()->check(ast->new_type_id->type_specifier, _scope); + // ### process ast->new_type_id + } + // ### process new-initializer + return false; } diff --git a/src/shared/cplusplus/CheckName.cpp b/src/shared/cplusplus/CheckName.cpp index 28040a87dce..832daf9ed4e 100644 --- a/src/shared/cplusplus/CheckName.cpp +++ b/src/shared/cplusplus/CheckName.cpp @@ -73,6 +73,10 @@ Name *CheckName::check(NameAST *name, Scope *scope) Name *previousName = switchName(0); Scope *previousScope = switchScope(scope); accept(name); + + if (_name && name) + name->name = _name; + (void) switchScope(previousScope); return switchName(previousName); }