tools/clang/lib/Sema/SemaHLSL.cpp
// TODO: improve this to provide a 'peek' at intermediate types,
// which should help compare struct foo[1000] to avoid 1000 steps + per-field steps
improve this to provide a 'peek' at intermediate types,
which should help compare struct foo[1000] to avoid 1000 steps + per-field steps
improve this to provide a ' peek ' at intermediate types which should help compare struct foo [ 1000 ] to avoid 1000 steps + per - field steps
bool FlattenedTypeIterator::pushTrackerForType(QualType type, MultiExprArg::iterator expression)
  {
  if (type->isVoidType()) {
    return false;
  }
  if (type->isFunctionType()) {
    return false;
  }
  if (m_firstType.isNull()) {
    m_firstType = type;
  }
  ArTypeObjectKind objectKind = m_source.GetTypeObjectKind(type);
  QualType elementType;
  unsigned int elementCount;
  const RecordType* recordType;
  RecordDecl::field_iterator fi, fe;
  switch (objectKind)
  {
  case ArTypeObjectKind::AR_TOBJ_ARRAY:
    elementType = type->getAsArrayTypeUnsafe()->getElementType(); 
    elementCount = GetArraySize(type);
    if (elementCount == 0) {
      if (type->isIncompleteArrayType()) {
        m_typeTrackers.push_back(FlattenedTypeIterator::FlattenedTypeTracker(elementType));
        return true;
      }
      return false;
    }
    m_typeTrackers.push_back(FlattenedTypeIterator::FlattenedTypeTracker(
      elementType, elementCount, nullptr));
    return true;
  case ArTypeObjectKind::AR_TOBJ_BASIC:
    m_typeTrackers.push_back(FlattenedTypeIterator::FlattenedTypeTracker(type, 1, expression));
    return true;
  case ArTypeObjectKind::AR_TOBJ_COMPOUND: {
    recordType = type->getAsStructureType();
    if (recordType == nullptr)
      recordType = dyn_cast<RecordType>(type.getTypePtr());
    fi = recordType->getDecl()->field_begin();
    fe = recordType->getDecl()->field_end();
    bool bAddTracker = false;
    if (fi != fe) {
      m_typeTrackers.push_back(
          FlattenedTypeIterator::FlattenedTypeTracker(type, fi, fe));
      type = (*fi)->getType();
      bAddTracker = true;
    }
    if (CXXRecordDecl *cxxRecordDecl =
            dyn_cast<CXXRecordDecl>(recordType->getDecl())) {
      CXXRecordDecl::base_class_iterator bi, be;
      bi = cxxRecordDecl->bases_begin();
      be = cxxRecordDecl->bases_end();
      if (bi != be) {
        m_typeTrackers.push_back(
            FlattenedTypeIterator::FlattenedTypeTracker(type, bi, be));
        bAddTracker = true;
      }
    }
    return bAddTracker;
  }
  case ArTypeObjectKind::AR_TOBJ_MATRIX:
    m_typeTrackers.push_back(FlattenedTypeIterator::FlattenedTypeTracker(
      m_source.GetMatrixOrVectorElementType(type),
      GetElementCount(type), nullptr));
    return true;
  case ArTypeObjectKind::AR_TOBJ_VECTOR:
    m_typeTrackers.push_back(FlattenedTypeIterator::FlattenedTypeTracker(
      m_source.GetMatrixOrVectorElementType(type),
      GetHLSLVecSize(type), nullptr));
    return true;
  case ArTypeObjectKind::AR_TOBJ_OBJECT:
    m_typeTrackers.push_back(FlattenedTypeIterator::FlattenedTypeTracker(type.getCanonicalType(), 1, expression));
    return true;
  default:
    DXASSERT(false, "unreachable");
    return false;
  }
}
bool FlattenedTypeIterator :: pushTrackerForType ( QualType type , MultiExprArg :: iterator expression ) { if ( type -> isVoidType ( ) ) { return false ; } if ( type -> isFunctionType ( ) ) { return false ; } if ( m_firstType . isNull ( ) ) { m_firstType = type ; } ArTypeObjectKind objectKind = m_source . GetTypeObjectKind ( type ) ; QualType elementType ; unsigned int elementCount ; const RecordType * recordType ; RecordDecl :: field_iterator fi , fe ; switch ( objectKind ) { case ArTypeObjectKind :: AR_TOBJ_ARRAY : elementType = type -> getAsArrayTypeUnsafe ( ) -> getElementType ( ) ; elementCount = GetArraySize ( type ) ; if ( elementCount == 0 ) { if ( type -> isIncompleteArrayType ( ) ) { m_typeTrackers . push_back ( FlattenedTypeIterator :: FlattenedTypeTracker ( elementType ) ) ; return true ; } return false ; } m_typeTrackers . push_back ( FlattenedTypeIterator :: FlattenedTypeTracker ( elementType , elementCount , nullptr ) ) ; return true ; case ArTypeObjectKind :: AR_TOBJ_BASIC : m_typeTrackers . push_back ( FlattenedTypeIterator :: FlattenedTypeTracker ( type , 1 , expression ) ) ; return true ; case ArTypeObjectKind :: AR_TOBJ_COMPOUND : { recordType = type -> getAsStructureType ( ) ; if ( recordType == nullptr ) recordType = dyn_cast < RecordType > ( type . getTypePtr ( ) ) ; fi = recordType -> getDecl ( ) -> field_begin ( ) ; fe = recordType -> getDecl ( ) -> field_end ( ) ; bool bAddTracker = false ; if ( fi != fe ) { m_typeTrackers . push_back ( FlattenedTypeIterator :: FlattenedTypeTracker ( type , fi , fe ) ) ; type = ( * fi ) -> getType ( ) ; bAddTracker = true ; } if ( CXXRecordDecl * cxxRecordDecl = dyn_cast < CXXRecordDecl > ( recordType -> getDecl ( ) ) ) { CXXRecordDecl :: base_class_iterator bi , be ; bi = cxxRecordDecl -> bases_begin ( ) ; be = cxxRecordDecl -> bases_end ( ) ; if ( bi != be ) { m_typeTrackers . push_back ( FlattenedTypeIterator :: FlattenedTypeTracker ( type , bi , be ) ) ; bAddTracker = true ; } } return bAddTracker ; } case ArTypeObjectKind :: AR_TOBJ_MATRIX : m_typeTrackers . push_back ( FlattenedTypeIterator :: FlattenedTypeTracker ( m_source . GetMatrixOrVectorElementType ( type ) , GetElementCount ( type ) , nullptr ) ) ; return true ; case ArTypeObjectKind :: AR_TOBJ_VECTOR : m_typeTrackers . push_back ( FlattenedTypeIterator :: FlattenedTypeTracker ( m_source . GetMatrixOrVectorElementType ( type ) , GetHLSLVecSize ( type ) , nullptr ) ) ; return true ; case ArTypeObjectKind :: AR_TOBJ_OBJECT : m_typeTrackers . push_back ( FlattenedTypeIterator :: FlattenedTypeTracker ( type . getCanonicalType ( ) , 1 , expression ) ) ; return true ; default : DXASSERT ( false , " " ) ; return false ; } }
TODO: improve this to provide a 'peek' at intermediate types,
which should help compare struct foo[1000] to avoid 1000 steps + per-field steps
TODO : improve this to provide a ' peek ' at intermediate types which should help compare struct foo [ 1000 ] to avoid 1000 steps + per - field steps
// TODO: handle multi-dimensional arrays // handle arrays of arrays // Skip empty struct. // Add type tracker for base. // Add base after child to make sure base considered first. // Object have no sub-types.