diff --git a/trick_source/codegen/Interface_Code_Gen/FindTrickICG.cpp b/trick_source/codegen/Interface_Code_Gen/FindTrickICG.cpp new file mode 100644 index 00000000..7c653a44 --- /dev/null +++ b/trick_source/codegen/Interface_Code_Gen/FindTrickICG.cpp @@ -0,0 +1,117 @@ + +#include +#include "clang/Lex/Token.h" +#include "clang/Basic/IdentifierTable.h" +#include "FindTrickICG.hh" +#include "Utilities.hh" + +FindTrickICG::FindTrickICG(clang::CompilerInstance & in_ci, HeaderSearchDirs & in_hsd , bool in_print_msgs ) + : ci(in_ci) , hsd(in_hsd) , print_msgs(in_print_msgs) , header_printed(false) { } + +void FindTrickICG::FileChanged(clang::SourceLocation Loc, FileChangeReason Reason, + clang::SrcMgr::CharacteristicKind FileType, + clang::FileID PrevFID ) { + /* + We are interested when the file changes, specifically when we enter and exit a file. + We are maintaining a stack of file names. When a file is entered the name is + pushed to the stack. When a file is exited, we pop a name from the stack. + */ + if ( Loc.isValid() and Loc.isFileID() ) { + clang::PresumedLoc PLoc = ci.getSourceManager().getPresumedLoc(Loc) ; + std::string loc_str ; + if ( ! PLoc.isInvalid()) { + loc_str = PLoc.getFilename() ; + switch (Reason) { + case EnterFile : + included_files.push_back(loc_str) ; + break ; + case ExitFile : + included_files.pop_back() ; + break ; + default: + break ; + } + } + } +} + +void FindTrickICG::If(clang::SourceLocation Loc, clang::SourceRange ConditionRange, bool ConditionValue) { + if ( ConditionRange.isValid() ) { + // Get the full text of the if statement into a string + clang::FullSourceLoc fsl_begin(ConditionRange.getBegin() , ci.getSourceManager()) ; + clang::FullSourceLoc fsl_end(ConditionRange.getEnd() , ci.getSourceManager()) ; + std::string if_text( fsl_begin.getCharacterData() , + (size_t)(fsl_end.getCharacterData() - fsl_begin.getCharacterData())) ; + + // if the if statement contains TRICK_ICG we need to mark it. + if ( if_text.find("TRICK_ICG") != std::string::npos ) { + // for each header in the stack, mark them as being exposed to TRICK_ICG + std::vector::iterator it ; + for ( it = included_files.begin() ; it != included_files.end() ; it++ ) { + hsd.addTrickICGFoundFile(*it) ; + } + // print warning messages. + if ( print_msgs ) { + print_header() ; + std::string loc_str = Loc.printToString(ci.getSourceManager()) ; + std::cout << color(WARNING, + std::string("Warning: TRICK_ICG used in preprocessor conditional ") + loc_str) << std::endl ; + } + } + } +} + +void FindTrickICG::ElIf(clang::SourceLocation Loc, clang::SourceRange ConditionRange, bool ConditionValue) { + // Do the same processing for an #elif statement as an #if statement. + If(Loc,ConditionRange,ConditionValue) ; +} + +void FindTrickICG::Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, const clang::MacroDirective *MD) { + // Get the token name that is being tested. + std::string name = MacroNameTok.getIdentifierInfo()->getName().str() ; + if ( ! name.compare("TRICK_ICG") ) { + std::string loc_str = Loc.printToString(ci.getSourceManager()) ; + // There is a singular ifdef TRICK_ICG in S_source.hh we need to ignore. + if ( (loc_str.find("S_source.hh") == std::string::npos) ) { + // for each header in the stack, mark them as being exposed to TRICK_ICG + std::vector::iterator it ; + for ( it = included_files.begin() ; it != included_files.end() ; it++ ) { + hsd.addTrickICGFoundFile(*it) ; + } + // print warning messages. + if ( print_msgs ) { + print_header() ; + std::cout << color(WARNING,std::string("Warning: ifdef TRICK_ICG found ") + loc_str) << std::endl ; + } + } + } + +} + +void FindTrickICG::Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, const clang::MacroDirective *MD) { + // Get the token name that is being tested. + std::string name = MacroNameTok.getIdentifierInfo()->getName().str() ; + if ( ! name.compare("TRICK_ICG") ) { + std::string loc_str = Loc.printToString(ci.getSourceManager()) ; + // for each header in the stack, mark them as being exposed to TRICK_ICG + std::vector::iterator it ; + for ( it = included_files.begin() ; it != included_files.end() ; it++ ) { + hsd.addTrickICGFoundFile(*it) ; + } + // print warning messages. + if ( print_msgs ) { + print_header() ; + std::cout << color(WARNING, std::string("Warning: ifndef TRICK_ICG found ") + loc_str) << std::endl ; + } + } +} + +void FindTrickICG::print_header() { + // Print the warning message once. + if ( ! header_printed ) { + std::cout << color(WARNING, std::string( + "Warning: TRICK_ICG found in one or more header files. The use of TRICK_ICG precludes the use of\n" + "some C++ class/structures in these headers. Consider removing the TRICK_ICG preprocessor conditionals\n")) ; + header_printed = true ; + } +} diff --git a/trick_source/codegen/Interface_Code_Gen/FindTrickICG.hh b/trick_source/codegen/Interface_Code_Gen/FindTrickICG.hh new file mode 100644 index 00000000..57cf6455 --- /dev/null +++ b/trick_source/codegen/Interface_Code_Gen/FindTrickICG.hh @@ -0,0 +1,47 @@ + +#include +#include +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Lex/PPCallbacks.h" +#include "HeaderSearchDirs.hh" + +/* + FindTrickICG searches preprocessor directives #if/#elif/#ifdef/#ifndef to see if they use TRICK_ICG + If they do reference TRICK_ICG we need to mark the stack of incude files that include the TRICK_ICG. + We also print a warning to the screen where the TRICK_ICG was found. + */ + +class FindTrickICG : public clang::PPCallbacks { + public: + FindTrickICG(clang::CompilerInstance & in_ci , HeaderSearchDirs & in_hsd , bool in_print_msgs ) ; + + // called when the file changes for a variety of reasons. + virtual void FileChanged(clang::SourceLocation Loc, FileChangeReason Reason, + clang::SrcMgr::CharacteristicKind FileType, + clang::FileID PrevFID = clang::FileID()) ; + + // callbacks called when the preprocessor directives of types are processed. + virtual void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange, bool ConditionValue) ; + virtual void ElIf(clang::SourceLocation Loc, clang::SourceRange ConditionRange, bool ConditionValue) ; + virtual void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, const clang::MacroDirective *MD) ; + virtual void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, const clang::MacroDirective *MD) ; + + // print a warning about using TRICK_ICG. + void print_header() ; + + private: + + // compiler instance to help locating file names + clang::CompilerInstance & ci ; + + HeaderSearchDirs & hsd ; + + // Are we printing warning messages? + bool print_msgs ; + + // Have we printed the big warning about TRICK_ICG? + bool header_printed ; + + // Using a vector as a stack to hold the stack of included headers we have entered. + std::vector included_files ; +} ; diff --git a/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.cpp b/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.cpp index 357844a1..dbc652b5 100644 --- a/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.cpp +++ b/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.cpp @@ -305,6 +305,9 @@ bool HeaderSearchDirs::isPathInCompat15 (const std::string& in_dir ) { return true ; } } + if ( trick_icg_present.find(in_dir) != trick_icg_present.end() ) { + return true ; + } return false ; } @@ -363,3 +366,11 @@ void HeaderSearchDirs::addDefines ( std::vector & defines ) { pp.setPredefines(pp.getPredefines() + "\n" + predefines) ; } + +void HeaderSearchDirs::addTrickICGFoundFile ( std::string file_name ) { + char * rp = almostRealPath(file_name.c_str()) ; + if ( rp != NULL ) { + trick_icg_present.insert(rp) ; + free(rp) ; + } +} diff --git a/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.hh b/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.hh index ee6457b3..fd41ca3e 100644 --- a/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.hh +++ b/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.hh @@ -105,6 +105,11 @@ class HeaderSearchDirs { */ void addDefines ( std::vector & defines ) ; + /** Add a file name to the set of files that we found TRICK_ICG used. + @param file_name = file_name string + */ + void addTrickICGFoundFile ( std::string file_name ) ; + private: /** Are we ICG'ing the sim_services files? */ bool sim_services ; @@ -154,8 +159,12 @@ class HeaderSearchDirs { /** List of directoris to write offsetof lines compatible with Trick 15 and earlier */ std::vector compat15_dirs ; + /** set of file names with trick_icg_present */ + std::set< std::string > trick_icg_present ; + /** Map of file names to in icg_nocomment_dir used as a cache */ std::map< std::string , bool > icg_nocomment_files ; + } ; #endif diff --git a/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp b/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp index 5f968945..211a78ae 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp +++ b/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp @@ -201,27 +201,6 @@ void PrintFileContents10::print_init_attr_func( std::ostream & ostream , ClassVa << " }\n" << " initialized = 1;\n\n" ; -#if 0 - if ( cv->getMangledTypeName() != cv->getName() ) { - ostream << " typedef " << cv->getName() << " " << cv->getMangledTypeName() << " ;\n\n" ; - } - - if ( !global_compat15 and !cv->isCompat15()) { - ostream << " if ( sizeof(" ; - printNamespaces( ostream, cv , "::" ) ; - printContainerClasses( ostream, cv , "::" ) ; - ostream << cv->getName() << ") > " << cv->getSize() << ") {\n" ; - ostream << " Trick::ClassSizeCheck::class_size_check()->add_diff(\"" ; - printNamespaces( ostream, cv , "::" ) ; - printContainerClasses( ostream, cv , "::" ) ; - ostream << cv->getName() << "\" , Trick::ClassSizeDiffInfo((sizeof(" ; - printNamespaces( ostream, cv , "::" ) ; - printContainerClasses( ostream, cv , "::" ) ; - ostream << cv->getName() << ") - " << cv->getSize() << ") , \"" << cv->getFileName() << "\")) ;\n" ; - ostream << " }\n" ; - } -#endif - unsigned int ii = 0; for ( auto field : cv->getFieldDescriptions() ) { if ( determinePrintAttr(cv, field) ) { diff --git a/trick_source/codegen/Interface_Code_Gen/main.cpp b/trick_source/codegen/Interface_Code_Gen/main.cpp index d9b541ac..1d31c0cd 100644 --- a/trick_source/codegen/Interface_Code_Gen/main.cpp +++ b/trick_source/codegen/Interface_Code_Gen/main.cpp @@ -23,6 +23,7 @@ #include "TranslationUnitVisitor.hh" #include "PrintAttributes.hh" #include "Utilities.hh" +#include "FindTrickICG.hh" /* Command line arguments. These work better as globals, as suggested in llvm/CommandLine documentation */ llvm::cl::list include_dirs("I", llvm::cl::Prefix, llvm::cl::desc("Include directory"), llvm::cl::value_desc("directory")); @@ -41,6 +42,7 @@ llvm::cl::list sink(llvm::cl::Sink, llvm::cl::ZeroOrMore); llvm::cl::list pre_compiled_headers("include", llvm::cl::Prefix, llvm::cl::desc("pre-compiled headers"), llvm::cl::value_desc("pre_compiled_headers")); llvm::cl::opt global_compat15("c", llvm::cl::desc("Print the offsetof calculations in attributes")) ; +llvm::cl::opt print_trick_icg("print-TRICK-ICG", llvm::cl::desc("Print warnings where TRICK_ICG may cause io_src inconsistencies")) ; llvm::cl::alias compat15_alias ("compat15" , llvm::cl::desc("Alias for -c") , llvm::cl::aliasopt(global_compat15)) ; /** @@ -125,6 +127,10 @@ int main(int argc, char * argv[]) { HeaderSearchDirs hsd(ci.getPreprocessor().getHeaderSearchInfo(), ci.getHeaderSearchOpts(), pp, sim_services_flag); hsd.addSearchDirs(include_dirs); + // Add a preprocessor callback to search for TRICK_ICG + FindTrickICG * ftg = new FindTrickICG(ci, hsd, print_trick_icg != llvm::cl::BOU_FALSE ) ; + pp.addPPCallbacks(ftg) ; + #if (LIBCLANG_MAJOR > 3) || ((LIBCLANG_MAJOR == 3) && (LIBCLANG_MINOR >= 8)) pp.getBuiltinInfo().initializeBuiltins(pp.getIdentifierTable(), pp.getLangOpts()); #else