/* Both FieldDecl and VarDecl derive from DeclaratorDecl. We can do common things to both node types in this function */ bool FieldVisitor::VisitDeclaratorDecl( clang::DeclaratorDecl *dd ) { fdes->setFileName(getFileName(ci , dd->getLocation(), hsd)) ; fdes->setName(dd->getNameAsString()) ; fdes->setAccess(dd->getAccess()) ; /* Get the source location of this field. */ clang::SourceRange dd_range = dd->getSourceRange() ; std::string file_name = ci.getSourceManager().getBufferName(dd_range.getEnd()) ; char * resolved_path = almostRealPath( file_name.c_str() ) ; if ( resolved_path ) { if ( isInUserOrTrickCode( ci , dd_range.getEnd() , hsd ) ) { fdes->setLineNo(ci.getSourceManager().getSpellingLineNumber(dd_range.getEnd())) ; /* process comment if neither ICG:(No) or ICG:(NoComment) is present */ if ( cs.hasTrickHeader(resolved_path) and !cs.hasICGNoComment(resolved_path) and !hsd.isPathInICGNoComment(resolved_path) ) { /* Get the possible comment on this line and parse it */ fdes->parseComment(cs.getComment(resolved_path , fdes->getLineNo())) ; } } free(resolved_path) ; } if ( debug_level >= 3 ) { if ( ! ci.getSourceManager().isInSystemHeader(dd_range.getEnd()) ) { std::cout << "\nFieldVisitor VisitDeclaratorDecl" << std::endl ; dd->dump() ; std::cout << std::endl ; std::cout << " public/private = " << fdes->getAccess() << std::endl ; } } return true ; }
/** Prints the io_src header information */ void PrintFileContents10::printIOHeader(std::ostream & ostream , std::string header_file_name) { if ( ! header_file_name.compare("S_source.hh") ) { header_file_name = "../S_source.hh" ; } else { header_file_name = almostRealPath(header_file_name.c_str()) ; } ostream << "/**\n" << " * This file was automatically generated by the ICG based on the file:\n" << " * " << header_file_name << "\n" << " * This file contains database parameter declarations specific to the\n" << " * data structures and enumerated types declared in the above file.\n" << " * These database parameters are used by the Trick input and\n" << " * data recording processors to gain access to important simulation\n" << " * variable information.\n" << " */\n" << "\n" << "#define TRICK_IN_IOSRC\n" << "#include <stdlib.h>\n" << "#include \"trick/MemoryManager.hh\"\n" << "#include \"trick/attributes.h\"\n" << "#include \"trick/parameter_types.h\"\n" << "#include \"trick/ClassSizeCheck.hh\"\n" << "#include \"trick/UnitsMap.hh\"\n" << "#include \"trick/checkpoint_stl.hh\"\n" << "#include \"" << header_file_name << "\"\n" << "\n" ; }
/** Prints the io_src header information */ void PrintFileContents10::printIOHeader(std::ofstream & outfile , std::string header_file_name) { if ( ! header_file_name.compare("S_source.hh") ) { header_file_name = "../S_source.hh" ; } else { header_file_name = almostRealPath(header_file_name.c_str()) ; } outfile << "\n" "/*\n" " * This file was automatically generated by the ICG based on the file:\n" " * " << header_file_name << "\n" " * This file contains database parameter declarations specific to the\n" " * data structures and enumerated types declared in the above file.\n" " * These database parameters are used by the Trick input and\n" " * data recording processors to gain access to important simulation\n" " * variable information.\n" " *\n" " * Auto Code Generator Programmer:\n" " * Rob Bailey Sweet Systems Inc 12/97\n" " * Alex Lin NASA 03/01\n" " * Alex Lin NASA 05/09\n" " */\n" "#define TRICK_IN_IOSRC\n" "#include <stdlib.h>\n" "\n" "#include \"trick/MemoryManager.hh\"\n" "#include \"trick/attributes.h\"\n" "#include \"trick/parameter_types.h\"\n" "#include \"trick/UnitsMap.hh\"\n\n" "#include \"trick/checkpoint_stl.hh\"\n\n" "#include \"" << header_file_name << "\"\n\n" ; }
void HeaderSearchDirs::AddTrickSearchDirs () { char * trick_home = getenv("TRICK_HOME") ; if ( trick_home != NULL ) { std::string temp_dir = std::string(trick_home) + "/include/trick" ; char * resolved_path = almostRealPath(temp_dir.c_str() ) ; hso.AddPath(resolved_path , clang::frontend::Quoted, false, true); trick_include_dir = std::string(resolved_path) ; free(resolved_path) ; temp_dir = std::string(trick_home) + "/trick_source" ; resolved_path = almostRealPath(temp_dir.c_str() ) ; hso.AddPath(resolved_path , clang::frontend::Quoted, false, true); trick_source_dir = std::string(resolved_path) ; free(resolved_path) ; } }
std::string getFileName( clang::CompilerInstance & ci , clang::SourceLocation sl , HeaderSearchDirs & hsd ) { clang::FileID fid = ci.getSourceManager().getFileID(sl) ; if ( ! fid.isInvalid() ) { const clang::FileEntry * fe = ci.getSourceManager().getFileEntryForID(fid) ; if ( fe != NULL ) { char * resolved_path = almostRealPath( fe->getName() ) ; if ( resolved_path != NULL and hsd.isPathInUserDir(resolved_path)) { return std::string(resolved_path) ; } } } return std::string() ; }
void HeaderSearchDirs::AddUserSearchDirs ( std::vector<std::string> & include_dirs ) { //std::cout << "num include dirs " << include_dirs.size() << std::endl ; int ii ; for ( ii = 0 ; ii < include_dirs.size() ; ii++ ) { //std::cout << "include dirs " << include_dirs[ii] << std::endl ; char * resolved_path = almostRealPath(include_dirs[ii].c_str()) ; if ( resolved_path != NULL ) { //std::cout << "adding resolved_path = " << resolved_path << std::endl ; hso.AddPath(resolved_path , clang::frontend::Angled, false, true); // Add the path as a system path as well for those included files that are erroneously in <> } } }
bool isInUserOrTrickCode( clang::CompilerInstance & ci , clang::SourceLocation sl , HeaderSearchDirs & hsd ) { clang::FileID fid = ci.getSourceManager().getFileID(sl) ; bool ret = false ; if ( ! fid.isInvalid() ) { const clang::FileEntry * fe = ci.getSourceManager().getFileEntryForID(fid) ; if ( fe != NULL ) { char * resolved_path = almostRealPath( fe->getName() ) ; if ( resolved_path != NULL ) { if ( hsd.isPathInUserOrTrickDir(resolved_path)) { ret = true ; } free(resolved_path) ; } } } return ret ; }
bool HeaderSearchDirs::isPathInICGNoComment (std::string in_file ) { char * resolved_path = almostRealPath(in_file.c_str() ) ; if ( resolved_path != NULL ) { std::string dir = std::string(dirname(resolved_path)) + "/"; if ( icg_nocomment_files.find(dir) == icg_nocomment_files.end() ) { icg_nocomment_files[dir] = false ; std::vector<std::string>::iterator vit ; for ( vit = icg_nocomment_dirs.begin() ; vit != icg_nocomment_dirs.end() ; vit++ ) { if ( ! dir.compare(0, (*vit).size(), (*vit))) { icg_nocomment_files[dir] = true ; break ; } } } free(resolved_path) ; return icg_nocomment_files[dir] ; } return false ; }
void HeaderSearchDirs::AddCompilerBuiltInSearchDirs () { FILE * fp ; char * lineptr = NULL ; char line[1024] ; size_t n = 0 ; ssize_t num_read ; const bool IsUserSupplied = false; const bool IsFramework = false; const bool IsSysRootRelative = true; // Add clang specific include directory first. Only required on linux systems. :( // This is so that ICG will find clang friendly headers first. gcc headers cause // all kinds of problems. On macs all headers are clang friendly. #if __linux std::stringstream icg_dir ; icg_dir << LLVM_HOME << "/lib/clang/" ; icg_dir << __clang_major__ << "." << __clang_minor__ ; #if (__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ >= 4)) #ifdef __clang_patchlevel__ icg_dir << "." << __clang_patchlevel__ ; #endif #endif icg_dir << "/include" ; char * resolved_path = realpath(icg_dir.str().c_str(), NULL ) ; if ( resolved_path != NULL ) { hso.AddPath(resolved_path , clang::frontend::System, IsFramework, IsSysRootRelative); } #endif fp = popen("${TRICK_HOME}/bin/trick-gte TRICK_CPPC" , "r") ; fgets(line , sizeof(line) , fp) ; pclose(fp) ; std::string trick_cppc = std::string(line) ; std::string command ; trick_cppc.erase(trick_cppc.find_last_not_of(" \n\r\t")+1) ; //std::cout << "TRICK_CPPC = " << trick_cppc << std::endl ; command = std::string("echo | ") + trick_cppc + std::string(" -v -xc++ -E - 2>&1") ; //std::cout << "command = " << command << std::endl ; fp = popen(command.c_str() , "r") ; bool dir_line = false ; while (fgets( line , sizeof(line) , fp ) != NULL ) { if ( !strncmp( line, "End of search list.", 19 )) { break ; } else if ( dir_line == true ) { //std::cout << "lineptr = " << lineptr << std::endl ; char * resolved_path = NULL ; std::string dir = std::string(line) ; dir.erase(dir.find_last_not_of(" \n\r\t\f\v") + 1) ; dir.erase(0, dir.find_first_not_of(" ")) ; if ( (n = dir.find(" (framework")) != std::string::npos ) { dir.erase(n) ; } resolved_path = almostRealPath(dir.c_str()) ; //std::cout << "dir = " << dir << std::endl ; if ( resolved_path != NULL ) { //std::cout << "gcc resolved_path = " << resolved_path << std::endl ; hso.AddPath(resolved_path , clang::frontend::System, IsFramework, IsSysRootRelative); free(resolved_path) ; } } else if ( !strncmp( line, "#include <...>", 14 )) { dir_line = true ; } } pclose(fp) ; }
/** Most of the main program is pieced together from examples on the web. We are doing the following. -# Creating lists of include directories, defines, and input files from the command line arguments. -# Initializing the compiler to read C++ code, and setting the compiler to think we are creating code for the default target architecture. -# Creating the necessary source and file managers as well as the preprocessor. -# Adding search directories and creating #define statements for -D command line arguments. -# Telling clang to use our ICGASTConsumer as an ASTConsumer. -# Parse the input file. */ int main( int argc , char * argv[] ) { #if (__clang_major__ >= 6) || ((__clang_major__ == 3) && (__clang_minor__ >= 5)) clang::TargetOptions to; #elif (__clang_major__ == 3) && (__clang_minor__ >= 3) clang::TargetOptions * to = new clang::TargetOptions() ; #else clang::TargetOptions to; #endif clang::CompilerInstance ci; /* Gather all of the command line arguments into lists of include directories, defines, and input files. All other arguments will be ignored. */ llvm::cl::SetVersionPrinter(ICG_version) ; llvm::cl::ParseCommandLineOptions(argc , argv) ; if ( ! validAttributesVersion(attr_version) ) { return -1 ; } /* if ( show_units ) { list_units() ; return 0 ; } */ if ( input_file_names.empty() ) { std::cerr << "No header file specified" << std::endl ; return 1 ; } ci.createDiagnostics(); clang::DiagnosticOptions & diago = ci.getDiagnosticOpts() ; diago.ShowColors = 1 ; ci.getDiagnostics().setIgnoreAllWarnings(true) ; #if ( GCC_MAJOR == 4 ) && ( GCC_MINOR <= 2 ) ci.getDiagnostics().setSuppressAllDiagnostics() ; #endif // Set all of the defaults to c++ clang::CompilerInvocation::setLangDefaults(ci.getLangOpts() , clang::IK_CXX) ; ci.getLangOpts().CXXExceptions = true ; // Activate C++11 parsing ci.getLangOpts().CPlusPlus11 = true ; // Set the default target architecture #if (__clang_major__ >= 6) || (__clang_major__ == 3) && (__clang_minor__ >= 5) to.Triple = llvm::sys::getDefaultTargetTriple(); #elif (__clang_major__ == 3) && (__clang_minor__ >= 3) to->Triple = llvm::sys::getDefaultTargetTriple(); #else to.Triple = llvm::sys::getDefaultTargetTriple(); #endif #if (__clang_major__ >= 6) || (__clang_major__ == 3) && (__clang_minor__ >= 5) std::shared_ptr<clang::TargetOptions> shared_to = std::make_shared<clang::TargetOptions>(to) ; clang::TargetInfo *pti = clang::TargetInfo::CreateTargetInfo(ci.getDiagnostics(), shared_to); #else clang::TargetInfo *pti = clang::TargetInfo::CreateTargetInfo(ci.getDiagnostics(), to); #endif ci.setTarget(pti); // Create all of the necessary managers. ci.createFileManager(); ci.createSourceManager(ci.getFileManager()); #if (__clang_major__ >= 6) || (__clang_major__ == 3) && (__clang_minor__ >= 5) ci.createPreprocessor(clang::TU_Complete); #else ci.createPreprocessor(); #endif clang::HeaderSearch & hs = ci.getPreprocessor().getHeaderSearchInfo() ; clang::HeaderSearchOptions & hso = ci.getHeaderSearchOpts() ; clang::Preprocessor & pp = ci.getPreprocessor() ; // Add all of the include directories to the preprocessor HeaderSearchDirs hsd(hs , hso , pp, sim_services_flag) ; hsd.addSearchDirs ( include_dirs ) ; // Tell the preprocessor to use its default predefines clang::PreprocessorOptions & ppo = ci.getPreprocessorOpts() ; ppo.UsePredefines = true; #if (__clang_major__ == 3) && (__clang_minor__ >= 8) pp.getBuiltinInfo().initializeBuiltins(pp.getIdentifierTable(), pp.getLangOpts()); #else pp.getBuiltinInfo().InitializeBuiltins(pp.getIdentifierTable(), pp.getLangOpts()); #endif // Add all of the #define from the command line to the default predefines. hsd.addDefines ( defines ) ; // Add our comment saver as a comment handler in the preprocessor CommentSaver cs(ci, hsd) ; pp.addCommentHandler(&cs) ; PrintAttributes pa( attr_version, hsd, cs, ci, force, sim_services_flag, output_dir) ; // create new class and enum map files if ( create_map ) { pa.createMapFiles() ; } // Tell the compiler to use our ICGASTconsumer ICGASTConsumer *astConsumer = new ICGASTConsumer(ci, hsd, cs, pa); #if (__clang_major__ >= 6) || ((__clang_major__ == 3) && (__clang_minor__ >= 6)) std::unique_ptr<clang::ASTConsumer> unique_ast(astConsumer) ; ci.setASTConsumer(std::move(unique_ast)); #else ci.setASTConsumer(astConsumer); #endif ci.createASTContext(); ci.createSema(clang::TU_Prefix, NULL); // Get the full path of the file to be read. char * input_file_cp = strdup(input_file_names[0].c_str()) ; char * input_file_file = basename(input_file_cp) ; char * input_file_dir = dirname(input_file_cp) ; char * input_file_full_path = NULL ; std::stringstream os ; os << input_file_dir << "/" << input_file_file ; input_file_full_path = almostRealPath( os.str().c_str() ) ; //std::cout << input_file_full_path << std::endl ; struct stat buffer ; if ( stat ( input_file_full_path , &buffer) != 0 ) { std::cerr << "Could not open file " << input_file_full_path << std::endl ; exit(-1) ; } // Open up the input file and parse it. const clang::FileEntry *pFile = ci.getFileManager().getFile(input_file_full_path); #if (__clang_major__ >= 6) || ((__clang_major__ == 3) && (__clang_minor__ >= 5)) ci.getSourceManager().setMainFileID(ci.getSourceManager().createFileID(pFile, clang::SourceLocation(), clang::SrcMgr::C_User)); #else ci.getSourceManager().createMainFileID(pFile); #endif ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(), &ci.getPreprocessor()); clang::ParseAST(ci.getSema()); ci.getDiagnosticClient().EndSourceFile(); free(input_file_cp) ; free(input_file_full_path) ; if ( ! sim_services_flag ) { pa.printIOMakefile() ; } // Close the map files pa.closeMapFiles() ; // Print the list of headers that have the ICG:(No) comment pa.printICGNoFiles() ; return 0; }
char * almostRealPath( const std::string& in_path ) { return almostRealPath(in_path.c_str()); }