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
This commit is contained in:
Alex Lin 2016-04-06 08:23:23 -05:00
parent fc98f6cf0a
commit 7dcc65d0bd
11 changed files with 114 additions and 45 deletions

View File

@ -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<FieldDescription *>::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 ;
}

View File

@ -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 ;
} ;

View File

@ -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<clang::FieldDecl *>(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<clang::VarDecl *>(d)) ;
cval.addFieldDescription(fvis.get_field_data()) ;
}
break ;
case clang::Decl::AccessSpec : {
access_spec_found = true ;
}
case clang::Decl::AccessSpec :
break ;
default :
break ;

View File

@ -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( &reg_expr , "(INVADE[ _]PRIVACY:)" , REG_EXTENDED | REG_ICASE ) ;
ret = regexec( &reg_expr , th_str.c_str() , 10 , pmatch , 0 ) ;
regfree(&reg_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) ;

View File

@ -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 ;

View File

@ -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 ;

View File

@ -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 ;

View File

@ -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() ;

View File

@ -32,7 +32,6 @@ class FieldVisitor : public clang::RecursiveASTVisitor<FieldVisitor> {
CommentSaver & cs ,
PrintAttributes & in_pa ,
std::string container_class ,
bool access_spec_found ,
bool inherited ,
bool virtual_inherited ,
unsigned int base_class_offset ) ;

View File

@ -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" ;

View File

@ -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 ;
}