From 7dcc65d0bd0d3e9312387dfbaa5a3c3dbb433ad2 Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Wed, 6 Apr 2016 08:23:23 -0500 Subject: [PATCH] Ignore privacy Mostly working. This removes the use of offsetof from all I/O code. This was the only reason we needed friends. In it's place we put the offset value that clang has calculated for the field. Still need to work on virtually inherited classes and confirm bitfields. refs #218 --- .../Interface_Code_Gen/ClassValues.cpp | 12 ++++++- .../codegen/Interface_Code_Gen/ClassValues.hh | 5 +++ .../Interface_Code_Gen/ClassVisitor.cpp | 11 +++---- .../Interface_Code_Gen/CommentSaver.cpp | 22 +++++++++++++ .../Interface_Code_Gen/CommentSaver.hh | 9 ++++++ .../Interface_Code_Gen/FieldDescription.cpp | 25 ++++++++++----- .../Interface_Code_Gen/FieldDescription.hh | 15 ++++++--- .../Interface_Code_Gen/FieldVisitor.cpp | 9 ++++-- .../Interface_Code_Gen/FieldVisitor.hh | 1 - .../PrintFileContents10.cpp | 19 +++++++++--- .../PrintFileContentsBase.cpp | 31 +++++++++---------- 11 files changed, 114 insertions(+), 45 deletions(-) diff --git a/trick_source/codegen/Interface_Code_Gen/ClassValues.cpp b/trick_source/codegen/Interface_Code_Gen/ClassValues.cpp index 031912cb..68a2270c 100644 --- a/trick_source/codegen/Interface_Code_Gen/ClassValues.cpp +++ b/trick_source/codegen/Interface_Code_Gen/ClassValues.cpp @@ -12,7 +12,9 @@ ClassValues::ClassValues(bool in_inherit, bool in_virtual_inherit) : is_pod(false) , is_abstract(false) , has_default_constructor(false) , - has_public_destructor(false) {} + has_public_destructor(false) , + invade_privacy(false) +{} ClassValues::~ClassValues() { std::vector::iterator fdit ; @@ -232,6 +234,14 @@ bool ClassValues::getHasPublicDestructor() { return has_public_destructor ; } +void ClassValues::setInvadePrivacy(bool in_val) { + invade_privacy = in_val ; +} + +bool ClassValues::getInvadePrivacy() { + return invade_privacy ; +} + void ClassValues::setMangledTypeName( std::string in_val ) { mangled_type_name = in_val ; } diff --git a/trick_source/codegen/Interface_Code_Gen/ClassValues.hh b/trick_source/codegen/Interface_Code_Gen/ClassValues.hh index 3c9f6c97..520f9509 100644 --- a/trick_source/codegen/Interface_Code_Gen/ClassValues.hh +++ b/trick_source/codegen/Interface_Code_Gen/ClassValues.hh @@ -76,6 +76,8 @@ class ClassValues : public ConstructValues { void setHasPublicDestructor(bool in_val) ; bool getHasPublicDestructor() ; void setMangledTypeName( std::string in_val ) ; + bool getInvadePrivacy() ; + void setInvadePrivacy( bool in_val ) ; std::string getMangledTypeName() ; std::string getFullyQualifiedMangledTypeName() ; @@ -117,6 +119,9 @@ class ClassValues : public ConstructValues { /** Does this class have a public destructor? */ bool has_public_destructor ; + /** Should we invade privacy and write attributes for everything we can? */ + bool invade_privacy ; + /** Mangled type name. Templates will have a mangled_type_name. */ std::string mangled_type_name ; } ; diff --git a/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp b/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp index c216b4d5..1d67a7d9 100644 --- a/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp +++ b/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp @@ -32,8 +32,7 @@ CXXRecordVisitor::CXXRecordVisitor( pa(in_pa) , cval(in_inherited , in_virtual_inherited) , include_virtual_base(in_include_virtual_base) , - base_class_offset(in_base_class_offset) , - access_spec_found(false) + base_class_offset(in_base_class_offset) { //cval = new ClassValues(in_inherited , in_virtual_inherited) ; } @@ -82,7 +81,7 @@ bool CXXRecordVisitor::TraverseDecl(clang::Decl *d) { } break ; case clang::Decl::Field : { - FieldVisitor fvis(ci , hsd , cs, pa, cval.getName() , access_spec_found , cval.isInherited(), cval.isVirtualInherited(), base_class_offset) ; + FieldVisitor fvis(ci , hsd , cs, pa, cval.getName() , cval.isInherited(), cval.isVirtualInherited(), base_class_offset) ; fvis.TraverseFieldDecl(static_cast(d)) ; cval.addFieldDescription(fvis.get_field_data()) ; } @@ -93,14 +92,12 @@ bool CXXRecordVisitor::TraverseDecl(clang::Decl *d) { break ; case clang::Decl::Var : { /* Static fields appear as vars. Treat it as a field. */ - FieldVisitor fvis(ci , hsd , cs, pa, cval.getName() , access_spec_found , cval.isInherited(), cval.isVirtualInherited(), base_class_offset) ; + FieldVisitor fvis(ci , hsd , cs, pa, cval.getName() , cval.isInherited(), cval.isVirtualInherited(), base_class_offset) ; fvis.TraverseVarDecl(static_cast(d)) ; cval.addFieldDescription(fvis.get_field_data()) ; } break ; - case clang::Decl::AccessSpec : { - access_spec_found = true ; - } + case clang::Decl::AccessSpec : break ; default : break ; diff --git a/trick_source/codegen/Interface_Code_Gen/CommentSaver.cpp b/trick_source/codegen/Interface_Code_Gen/CommentSaver.cpp index b75dd5af..66de220b 100644 --- a/trick_source/codegen/Interface_Code_Gen/CommentSaver.cpp +++ b/trick_source/codegen/Interface_Code_Gen/CommentSaver.cpp @@ -84,6 +84,7 @@ void CommentSaver::getICGField( std::string file_name ) { /* default the icg_no flags to false */ icg_no_found[file_name] = false ; icg_no_comment_found[file_name] = false ; + invade_privacy[file_name] = false ; std::string th_str = getTrickHeaderComment(file_name) ; if ( ! th_str.empty() ) { @@ -113,6 +114,10 @@ void CommentSaver::getICGField( std::string file_name ) { exit(-1) ; } } + size_t trick_parse_invade_privacy = th_str.find("trick_invade_privacy") ; + if ( trick_parse_invade_privacy != std::string::npos ) { + invade_privacy[file_name] = true ; + } } else { std::transform(th_str.begin(), th_str.end(), th_str.begin(), ::toupper) ; @@ -121,6 +126,14 @@ void CommentSaver::getICGField( std::string file_name ) { regmatch_t pmatch[10] ; memset(pmatch , 0 , sizeof(pmatch)) ; + ret = regcomp( ®_expr , "(INVADE[ _]PRIVACY:)" , REG_EXTENDED | REG_ICASE ) ; + ret = regexec( ®_expr , th_str.c_str() , 10 , pmatch , 0 ) ; + regfree(®_expr) ; + + if ( ret == 0 ) { + invade_privacy[file_name] = true ; + } + /* POSIX regular expressions are always greedy, making our job harder. We have to use several regular expressions to get the types. This was so much easier in perl! */ @@ -193,6 +206,15 @@ bool CommentSaver::hasICGNoComment( std::string file_name ) { return icg_no_comment_found[file_name] ; } +bool CommentSaver::hasInvadePrivacy( std::string file_name ) { + + if ( invade_privacy.find(file_name) == invade_privacy.end() ) { + getICGField(file_name) ; + } + + return invade_privacy[file_name] ; +} + std::set< std::string > CommentSaver::getIgnoreTypes( std::string file_name ) { std::set< std::string > ignore_types ; std::string th_str = getTrickHeaderComment(file_name) ; diff --git a/trick_source/codegen/Interface_Code_Gen/CommentSaver.hh b/trick_source/codegen/Interface_Code_Gen/CommentSaver.hh index 22c5add8..cb95e975 100644 --- a/trick_source/codegen/Interface_Code_Gen/CommentSaver.hh +++ b/trick_source/codegen/Interface_Code_Gen/CommentSaver.hh @@ -77,6 +77,12 @@ class CommentSaver : public clang::CommentHandler { */ bool hasICGNoComment( std::string file_name ) ; + /** Searches the Trick header comment for the Invade_Privacy:() entry. + @param file_name = File name to search + @return true = ICG:(NoComment) was found. + */ + bool hasInvadePrivacy( std::string file_name ) ; + /** Searches the Trick header comment for the ICG_EXCLUDE_TYPES field @param file_name = File name to search @return set of strings that list the type names to ignore. @@ -95,6 +101,9 @@ class CommentSaver : public clang::CommentHandler { /** Map of file name to ICG: (NoComment) found */ std::map < std::string , bool > icg_no_comment_found ; + /** Map of file name to ICG: (NoComment) found */ + std::map < std::string , bool > invade_privacy ; + /** All comments source locations indexed by file name then line number */ std::map < std::string , std::map < unsigned int , clang::SourceRange > > comment_map ; diff --git a/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp b/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp index 19fb361f..c0bfd6b2 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp +++ b/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp @@ -16,13 +16,13 @@ FieldDescription::FieldDescription( std::string in_container_class , - bool in_access_spec_found , bool in_inherited , bool in_virtual_inherited , unsigned int in_base_class_offset) : container_class(in_container_class) , base_class_offset(in_base_class_offset) , - access_spec_found(in_access_spec_found) , + field_offset(0) , + field_width(0) , inherited(in_inherited) , virtual_inherited(in_virtual_inherited) , units("--") , @@ -251,6 +251,22 @@ unsigned int FieldDescription::getBaseClassOffset() { return base_class_offset ; } +void FieldDescription::setFieldOffset(unsigned int in_offset) { + field_offset = in_offset ; +} + +unsigned int FieldDescription::getFieldOffset() { + return field_offset ; +} + +void FieldDescription::setFieldWidth(unsigned int in_width) { + field_width = in_width ; +} + +unsigned int FieldDescription::getFieldWidth() { + return field_width ; +} + void FieldDescription::setNonCanonicalTypeName( std::string in_val ) { non_canonical_type_name = in_val ; } @@ -302,10 +318,6 @@ std::string FieldDescription::getDescription() { return description ; } -bool FieldDescription::getAccessSpecFound() { - return access_spec_found ; -} - bool FieldDescription::isInherited() { return inherited ; } @@ -440,7 +452,6 @@ std::ostream & operator << (std::ostream & os , FieldDescription & fdes ) { os << " io = " << fdes.io << std::endl ; os << " description = " << fdes.description << std::endl ; os << " access = " << fdes.access << std::endl ; - os << " access_spec_found = " << fdes.access_spec_found << std::endl ; os << " is_bitfield = " << fdes.is_bitfield << std::endl ; os << " bitfield_width = " << fdes.bitfield_width << std::endl ; os << " bitfield_start_bit = " << fdes.bitfield_start_bit << std::endl ; diff --git a/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh b/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh index 2c3e5db5..3a0952bf 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh +++ b/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh @@ -31,7 +31,6 @@ class FieldDescription : public ConstructValues { /* Default the inheritance to false */ FieldDescription( std::string in_container_class , - bool access_spec_found , bool inherited , bool virtual_inherited , unsigned int base_class_offset ) ; @@ -43,6 +42,10 @@ class FieldDescription : public ConstructValues { std::string getContainerClass() ; void setContainerClass( std::string in_name ) ; unsigned int getBaseClassOffset() ; + void setFieldOffset( unsigned int in_offset ) ; + unsigned int getFieldOffset() ; + void setFieldWidth( unsigned int in_offset ) ; + unsigned int getFieldWidth() ; void setNonCanonicalTypeName( std::string in_val ) ; std::string getNonCanonicalTypeName() ; void setTypeName( std::string in_val ) ; @@ -78,7 +81,6 @@ class FieldDescription : public ConstructValues { bool hasSTLClear() ; void setStatic( bool yes_no ) ; bool isStatic() ; - bool getAccessSpecFound() ; bool isInherited() ; bool isVirtualInherited() ; void setAccess( clang::AccessSpecifier in_val ) ; @@ -101,6 +103,12 @@ class FieldDescription : public ConstructValues { be added to field offset */ unsigned int base_class_offset ; + /** The total offset to the current field in bytes */ + unsigned int field_offset ; + + /** The size of the current field in bytes */ + unsigned int field_width ; + /** Name of the type. Non-canonical. It's what was actually read in input file */ std::string non_canonical_type_name ; @@ -144,9 +152,6 @@ class FieldDescription : public ConstructValues { /** dimensions sizes */ int array_sizes[8] ; - /** does this field follow a public/private/protected keyword */ - bool access_spec_found ; - /** is this field inherited from parent class */ bool inherited ; diff --git a/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp b/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp index 96e7e418..a3115e5b 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp +++ b/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp @@ -22,7 +22,6 @@ FieldVisitor::FieldVisitor(clang::CompilerInstance & in_ci , CommentSaver & in_cs , PrintAttributes & in_pa , std::string container_class , - bool in_access_spec_found , bool in_inherited , bool in_virtual_inherited , unsigned int in_base_class_offset ) : @@ -30,7 +29,7 @@ FieldVisitor::FieldVisitor(clang::CompilerInstance & in_ci , hsd(in_hsd) , cs(in_cs) , pa(in_pa) { - fdes = new FieldDescription(container_class, in_access_spec_found, in_inherited, in_virtual_inherited, in_base_class_offset) ; + fdes = new FieldDescription(container_class, in_inherited, in_virtual_inherited, in_base_class_offset) ; } bool FieldVisitor::VisitDecl(clang::Decl *d) { @@ -206,6 +205,8 @@ bool FieldVisitor::VisitFieldDecl( clang::FieldDecl *field ) { fdes->setBitFieldStart( 32 - (field_offset_bits % 32) - fdes->getBitFieldWidth()) ; fdes->setBitFieldByteOffset((field_offset_bits / 32) * 4 ) ; } + // set the offset to the field + fdes->setFieldOffset(field->getASTContext().getFieldOffset(field) / 8 + fdes->getBaseClassOffset()) ; // If the current type is not canonical because of typedefs or template parameter substitution, // traverse the canonical type @@ -216,6 +217,10 @@ bool FieldVisitor::VisitFieldDecl( clang::FieldDecl *field ) { std::cout << " is_canonical = " << qt.isCanonical() << std::endl ; //field->dump() ; } + + // set the offset to the field + fdes->setFieldWidth(field->getASTContext().getTypeSize(qt) / 8) ; + if ( !qt.isCanonical() ) { fdes->setNonCanonicalTypeName(qt.getAsString()) ; clang::QualType ct = qt.getCanonicalType() ; diff --git a/trick_source/codegen/Interface_Code_Gen/FieldVisitor.hh b/trick_source/codegen/Interface_Code_Gen/FieldVisitor.hh index 09a4cc06..354d64ac 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldVisitor.hh +++ b/trick_source/codegen/Interface_Code_Gen/FieldVisitor.hh @@ -32,7 +32,6 @@ class FieldVisitor : public clang::RecursiveASTVisitor { CommentSaver & cs , PrintAttributes & in_pa , std::string container_class , - bool access_spec_found , bool inherited , bool virtual_inherited , unsigned int base_class_offset ) ; diff --git a/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp b/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp index 30895f16..0c1b02eb 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp +++ b/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp @@ -82,12 +82,12 @@ void PrintFileContents10::print_field_attr(std::ofstream & outfile , FieldDescr outfile << fdes->getMangledTypeName() << "\""; // end type_name outfile << ", \"" << fdes->getUnits() << "\"" ; // units outfile << ", \"\", \"\"," << std::endl ; // alias , user_defined - outfile << " \"" << fdes->getDescription() << "\"," << std::endl ; // des + outfile << " \"" << fdes->getDescription() << "\"," << std::endl ; // description outfile << " " << fdes->getIO() ; // io outfile << "," << fdes->getEnumString() ; // type - outfile << ",0,0,0,Language_CPP" ; // size, range_min, range_max, language + outfile << "," << fdes->getFieldWidth() << ",0,0,Language_CPP" ; // size, range_min, range_max, language outfile << "," << (fdes->isStatic() << 1 ) << "," << std::endl ; // mods - outfile << " " << "0" << ",NULL" ; // offset, attr + outfile << " " << fdes->getFieldOffset() << ",NULL" ; // offset, attr outfile << "," << fdes->getNumDims() ; // num_index outfile << ",{" ; @@ -128,7 +128,8 @@ void PrintFileContents10::print_class_attr(std::ofstream & outfile , ClassValues outfile << "," << std::endl ; } } - FieldDescription * new_fdes = new FieldDescription(std::string(""), true, false, false, 0) ; + // Print an empty sentinel attribute at the end of the class. + FieldDescription * new_fdes = new FieldDescription(std::string(""), false, false, 0) ; print_field_attr(outfile, new_fdes) ; outfile << " };" << std::endl ; delete new_fdes ; @@ -139,6 +140,9 @@ void PrintFileContents10::print_class_attr(std::ofstream & outfile , ClassValues /** Prints init_attr function for each class */ void PrintFileContents10::print_field_init_attr_stmts( std::ofstream & outfile , FieldDescription * fdes , ClassValues * cv ) { + // Static bitfields do not get to this point, they are filtered out in determinePrintAttr + + // Always print offset of a static variable if ( fdes->isStatic() ) { // print a special offsetof statement if this is a static outfile << " attr" ; @@ -148,7 +152,9 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ofstream & outfile , printNamespaces( outfile, cv , "::" ) ; printContainerClasses( outfile, cv , "::" ) ; outfile << cv->getName() << "::" << fdes->getName() << " ;\n" ; - } else if ( fdes->isBitField() ) { + } + + if ( fdes->isBitField() ) { // else if this is a bitfield outfile << " attr" ; printNamespaces( outfile, cv , "__" ) ; @@ -161,6 +167,8 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ofstream & outfile , printNamespaces( outfile, cv , "__" ) ; printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() << "[i].size = sizeof(unsigned int) ;\n" ; + } +#if 0 } else if ( fdes->isVirtualInherited() ) { // else if we have a virtually inherited class. outfile << " attr" ; @@ -188,6 +196,7 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ofstream & outfile , printContainerClasses( outfile, cv , "::" ) ; outfile << cv->getMangledTypeName() << "," << fdes->getName() << ") ;\n" ; } +#endif if ( !fdes->isRecord() and !fdes->isEnum() and !fdes->isBitField() and !fdes->isSTL()) { outfile << " attr" ; diff --git a/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp b/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp index 7af34e5b..b029b64c 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp +++ b/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp @@ -74,25 +74,22 @@ void PrintFileContentsBase::print_close_extern_c(std::ofstream & outfile) { */ bool PrintFileContentsBase::determinePrintAttr( ClassValues * c , FieldDescription * fdes ) { if ( fdes->getTypeName().compare("void") and fdes->getIO() != 0 and fdes->getEnumString().compare("TRICK_VOID")) { - if ( fdes->isInherited() ) { - return ((c->getHasInitAttrFriend() && fdes->getAccess() == clang::AS_protected) - || (fdes->getAccess() == clang::AS_public)) ; + if ( fdes->isStatic() ) { + // Cannot take the address of a bitfield, attributes need the address of static variables. + // return false if we have a static bitfield + if ( fdes->isBitField() ) { + return false ; + } + if ( fdes->isInherited() ) { + return ((c->getHasInitAttrFriend() && fdes->getAccess() == clang::AS_protected) + || (fdes->getAccess() == clang::AS_public)) ; + } else { + return (c->getHasInitAttrFriend() + || (fdes->getAccess() == clang::AS_public)) ; + } } else { - return (c->getHasInitAttrFriend() - || (fdes->getAccess() == clang::AS_public)) ; + return true ; } -#if 0 - // Use this version when/if we decide to #define private public. - if ( fdes->isInherited() ) { - return ((c->getHasInitAttrFriend() && fdes->getAccess() == clang::AS_protected) - || (fdes->getAccess() == clang::AS_public) - || fdes->getAccessSpecFound()) ; - } else { - return (c->getHasInitAttrFriend() - || (fdes->getAccess() == clang::AS_public) - || fdes->getAccessSpecFound()) ; - } -#endif } return false ; }