From 4ff8591b12bce2d7cf26c287100d064bc4b17487 Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Thu, 10 Mar 2016 10:42:59 -0600 Subject: [PATCH] ATTRIBUTES for classes with non-locally typedef'd members is wrong Interesting case. I found that we should process the canonical type names where we were not before. This resolves all typedefs and should be be more accurate in the future. When we process the canonical type we need to ignore the processing of the non-canonical type. We set a flag after the canonical type is processed to ignore any type that is processed after. refs #198 --- .../Interface_Code_Gen/FieldDescription.cpp | 9 +++++ .../Interface_Code_Gen/FieldDescription.hh | 5 +++ .../Interface_Code_Gen/FieldVisitor.cpp | 39 +++++++++++++++++-- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp b/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp index af3d585c..ee5ceb3c 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp +++ b/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp @@ -38,6 +38,7 @@ FieldDescription::FieldDescription( is_record(0) , is_static(0) , has_type(0) , + has_dims(0) , num_dims(0) , array_sizes() {} ; @@ -390,6 +391,14 @@ bool FieldDescription::hasType() { return has_type ; } +void FieldDescription::setHasDims( bool yes_no ) { + has_dims = yes_no ; +} + +bool FieldDescription::hasDims() { + return has_dims ; +} + unsigned int FieldDescription::getNumDims() { return num_dims ; } diff --git a/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh b/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh index 8024a448..94677359 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh +++ b/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh @@ -77,6 +77,8 @@ class FieldDescription : public ConstructValues { bool isVirtualInherited() ; void setHasType( bool yes_no ) ; bool hasType() ; + void setHasDims( bool yes_no ) ; + bool hasDims() ; void setAccess( clang::AccessSpecifier in_val ) ; clang::AccessSpecifier getAccess() ; @@ -158,6 +160,9 @@ class FieldDescription : public ConstructValues { /** Have we resolved the type for this parameter? */ bool has_type ; + /** Have we resolved the dimensions for this parameter? */ + bool has_dims ; + /** map of strings to io numbers. One copy for all fields */ static std::map io_map ; diff --git a/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp b/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp index 5759c2c2..254e5b64 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp +++ b/trick_source/codegen/Interface_Code_Gen/FieldVisitor.cpp @@ -130,7 +130,9 @@ bool FieldVisitor::VisitBuiltinType(clang::BuiltinType *bt) { bool FieldVisitor::VisitConstantArrayType(clang::ConstantArrayType *cat) { //cat->dump() ; std::cout << std::endl ; - fdes->addArrayDim(cat->getSize().getZExtValue()) ; + if ( ! fdes->hasDims() ) { + fdes->addArrayDim(cat->getSize().getZExtValue()) ; + } return true; } @@ -207,16 +209,31 @@ bool FieldVisitor::VisitFieldDecl( clang::FieldDecl *field ) { fdes->setBitFieldStart( 32 - (field_offset_bits % 32) - fdes->getBitFieldWidth()) ; fdes->setBitFieldByteOffset((field_offset_bits / 32) * 4 ) ; } + + clang::QualType qt = field->getType() ; + // If the current type is not canonical because of typedefs, traverse the canonical type + if ( !qt.isCanonical() ) { + clang::QualType ct = qt.getCanonicalType() ; + TraverseType(ct) ; + // Traversing the canonical type will set the has_type flag. Set the has_dims flag too so + // when we continue parsing the AST and the non-canonical type, we don't double add dimensions. + fdes->setHasDims(true) ; + } return true ; } bool FieldVisitor::VisitElaboratedType(clang::ElaboratedType *et) { + if ( debug_level >= 4 ) { + std::cout << "FieldVisitor VisitElaboratedType" << std::endl ; + } //et->dump() ; std::cout << std::endl ; return true ; } bool FieldVisitor::VisitPointerType(clang::PointerType *p) { - fdes->addArrayDim(-1) ; + if ( ! fdes->hasDims() ) { + fdes->addArrayDim(-1) ; + } return true; } @@ -242,8 +259,17 @@ bool FieldVisitor::VisitRecordType(clang::RecordType *rt) { //std::cout << "hasNameForLinkage " << rt->getDecl()->hasNameForLinkage() << std::endl ; if ( rt->getDecl()->hasNameForLinkage() ) { if ( rt->getDecl()->getDeclName() ) { - //std::cout << "getDeclName " << rt->getDecl()->getDeclName().getAsString() << std::endl ; - fdes->setTypeName(rt->getDecl()->getQualifiedNameAsString()) ; + std::string type_name = rt->getDecl()->getQualifiedNameAsString() ; + // Handle the string class differently than regular records. + if ( ! type_name.compare("std::basic_string") || !type_name.compare("std::__1::basic_string")) { + fdes->setEnumString("TRICK_STRING") ; + fdes->setTypeName("std::string") ; + fdes->setHasType(true) ; + return true ; + } else { + //std::cout << "getDeclName " << type_name << std::endl ; + fdes->setTypeName(type_name) ; + } } else { //std::cout << "getTypedefNameForAnonDecl " << rt->getDecl()->getTypedefNameForAnonDecl() << std::endl ; fdes->setTypeName(rt->getDecl()->getTypedefNameForAnonDecl()->getQualifiedNameAsString()) ; @@ -448,6 +474,11 @@ bool FieldVisitor::VisitTypedefType(clang::TypedefType *tt) { fdes->setHasType(true) ; } else if ( tt->isRecordType() ) { + + if ( debug_level >= 4 ) { + std::cout << "FieldVisitor isRecordType" << std::endl ; + } + std::string type_name = tt->desugar().getAsString() ; if ((pos = type_name.find("struct ")) != std::string::npos ) { type_name.erase(pos , 7) ;