3 #include "llvm/Support/raw_ostream.h"
4 #include "llvm/System/Host.h"
5 #include "llvm/Config/config.h"
7 #include "clang/Frontend/DiagnosticOptions.h"
8 #include "clang/Frontend/TextDiagnosticPrinter.h"
10 #include "clang/Basic/LangOptions.h"
11 #include "clang/Basic/FileSystemOptions.h"
13 #include "clang/Index/TranslationUnit.h"
14 #include "clang/Basic/SourceManager.h"
15 #include "clang/Lex/HeaderSearch.h"
16 #include "clang/Basic/FileManager.h"
18 #include "clang/Frontend/HeaderSearchOptions.h"
19 #include "clang/Frontend/Utils.h"
21 #include "clang/Basic/TargetOptions.h"
22 #include "clang/Basic/TargetInfo.h"
24 #include "clang/Lex/Preprocessor.h"
25 #include "clang/Frontend/PreprocessorOptions.h"
26 #include "clang/Frontend/FrontendOptions.h"
28 #include "clang/Frontend/CompilerInvocation.h"
30 #include "clang/Basic/IdentifierTable.h"
31 #include "clang/Basic/Builtins.h"
33 #include "clang/AST/ASTContext.h"
34 #include "clang/AST/ASTConsumer.h"
35 #include "clang/Sema/Sema.h"
36 #include "clang/AST/DeclBase.h"
37 #include "clang/AST/Type.h"
38 #include "clang/AST/Decl.h"
39 #include "clang/Sema/Lookup.h"
40 #include "clang/Sema/Ownership.h"
41 #include "clang/AST/DeclGroup.h"
43 #include "clang/Parse/Parser.h"
45 #include "clang/Parse/ParseAST.h"
46 #include "clang/Basic/Version.h"
48 #include "llvm/Support/CommandLine.h"
51 #include "stringoper.h"
52 #include "commandlineopt.h"
54 using namespace clang;
57 class FindStates : public ASTConsumer
63 virtual void Initialize(ASTContext &ctx)//run after the AST is constructed
65 SourceManager &sman = ctx.getSourceManager();
66 fSloc = new FullSourceLoc(loc, sman);
69 virtual void HandleTopLevelDecl(DeclGroupRef DGR)// traverse all top level declarations
72 const SourceManager &sman = fSloc->getManager();
74 std::string super_class, output;
75 llvm::raw_string_ostream x(output);
76 for (DeclGroupRef::iterator i = DGR.begin(), e = DGR.end(); i != e; ++i)
78 const Decl *decl = *i;
79 loc = decl->getLocation();
82 const NamedDecl *namedDecl = dyn_cast<NamedDecl>(decl);
83 //std::cout<<decl->getDeclKindName()<<"\n";
84 if(!sman.isInSystemHeader(loc))
86 if (const TagDecl *tagDecl = dyn_cast<TagDecl>(decl))
88 if(tagDecl->isStruct() || tagDecl->isClass()) //is it a structure or class
90 const CXXRecordDecl *cRecDecl = dyn_cast<CXXRecordDecl>(decl);
91 line = cut_commentary(clean_spaces(get_line_of_code(sman.getCharacterData(loc))));
94 if(find_states(cRecDecl, line))
96 const DeclContext *declCont = tagDecl->castToDeclContext(tagDecl);
97 std::cout << "New state: " << namedDecl->getNameAsString() << "\n";
98 find_transitions(namedDecl->getNameAsString(), declCont);
103 if(const NamespaceDecl *namespaceDecl = dyn_cast<NamespaceDecl>(decl))
106 DeclContext *declCont = namespaceDecl->castToDeclContext(namespaceDecl);
107 //declCont->dumpDeclContext();
108 recursive_visit(declCont);
115 void recursive_visit(const DeclContext *declCont) //recursively visit all decls inside namespace
117 const SourceManager &sman = fSloc->getManager();
120 for (DeclContext::decl_iterator i = declCont->decls_begin(), e = declCont->decls_end(); i != e; ++i)
122 const Decl *decl = *i;
123 const NamedDecl *namedDecl = dyn_cast<NamedDecl>(decl);
125 //std::cout<<"a "<<decl->getDeclKindName()<<"\n";
126 loc = decl->getLocation();
129 if (const TagDecl *tagDecl = dyn_cast<TagDecl>(decl))
131 if(tagDecl->isStruct() || tagDecl->isClass()) //is it a structure or class
133 const CXXRecordDecl *cRecDecl = dyn_cast<CXXRecordDecl>(decl);
134 line = cut_commentary(clean_spaces(get_line_of_code(sman.getCharacterData(loc))));
137 if(find_states(cRecDecl, line))
139 const DeclContext *declCont = tagDecl->castToDeclContext(tagDecl);
140 std::cout << "New state: " << namedDecl->getNameAsString() << "\n";
141 find_transitions(namedDecl->getNameAsString(), declCont);
146 if(const NamespaceDecl *namespaceDecl = dyn_cast<NamespaceDecl>(decl))
148 DeclContext *declCont = namespaceDecl->castToDeclContext(namespaceDecl);
149 //declCont->dumpDeclContext();
150 recursive_visit(declCont);
155 bool find_states(const CXXRecordDecl *cRecDecl, std::string line)
157 std::string super_class = get_super_class(line), base;
158 if(cRecDecl->getNumBases()>1)
160 for(int i = 0; i<cRecDecl->getNumBases();i++ )
162 if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
163 else base = super_class;
164 if(is_state(base)) return true;
167 super_class = get_next_base(super_class);
174 if(is_state(super_class)) return true;
179 void find_transitions (const std::string name_of_state,const DeclContext *declCont) // traverse all methods for finding declarations of transitions
181 std::string output, line, event, dest, params, base;
182 llvm::raw_string_ostream x(output);
185 for (DeclContext::decl_iterator i = declCont->decls_begin(), e = declCont->decls_end(); i != e; ++i)
187 const Decl *decl = *i;
189 if (const TypedefDecl *typeDecl = dyn_cast<TypedefDecl>(decl))
193 line = clean_spaces(cut_typedef(output));
200 line = get_inner_part(line);
203 for(int j = 0;j<num;j++)
205 if(j!=num-1) base = get_first_base(line);
207 if(is_transition(base))
209 params = get_transition_params(line);
210 pos = params.find(",");
211 event = params.substr(0,pos);
212 dest = params.substr(pos+1);
213 std::cout << "New transition: " << name_of_state<<" -> "<<event<<" -> "<< dest<<"\n";
214 line = get_next_base(line);
218 line = get_next_base(line);
226 int main(int argc, char *argv[])
228 llvm::cl::ParseCommandLineOptions(argc, argv);
229 DiagnosticOptions diagnosticOptions;
230 TextDiagnosticPrinter *tdp = new TextDiagnosticPrinter(llvm::nulls(), diagnosticOptions);
231 llvm::IntrusiveRefCntPtr<DiagnosticIDs> dis(new DiagnosticIDs());
232 Diagnostic diag(dis,tdp);
233 FileSystemOptions fileSysOpt;
237 FileManager fm (fileSysOpt);
239 SourceManager sm ( diag, fm);
240 HeaderSearch *headers = new HeaderSearch(fm);
241 CompilerInvocation::setLangDefaults(lang, IK_ObjCXX);
243 HeaderSearchOptions hsopts;
244 hsopts.ResourceDir=LLVM_PREFIX "/lib/clang/" CLANG_VERSION_STRING;
245 for(int i = 0; i<includeFiles.size();i++)
247 hsopts.AddPath(includeFiles[i],
248 clang::frontend::Angled,
254 to.Triple = llvm::sys::getHostTriple();
255 TargetInfo *ti = TargetInfo::CreateTargetInfo(diag, to);
256 clang::ApplyHeaderSearchOptions(
261 Preprocessor pp(diag, lang, *ti, sm, *headers);
263 PreprocessorOptions ppio;
264 InitializePreprocessor(pp, ppio,hsopts,f);
265 const FileEntry *file = fm.getFile("test.cpp");
266 sm.createMainFileID(file);
267 IdentifierTable tab(lang);
269 Builtin::Context builtins(*ti);
271 ASTContext ctx(lang, sm, *ti, tab, sel, builtins,0);
272 tdp->BeginSourceFile(lang, &pp);
273 ParseAST(pp, &c, ctx, false, false);
274 tdp->EndSourceFile();