mirror of
https://github.com/nasa/trick.git
synced 2024-12-24 07:16:41 +00:00
Detect when TRICK_ICG is used in header files and compensate for it. #375
Created a hook for the clang preprocessor. The hook does 2 things. It keeps track to which header files we have entered and exited. Second it searches for the use of TRICK_ICG. If we find an instance of TRICK_ICG we mark all of the included files from this point up the chain as requiring compensation. To compensate for using TRICK_ICG we write out the older offset statements to get the location of variables in classes/structures.
This commit is contained in:
parent
0140b0b966
commit
ba47c2048c
117
trick_source/codegen/Interface_Code_Gen/FindTrickICG.cpp
Normal file
117
trick_source/codegen/Interface_Code_Gen/FindTrickICG.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
|
||||
#include <iostream>
|
||||
#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<std::string>::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<std::string>::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<std::string>::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 ;
|
||||
}
|
||||
}
|
47
trick_source/codegen/Interface_Code_Gen/FindTrickICG.hh
Normal file
47
trick_source/codegen/Interface_Code_Gen/FindTrickICG.hh
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#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<std::string> included_files ;
|
||||
} ;
|
@ -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<std::string> & 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) ;
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +105,11 @@ class HeaderSearchDirs {
|
||||
*/
|
||||
void addDefines ( std::vector<std::string> & 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<std::string> 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
|
||||
|
@ -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) ) {
|
||||
|
@ -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<std::string> include_dirs("I", llvm::cl::Prefix, llvm::cl::desc("Include directory"), llvm::cl::value_desc("directory"));
|
||||
@ -41,6 +42,7 @@ llvm::cl::list<std::string> sink(llvm::cl::Sink, llvm::cl::ZeroOrMore);
|
||||
llvm::cl::list<std::string> pre_compiled_headers("include", llvm::cl::Prefix, llvm::cl::desc("pre-compiled headers"), llvm::cl::value_desc("pre_compiled_headers"));
|
||||
|
||||
llvm::cl::opt<bool> global_compat15("c", llvm::cl::desc("Print the offsetof calculations in attributes")) ;
|
||||
llvm::cl::opt<llvm::cl::boolOrDefault> 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
|
||||
|
Loading…
Reference in New Issue
Block a user