From 25aa2a1c653bea6fbecdff650fe90201bb3e4810 Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Tue, 4 Sep 2012 00:34:22 +0200 Subject: [PATCH] Add more warnings, improve reported locations and ranges, refactor --- src/visualizer.cpp | 133 +++++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 52 deletions(-) diff --git a/src/visualizer.cpp b/src/visualizer.cpp index 8a41710..a18b4c1 100644 --- a/src/visualizer.cpp +++ b/src/visualizer.cpp @@ -368,45 +368,56 @@ public: Diag(Decl->getLocation(), diag_unhandled_reaction_decl) << Decl->getDeclKindName(); } - CXXRecordDecl *getTemplateArgDecl(const Type *T, unsigned ArgNum, const SourceLocation Loc) + TemplateArgumentLoc getTemplateArgLoc(const TypeLoc &T, unsigned ArgNum) { - if (const ElaboratedType *ET = dyn_cast(T)) - return getTemplateArgDecl(ET->getNamedType().getTypePtr(), ArgNum, Loc); - else if (const TemplateSpecializationType *TST = dyn_cast(T)) { - if (TST->getNumArgs() >= ArgNum+1) - return TST->getArg(ArgNum).getAsType()->getAsCXXRecordDecl(); + if (const ElaboratedTypeLoc *ET = dyn_cast(&T)) + return getTemplateArgLoc(ET->getNamedTypeLoc(), ArgNum); + else if (const TemplateSpecializationTypeLoc *TST = dyn_cast(&T)) { + if (TST->getNumArgs() >= ArgNum+1) { + return TST->getArgLoc(ArgNum); + } else + Diag(TST->getBeginLoc(), diag_warning) << TST->getType()->getTypeClassName() << "has not enough arguments" << TST->getSourceRange(); } else - Diag(Loc, diag_warning) << T->getTypeClassName() << "type as template argument is not supported"; + Diag(T.getBeginLoc(), diag_warning) << T.getType()->getTypeClassName() << "type as template argument is not supported" << T.getSourceRange(); + return TemplateArgumentLoc(); + } + + TemplateArgumentLoc getTemplateArgLocOfBase(const CXXBaseSpecifier *Base, unsigned ArgNum) { + return getTemplateArgLoc(Base->getTypeSourceInfo()->getTypeLoc(), 1); + } + + CXXRecordDecl *getTemplateArgDeclOfBase(const CXXBaseSpecifier *Base, unsigned ArgNum, TemplateArgumentLoc &Loc) { + Loc = getTemplateArgLocOfBase(Base, 1); + switch (Loc.getArgument().getKind()) { + case TemplateArgument::Type: + return Loc.getTypeSourceInfo()->getType()->getAsCXXRecordDecl(); + case TemplateArgument::Null: + // Diag() was already called + break; + default: + Diag(Loc.getSourceRange().getBegin(), diag_warning) << Loc.getArgument().getKind() << "unsupported kind" << Loc.getSourceRange(); + } return 0; } CXXRecordDecl *getTemplateArgDeclOfBase(const CXXBaseSpecifier *Base, unsigned ArgNum) { - return getTemplateArgDecl(Base->getType().getTypePtr(), 1, - Base->getTypeSourceInfo()->getTypeLoc().getLocStart()); + TemplateArgumentLoc Loc; + return getTemplateArgDeclOfBase(Base, ArgNum, Loc); } - bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) + void handleSimpleState(CXXRecordDecl *RecordDecl, const CXXBaseSpecifier *Base) { - if (!Declaration->isCompleteDefinition()) - return true; - if (Declaration->getQualifiedNameAsString() == "boost::statechart::state") - return true; // This is an "abstract class" not a real state + string name(RecordDecl->getName()); //getQualifiedNameAsString()); + Diag(RecordDecl->getLocStart(), diag_found_state) << name; - MyCXXRecordDecl *RecordDecl = static_cast(Declaration); - const CXXBaseSpecifier *Base; + Model::State *state; + // Either we saw a reference to forward declared state + // before, or we create a new state. + if (!(state = model.removeFromUndefinedContexts(name))) + state = new Model::State(name); - if (RecordDecl->isDerivedFrom("boost::statechart::simple_state", &Base)) - { - string name(RecordDecl->getName()); //getQualifiedNameAsString()); - Diag(RecordDecl->getLocStart(), diag_found_state) << name; - - Model::State *state; - // Either we saw a reference to forward declared state - // before, or we create a new state. - if (!(state = model.removeFromUndefinedContexts(name))) - state = new Model::State(name); - - CXXRecordDecl *Context = getTemplateArgDeclOfBase(Base, 1); + CXXRecordDecl *Context = getTemplateArgDeclOfBase(Base, 1); + if (Context) { Model::Context *c = model.findContext(Context->getName()); if (!c) { Model::State *s = new Model::State(Context->getName()); @@ -414,36 +425,54 @@ public: c = s; } c->add(state); + } - if (MyCXXRecordDecl *InnerInitialState = - static_cast(getTemplateArgDeclOfBase(Base, 2))) { - if (InnerInitialState->isDerivedFrom("boost::statechart::simple_state") || - InnerInitialState->isDerivedFrom("boost::statechart::state_machine")) - state->setInitialInnerState(InnerInitialState->getName()); - else - Diag(Base->getTypeSourceInfo()->getTypeLoc().getLocStart(), diag_warning) - << InnerInitialState->getQualifiedNameAsString() << " as inner initial state is not supported"; - } + TemplateArgumentLoc Loc; + if (MyCXXRecordDecl *InnerInitialState = + static_cast(getTemplateArgDeclOfBase(Base, 2, Loc))) { + if (InnerInitialState->isDerivedFrom("boost::statechart::simple_state") || + InnerInitialState->isDerivedFrom("boost::statechart::state_machine")) + state->setInitialInnerState(InnerInitialState->getName()); + else + Diag(Loc.getTypeSourceInfo()->getTypeLoc().getLocStart(), diag_warning) + << InnerInitialState->getName() << " as inner initial state is not supported" << Loc.getSourceRange(); + } // if (CXXRecordDecl *History = getTemplateArgDecl(Base->getType().getTypePtr(), 3)) // Diag(History->getLocStart(), diag_no_history); - IdentifierInfo& II = ASTCtx->Idents.get("reactions"); - // TODO: Lookup for reactions even in base classes - probably by using Sema::LookupQualifiedName() - for (DeclContext::lookup_result Reactions = RecordDecl->lookup(DeclarationName(&II)); - Reactions.first != Reactions.second; ++Reactions.first) - HandleReaction(*Reactions.first, RecordDecl); - } - else if (RecordDecl->isDerivedFrom("boost::statechart::state_machine", &Base)) - { - Model::Machine m(RecordDecl->getName()); - Diag(RecordDecl->getLocStart(), diag_found_statemachine) << m.name; + IdentifierInfo& II = ASTCtx->Idents.get("reactions"); + // TODO: Lookup for reactions even in base classes - probably by using Sema::LookupQualifiedName() + for (DeclContext::lookup_result Reactions = RecordDecl->lookup(DeclarationName(&II)); + Reactions.first != Reactions.second; ++Reactions.first) + HandleReaction(*Reactions.first, RecordDecl); + } - if (MyCXXRecordDecl *InitialState = - static_cast(getTemplateArgDeclOfBase(Base, 1))) - m.setInitialState(InitialState->getName()); - model.add(m); - } + void handleStateMachine(CXXRecordDecl *RecordDecl, const CXXBaseSpecifier *Base) + { + Model::Machine m(RecordDecl->getName()); + Diag(RecordDecl->getLocStart(), diag_found_statemachine) << m.name; + + if (MyCXXRecordDecl *InitialState = + static_cast(getTemplateArgDeclOfBase(Base, 1))) + m.setInitialState(InitialState->getName()); + model.add(m); + } + + bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) + { + if (!Declaration->isCompleteDefinition()) + return true; + if (Declaration->getQualifiedNameAsString() == "boost::statechart::state") + return true; // This is an "abstract class" not a real state + + MyCXXRecordDecl *RecordDecl = static_cast(Declaration); + const CXXBaseSpecifier *Base; + + if (RecordDecl->isDerivedFrom("boost::statechart::simple_state", &Base)) + handleSimpleState(RecordDecl, Base); + else if (RecordDecl->isDerivedFrom("boost::statechart::state_machine", &Base)) + handleStateMachine(RecordDecl, Base); else if (RecordDecl->isDerivedFrom("boost::statechart::event")) { //sc.events.push_back(RecordDecl->getNameAsString()); -- 2.39.2