]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/commitdiff
Add more warnings, improve reported locations and ranges, refactor
authorMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 3 Sep 2012 22:34:22 +0000 (00:34 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 3 Sep 2012 22:34:22 +0000 (00:34 +0200)
src/visualizer.cpp

index 8a4171071aac954950b511078b58ba9a5f536f21..a18b4c12caa543f77d59ebc77946e19ae6229d95 100644 (file)
@@ -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<ElaboratedType>(T))
-           return getTemplateArgDecl(ET->getNamedType().getTypePtr(), ArgNum, Loc);
-       else if (const TemplateSpecializationType *TST = dyn_cast<TemplateSpecializationType>(T)) {
-           if (TST->getNumArgs() >= ArgNum+1)
-               return TST->getArg(ArgNum).getAsType()->getAsCXXRecordDecl();
+       if (const ElaboratedTypeLoc *ET = dyn_cast<ElaboratedTypeLoc>(&T))
+           return getTemplateArgLoc(ET->getNamedTypeLoc(), ArgNum);
+       else if (const TemplateSpecializationTypeLoc *TST = dyn_cast<TemplateSpecializationTypeLoc>(&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<MyCXXRecordDecl*>(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<MyCXXRecordDecl*>(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<MyCXXRecordDecl*>(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<MyCXXRecordDecl*>(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<MyCXXRecordDecl*>(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<MyCXXRecordDecl*>(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());