From 54591ec005b70c5e7cfff150ba0a39f1e5f7bc2e Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Wed, 13 Apr 2016 16:01:59 -0500 Subject: [PATCH] Ignore privacy Found some of those uncommon cases like inheriting from templates which contain private embedded classes. refs #218 --- .../ClassTemplateVisitor.cpp | 27 +++++++-- .../Interface_Code_Gen/ClassVisitor.cpp | 35 +++++++++++ .../Interface_Code_Gen/ClassVisitor.hh | 1 + .../Interface_Code_Gen/FieldVisitor.cpp | 60 +++++++++++++------ .../PrintFileContents10.cpp | 24 ++++++++ 5 files changed, 124 insertions(+), 23 deletions(-) diff --git a/trick_source/codegen/Interface_Code_Gen/ClassTemplateVisitor.cpp b/trick_source/codegen/Interface_Code_Gen/ClassTemplateVisitor.cpp index ebabf79d..bd36bf61 100644 --- a/trick_source/codegen/Interface_Code_Gen/ClassTemplateVisitor.cpp +++ b/trick_source/codegen/Interface_Code_Gen/ClassTemplateVisitor.cpp @@ -43,6 +43,27 @@ bool ClassTemplateVisitor::TraverseDecl(clang::Decl *d) { switch ( d->getKind() ) { case clang::Decl::CXXRecord : { TraverseCXXRecordDecl(static_cast(d)) ; + + clang::CXXRecordDecl * crd = static_cast(d) ; + /* The definition of the record must exist before we can process it. The definition is + NULL when this is only a forward declaration of a class. We also only want to + process embedded classes that have public access. */ + clang::RecordDecl * rd = crd->getDefinition() ; + if ( rd != NULL ) { + //d->dump() ; + //std::cout << "access = " << rd->getAccess() << std::endl << std::endl ; + if ( rd->getAccess() == clang::AS_protected || rd->getAccess() == clang::AS_private ) { + // protected and private embedded classes cannot be used outside of their class + // in our auto-generated code. Keep a set of all classes of this type so we can + // test against them. + ClassValues temp_cv ; + temp_cv.getNamespacesAndClasses(crd->getDeclContext()) ; + //std::cout << "marking private " << temp_cv.getFullyQualifiedName() + crd->getNameAsString() << std::endl ; + CXXRecordVisitor::addPrivateEmbeddedClass(temp_cv.getFullyQualifiedName() + crd->getNameAsString()) ; + } else { + TraverseCXXRecordDecl(static_cast(d)) ; + } + } } break ; case clang::Decl::Enum : { @@ -54,10 +75,8 @@ bool ClassTemplateVisitor::TraverseDecl(clang::Decl *d) { } EnumVisitor evis(ci, hsd) ; evis.TraverseDecl(ed) ; - //if ( evis.get_enum_data() != NULL ) { - evis.get_enum_data()->setHasDefinition(false) ; - pa.printEnum(evis.get_enum_data()) ; - //} + evis.get_enum_data()->setHasDefinition(false) ; + pa.printEnum(evis.get_enum_data()) ; } } diff --git a/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp b/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp index 2b6d94c2..79bf41bc 100644 --- a/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp +++ b/trick_source/codegen/Interface_Code_Gen/ClassVisitor.cpp @@ -1,6 +1,7 @@ #include #include +#include #include "llvm/Support/CommandLine.h" #include "clang/Basic/SourceManager.h" @@ -307,6 +308,10 @@ ClassValues * CXXRecordVisitor::get_class_data() { std::set CXXRecordVisitor::private_embedded_classes ; +void CXXRecordVisitor::addPrivateEmbeddedClass( std::string in_name ) { + private_embedded_classes.insert(in_name) ; +} + bool CXXRecordVisitor::isPrivateEmbeddedClass( std::string in_name ) { size_t pos ; while ((pos = in_name.find("class ")) != std::string::npos ) { @@ -315,6 +320,36 @@ bool CXXRecordVisitor::isPrivateEmbeddedClass( std::string in_name ) { while ((pos = in_name.find("struct ")) != std::string::npos ) { in_name.erase(pos , 7) ; } + while ((pos = in_name.find("const ")) != std::string::npos ) { + in_name.erase(pos , 6) ; + } + // remove any array or pointer dimensions. + if ( in_name.find_first_of("[*") != std::string::npos ) { + in_name.erase(in_name.find_first_of("[*")) ; + } + // remove trailing spaces + in_name.erase(std::find_if(in_name.rbegin(), in_name.rend(), + std::not1(std::ptr_fun(std::isspace))).base(), in_name.end()); + + // remove all template arguments "" + bool template_arg_found ; + do { + template_arg_found = false ; + std::stack bracket_pos ; + for ( int ii = 0 ; ii < in_name.length() ; ii++ ) { + if ( in_name[ii] == '<' ) { + bracket_pos.push(ii) ; + } else if ( in_name[ii] == '>' ) { + int begin = bracket_pos.top() ; + bracket_pos.pop() ; + if ( bracket_pos.empty() ) { + template_arg_found = true ; + in_name.erase(begin, ii - begin + 1) ; + break ; + } + } + } + } while ( template_arg_found == true ) ; std::set::iterator it ; it = private_embedded_classes.find(in_name) ; diff --git a/trick_source/codegen/Interface_Code_Gen/ClassVisitor.hh b/trick_source/codegen/Interface_Code_Gen/ClassVisitor.hh index 1280ffec..30676c39 100644 --- a/trick_source/codegen/Interface_Code_Gen/ClassVisitor.hh +++ b/trick_source/codegen/Interface_Code_Gen/ClassVisitor.hh @@ -55,6 +55,7 @@ class CXXRecordVisitor : public clang::RecursiveASTVisitor { /** Returns the class data */ ClassValues * get_class_data() ; + static void addPrivateEmbeddedClass(std::string in_name) ; static bool isPrivateEmbeddedClass(std::string in_name) ; private: /** The compiler instance. */ diff --git a/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp b/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp index a888f5b6..6f44c9b9 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp +++ b/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp @@ -343,7 +343,7 @@ static std::map init_stl_classes() { return my_map ; } -static bool checkForPRivateTemplateArgs( clang::ClassTemplateSpecializationDecl * ctsd ) { +static bool checkForPrivateTemplateArgs( clang::ClassTemplateSpecializationDecl * ctsd ) { unsigned int ii ; for ( ii = 0 ; ii < ctsd->getTemplateArgs().size() ; ii++ ) { const clang::TemplateArgument & ta = ctsd->getTemplateArgs().get(ii) ; @@ -362,7 +362,7 @@ static bool checkForPRivateTemplateArgs( clang::ClassTemplateSpecializationDecl if ( clang::isa(crd) ) { clang::ClassTemplateSpecializationDecl * inner_ctsd ; inner_ctsd = clang::cast(crd) ; - return checkForPRivateTemplateArgs(inner_ctsd) ; + return checkForPrivateTemplateArgs(inner_ctsd) ; } } } @@ -416,24 +416,26 @@ bool FieldVisitor::VisitRecordType(clang::RecordType *rt) { if (!tst_string.compare( 0 , (*it).first.size() , (*it).first)) { clang::RecordDecl * rd = rt->getDecl()->getDefinition() ; - clang::ClassTemplateSpecializationDecl * ctsd ; - ctsd = clang::cast(rd) ; + if ( rd != NULL and clang::ClassTemplateSpecializationDecl::classof(rd) ) { + clang::ClassTemplateSpecializationDecl * ctsd ; + ctsd = clang::cast(rd) ; - // If a private embedded class is in an STL the resulting io_src code will not compile. - // Search the template arguments for private embedded classes, if found remove io capabilites. - if ( checkForPRivateTemplateArgs( ctsd )) { - fdes->setIO(0) ; + // If a private embedded class is in an STL the resulting io_src code will not compile. + // Search the template arguments for private embedded classes, if found remove io capabilites. + if ( checkForPrivateTemplateArgs( ctsd )) { + fdes->setIO(0) ; + } + + fdes->setEnumString("TRICK_STL") ; + fdes->setSTL(true) ; + fdes->setTypeName(tst_string) ; + fdes->setSTLClear((*it).second) ; + // set the type name to the non canonical name, the name the user put in the header file + // The typename is not used by STL variables, and it is nice to see the type that was + // actually inputted by the user + fdes->setMangledTypeName(fdes->getNonCanonicalTypeName()) ; + return false ; } - - fdes->setEnumString("TRICK_STL") ; - fdes->setSTL(true) ; - fdes->setTypeName(tst_string) ; - fdes->setSTLClear((*it).second) ; - // set the type name to the non canonical name, the name the user put in the header file - // The typename is not used by STL variables, and it is nice to see the type that was - // actually inputted by the user - fdes->setMangledTypeName(fdes->getNonCanonicalTypeName()) ; - return false ; } } // If the record type is in std:: but not one we can process, set the I/O spec to zero and return. @@ -446,7 +448,7 @@ bool FieldVisitor::VisitRecordType(clang::RecordType *rt) { If so process the template type and return */ clang::RecordDecl * rd = rt->getDecl()->getDefinition() ; if ( rd != NULL and clang::ClassTemplateSpecializationDecl::classof(rd) ) { - if ( checkForPRivateTemplateArgs( clang::cast(rd)) ) { + if ( checkForPrivateTemplateArgs( clang::cast(rd)) ) { fdes->setIO(0) ; if ( debug_level >= 3 ) { std::cout << " template using private/protected class as argument, not processing" << std::endl ; @@ -492,6 +494,7 @@ bool FieldVisitor::VisitRecordType(clang::RecordType *rt) { } bool FieldVisitor::VisitVarDecl( clang::VarDecl *v ) { + fdes->setStatic(v->isStaticDataMember()) ; /* If we have a static const integer type with an initializer value, this variable will not be instantiated by the compiler. The compiler substitutes in the value internally. @@ -501,6 +504,7 @@ bool FieldVisitor::VisitVarDecl( clang::VarDecl *v ) { v->getType().isConstQualified() and v->hasInit() ) { fdes->setIO(0) ; + return false ; } else if ( v->isStaticDataMember() and v->getType().isConstQualified() ) { /* Static const members cannot be set through attributes code. Remove input @@ -515,6 +519,24 @@ bool FieldVisitor::VisitVarDecl( clang::VarDecl *v ) { std::cout << " IO = " << fdes->getIO() << std::endl ; //v->dump() ; std::cout << std::endl ; } + + clang::QualType qt = v->getType() ; + // If the current type is not canonical because of typedefs or template parameter substitution, + // traverse the canonical type + if ( !qt.isCanonical() ) { + fdes->setNonCanonicalTypeName(qt.getAsString()) ; + clang::QualType ct = qt.getCanonicalType() ; + std::string tst_string = ct.getAsString() ; + if ( debug_level >= 3 ) { + std::cout << "\033[33mFieldVisitor VisitVarDecl: Processing canonical type\033[00m" << std::endl ; + ct.dump() ; + } + TraverseType(ct) ; + // We have extracted the canonical type and everything else we need + // return false so we cut off processing of this AST branch + return false ; + } + return true ; } diff --git a/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp b/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp index 7cb15ed8..590920b2 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp +++ b/trick_source/codegen/Interface_Code_Gen/PrintFileContents10.cpp @@ -167,6 +167,8 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ofstream & outfile , printNamespaces( outfile, cv , "__" ) ; printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() << "[" << index << "].checkpoint_stl = checkpoint_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << fdes->getName() ; @@ -176,6 +178,8 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ofstream & outfile , printNamespaces( outfile, cv , "__" ) ; printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() << "[" << index << "].post_checkpoint_stl = post_checkpoint_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << fdes->getName() ; @@ -185,6 +189,8 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ofstream & outfile , printNamespaces( outfile, cv , "__" ) ; printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() << "[" << index << "].restore_stl = restore_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << fdes->getName() ; @@ -195,6 +201,8 @@ void PrintFileContents10::print_field_init_attr_stmts( std::ofstream & outfile , printNamespaces( outfile, cv , "__" ) ; printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() << "[" << index << "].clear_stl = clear_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << fdes->getName() ; @@ -438,18 +446,24 @@ void PrintFileContents10::print_stl_helper_proto(std::ofstream & outfile , Class for ( fit = cv->field_begin() ; fit != cv->field_end() ; fit++ ) { if ( (*fit)->isSTL() and determinePrintAttr(cv , *fit) ) { outfile << "void checkpoint_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << (*fit)->getName() ; outfile << "(void * start_address, const char * obj_name , const char * var_name) ;" << std::endl ; outfile << "void post_checkpoint_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << (*fit)->getName() ; outfile << "(void * start_address, const char * obj_name , const char * var_name) ;" << std::endl ; outfile << "void restore_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << (*fit)->getName() ; @@ -457,6 +471,8 @@ void PrintFileContents10::print_stl_helper_proto(std::ofstream & outfile , Class if ((*fit)->hasSTLClear()) { outfile << "void clear_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << (*fit)->getName() ; @@ -469,6 +485,8 @@ void PrintFileContents10::print_stl_helper_proto(std::ofstream & outfile , Class void PrintFileContents10::print_checkpoint_stl(std::ofstream & outfile , FieldDescription * fdes , ClassValues * cv ) { outfile << "void checkpoint_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << fdes->getName() ; @@ -482,6 +500,8 @@ void PrintFileContents10::print_checkpoint_stl(std::ofstream & outfile , FieldDe void PrintFileContents10::print_post_checkpoint_stl(std::ofstream & outfile , FieldDescription * fdes , ClassValues * cv ) { outfile << "void post_checkpoint_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << fdes->getName() ; @@ -495,6 +515,8 @@ void PrintFileContents10::print_post_checkpoint_stl(std::ofstream & outfile , Fi void PrintFileContents10::print_restore_stl(std::ofstream & outfile , FieldDescription * fdes , ClassValues * cv ) { outfile << "void restore_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << fdes->getName() ; @@ -508,6 +530,8 @@ void PrintFileContents10::print_restore_stl(std::ofstream & outfile , FieldDescr void PrintFileContents10::print_clear_stl(std::ofstream & outfile , FieldDescription * fdes , ClassValues * cv ) { outfile << "void clear_stl_" ; + printNamespaces( outfile, cv , "__" ) ; + printContainerClasses( outfile, cv , "__" ) ; outfile << cv->getMangledTypeName() ; outfile << "_" ; outfile << fdes->getName() ;