Give an example of walking TypeIds in a DexFile
Also prevent accidentally copying of DexFile structures

Change-Id: I293bdfe073ce1e1a54f6de2e0abadac312503016
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 0999788..c28fc65 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -633,7 +633,6 @@
   // Load instance fields.
   DCHECK(klass->ifields_ == NULL);
   if (num_instance_fields != 0) {
-    // TODO: allocate on the object heap.
     klass->ifields_ = AllocObjectArray<Field>(num_instance_fields);
     uint32_t last_idx = 0;
     for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index ce08b1b..e2b9a2b 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -23,7 +23,10 @@
   }
 
   void AssertPrimitiveClass(const StringPiece& descriptor) {
-    Class* primitive = class_linker_->FindSystemClass(descriptor);
+    AssertPrimitiveClass(descriptor, class_linker_->FindSystemClass(descriptor));
+  }
+
+  void AssertPrimitiveClass(const StringPiece& descriptor, const Class* primitive) {
     ASSERT_TRUE(primitive != NULL);
     ASSERT_TRUE(primitive->GetClass() != NULL);
     ASSERT_EQ(primitive->GetClass(), primitive->GetClass()->GetClass());
@@ -56,6 +59,13 @@
                         const StringPiece& component_type,
                         ClassLoader* class_loader) {
     Class* array = class_linker_->FindClass(array_descriptor, class_loader);
+    EXPECT_EQ(array_rank, array->array_rank_);
+    EXPECT_TRUE(array->GetComponentType()->GetDescriptor()->Equals(component_type));
+    EXPECT_EQ(class_loader, array->GetClassLoader());
+    AssertArrayClass(array_descriptor, array);
+  }
+
+  void AssertArrayClass(const StringPiece& array_descriptor, Class* array) {
     ASSERT_TRUE(array != NULL);
     ASSERT_TRUE(array->GetClass() != NULL);
     ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
@@ -64,16 +74,14 @@
     EXPECT_TRUE(array->GetSuperClass() != NULL);
     EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Object;"), array->GetSuperClass());
     EXPECT_TRUE(array->HasSuperClass());
-    EXPECT_EQ(class_loader, array->GetClassLoader());
     ASSERT_TRUE(array->GetComponentType() != NULL);
     ASSERT_TRUE(array->GetComponentType()->GetDescriptor() != NULL);
-    EXPECT_TRUE(array->GetComponentType()->GetDescriptor()->Equals(component_type));
     EXPECT_TRUE(array->GetStatus() == Class::kStatusInitialized);
     EXPECT_FALSE(array->IsErroneous());
     EXPECT_TRUE(array->IsVerified());
     EXPECT_TRUE(array->IsLinked());
     EXPECT_TRUE(array->IsArray());
-    EXPECT_EQ(array_rank, array->array_rank_);
+    EXPECT_LE(1, array->array_rank_);
     EXPECT_FALSE(array->IsInterface());
     EXPECT_EQ(array->GetComponentType()->IsPublic(), array->IsPublic());
     EXPECT_TRUE(array->IsFinal());
@@ -86,7 +94,7 @@
     EXPECT_EQ(2U, array->NumInterfaces());
   }
 
-  void AssertDexFileMethod(Class* klass, Method* method) {
+  void AssertMethod(Class* klass, Method* method) {
     EXPECT_TRUE(method != NULL);
     EXPECT_TRUE(method->GetName() != NULL);
     EXPECT_TRUE(method->GetSignature() != NULL);
@@ -101,17 +109,14 @@
     EXPECT_EQ(method->declaring_class_->dex_cache_->GetFields(), method->dex_cache_fields_);
   }
 
-  void AssertDexFileField(Class* klass, Field* field) {
+  void AssertField(Class* klass, Field* field) {
     EXPECT_TRUE(field != NULL);
     EXPECT_EQ(klass, field->GetDeclaringClass());
     EXPECT_TRUE(field->GetName() != NULL);
     EXPECT_TRUE(field->GetDescriptor() != NULL);
   }
 
-  void AssertDexFileClass(ClassLoader* class_loader, const char* descriptor) {
-    ASSERT_TRUE(descriptor != NULL);
-    Class* klass = class_linker_->FindSystemClass(descriptor);
-    ASSERT_TRUE(klass != NULL);
+  void AssertClass(const StringPiece& descriptor, Class* klass) {
     EXPECT_TRUE(klass->GetDescriptor()->Equals(descriptor));
     if (klass->descriptor_->Equals(String::AllocFromModifiedUtf8("Ljava/lang/Object;"))) {
       EXPECT_FALSE(klass->HasSuperClass());
@@ -119,7 +124,6 @@
       EXPECT_TRUE(klass->HasSuperClass());
       EXPECT_TRUE(klass->GetSuperClass() != NULL);
     }
-    EXPECT_EQ(class_loader, klass->GetClassLoader());
     EXPECT_TRUE(klass->GetDexCache() != NULL);
     EXPECT_TRUE(klass->GetComponentType() == NULL);
     EXPECT_TRUE(klass->GetComponentType() == NULL);
@@ -161,25 +165,25 @@
 
     for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
       Method* method = klass->GetDirectMethod(i);
-      AssertDexFileMethod(klass, method);
+      AssertMethod(klass, method);
       EXPECT_EQ(klass, method->GetDeclaringClass());
     }
 
     for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
       Method* method = klass->GetVirtualMethod(i);
-      AssertDexFileMethod(klass, method);
+      AssertMethod(klass, method);
       EXPECT_TRUE(method->GetDeclaringClass()->IsAssignableFrom(klass));
     }
 
     for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
       Field* field = klass->GetInstanceField(i);
-      AssertDexFileField(klass, field);
+      AssertField(klass, field);
       EXPECT_FALSE(field->IsStatic());
     }
 
     for (size_t i = 0; i < klass->NumStaticFields(); i++) {
       Field* field = klass->GetStaticField(i);
-      AssertDexFileField(klass, field);
+      AssertField(klass, field);
       EXPECT_TRUE(field->IsStatic());
    }
 
@@ -187,13 +191,15 @@
     EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields());
     for (size_t i = 0; i < klass->NumReferenceInstanceFields(); i++) {
       Field* field = klass->GetInstanceField(i);
-      Class* field_type = class_linker_->FindClass(field->GetDescriptor(), class_loader);
+      Class* field_type = class_linker_->FindClass(field->GetDescriptor(),
+                                                   klass->GetClassLoader());
       ASSERT_TRUE(field_type != NULL);
       EXPECT_FALSE(field_type->IsPrimitive());
     }
     for (size_t i = klass->NumReferenceInstanceFields(); i < klass->NumInstanceFields(); i++) {
       Field* field = klass->GetInstanceField(i);
-      Class* field_type = class_linker_->FindClass(field->GetDescriptor(), class_loader);
+      Class* field_type = class_linker_->FindClass(field->GetDescriptor(),
+                                                   klass->GetClassLoader());
       ASSERT_TRUE(field_type != NULL);
       EXPECT_TRUE(field_type->IsPrimitive());
     }
@@ -208,19 +214,41 @@
               total_num_reference_instance_fields == 0);
   }
 
-  static void TestRootVisitor(Object* root, void* arg) {
-    EXPECT_TRUE(root != NULL);
+  void AssertDexFileClass(ClassLoader* class_loader, const StringPiece& descriptor) {
+    ASSERT_TRUE(descriptor != NULL);
+    Class* klass = class_linker_->FindSystemClass(descriptor);
+    ASSERT_TRUE(klass != NULL);
+    EXPECT_TRUE(klass->GetDescriptor()->Equals(descriptor));
+    EXPECT_EQ(class_loader, klass->GetClassLoader());
+    if (klass->IsPrimitive()) {
+      AssertPrimitiveClass(descriptor, klass);
+    } else if (klass->IsArray()) {
+      AssertArrayClass(descriptor, klass);
+    } else {
+      AssertClass(descriptor, klass);
+    }
   }
 
   void AssertDexFile(const DexFile* dex, ClassLoader* class_loader) {
     ASSERT_TRUE(dex != NULL);
+    // Verify all the classes defined in this file
     for (size_t i = 0; i < dex->NumClassDefs(); i++) {
-      const DexFile::ClassDef class_def = dex->GetClassDef(i);
+      const DexFile::ClassDef& class_def = dex->GetClassDef(i);
       const char* descriptor = dex->GetClassDescriptor(class_def);
       AssertDexFileClass(class_loader, descriptor);
     }
+    // Verify all the types referened by this file
+    for (size_t i = 0; i < dex->NumTypeIds(); i++) {
+      const DexFile::TypeId& type_id = dex->GetTypeId(i);
+      const char* descriptor = dex->GetTypeDescriptor(type_id);
+      AssertDexFileClass(class_loader, descriptor);
+    }
     class_linker_->VisitRoots(TestRootVisitor, NULL);
   }
+
+  static void TestRootVisitor(Object* root, void* arg) {
+    EXPECT_TRUE(root != NULL);
+  }
 };
 
 TEST_F(ClassLinkerTest, FindClassNonexistent) {
diff --git a/src/dex_file.h b/src/dex_file.h
index 51f5d08..1431f1e 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -77,16 +77,22 @@
     uint32_t class_defs_off_;
     uint32_t data_size_;
     uint32_t data_off_;
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Header);
   };
 
   // Raw string_id_item.
   struct StringId {
     uint32_t string_data_off_;  // offset in bytes from the base address
+   private:
+    DISALLOW_COPY_AND_ASSIGN(StringId);
   };
 
   // Raw type_id_item.
   struct TypeId {
     uint32_t descriptor_idx_;  // index into string_ids
+   private:
+    DISALLOW_COPY_AND_ASSIGN(TypeId);
   };
 
   // Raw field_id_item.
@@ -94,6 +100,8 @@
     uint16_t class_idx_;  // index into type_ids_ list for defining class
     uint16_t type_idx_;  // index into type_ids_ for field type
     uint32_t name_idx_;  // index into string_ids_ for field name
+   private:
+    DISALLOW_COPY_AND_ASSIGN(FieldId);
   };
 
   // Raw method_id_item.
@@ -101,6 +109,8 @@
     uint16_t class_idx_;  // index into type_ids_ list for defining class
     uint16_t proto_idx_;  // index into proto_ids_ for method prototype
     uint32_t name_idx_;  // index into string_ids_ for method name
+   private:
+    DISALLOW_COPY_AND_ASSIGN(MethodId);
   };
 
   // Raw proto_id_item.
@@ -108,6 +118,8 @@
     uint32_t shorty_idx_;  // index into string_ids for shorty descriptor
     uint32_t return_type_idx_;  // index into type_ids list for return type
     uint32_t parameters_off_;  // file offset to type_list for parameter types
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ProtoId);
   };
 
   // Raw class_def_item.
@@ -120,11 +132,15 @@
     uint32_t annotations_off_;  // file offset to annotations_directory_item
     uint32_t class_data_off_;  // file offset to class_data_item
     uint32_t static_values_off_;  // file offset to EncodedArray
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ClassDef);
   };
 
   // Raw type_item.
   struct TypeItem {
     uint16_t type_idx_;  // index into type_ids section
+   private:
+    DISALLOW_COPY_AND_ASSIGN(TypeItem);
   };
 
   // Raw type_list.
@@ -142,6 +158,7 @@
    private:
     uint32_t size_;  // size of the list, in entries
     TypeItem list_[1];  // elements of the list
+    DISALLOW_COPY_AND_ASSIGN(TypeList);
   };
 
   class ParameterIterator {  // TODO: stream
@@ -184,6 +201,8 @@
     uint32_t debug_info_off_;  // file offset to debug info stream
     uint32_t insns_size_;  // size of the insns array, in 2 byte code units
     uint16_t insns_[1];
+   private:
+    DISALLOW_COPY_AND_ASSIGN(CodeItem);
   };
 
   struct CatchHandlerItem {
@@ -196,6 +215,8 @@
     uint32_t start_addr_;
     uint16_t insn_count_;
     uint16_t handler_off_;
+   private:
+    DISALLOW_COPY_AND_ASSIGN(TryItem);
   };
 
   class CatchHandlerIterator {
@@ -268,6 +289,9 @@
   struct Field {
     uint32_t field_idx_;  // index into the field_ids list for the identity of this field
     uint32_t access_flags_;  // access flags for the field
+    Field() {};
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Field);
   };
 
   // Decoded form of encoded_method.
@@ -275,6 +299,9 @@
     uint32_t method_idx_;
     uint32_t access_flags_;
     uint32_t code_off_;
+    Method() {};
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Method);
   };
 
   typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
@@ -377,6 +404,11 @@
     return dexStringByTypeIdx(class_def.class_idx_);
   }
 
+  // Returns the type descriptor string of a type id.
+  const char* GetTypeDescriptor(const TypeId& type_id) const {
+    return dexStringById(type_id.descriptor_idx_);
+  }
+
   // Returns the StringId at the specified index.
   const StringId& GetStringId(uint32_t idx) const {
     CHECK_LT(idx, NumStringIds());
@@ -691,6 +723,9 @@
 
     // Is the local defined and live.
     bool is_live_;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(LocalInfo);
   };
 
   struct LineNumFromPcContext {
@@ -698,6 +733,8 @@
                            address_(address), line_num_(line_num) {}
     uint32_t address_;
     uint32_t line_num_;
+   private:
+    DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext);
   };
 
   void InvokeLocalCbIfLive(void *cnxt, int reg, uint32_t end_address,
diff --git a/src/image_test.cc b/src/image_test.cc
index 7c1312b..54c2c75 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -17,7 +17,7 @@
 
   // TODO: move the touching of classes and GC to the ImageWriter proper
   for (size_t i = 0; i < java_lang_dex_file_->NumClassDefs(); i++) {
-    const DexFile::ClassDef class_def = java_lang_dex_file_->GetClassDef(i);
+    const DexFile::ClassDef& class_def = java_lang_dex_file_->GetClassDef(i);
     const char* descriptor = java_lang_dex_file_->GetClassDescriptor(class_def);
     Class* klass = class_linker_->FindSystemClass(descriptor);
     ASSERT_TRUE(klass != NULL) << descriptor;
@@ -81,7 +81,7 @@
   byte* boot_base = boot_space->GetBase();
   byte* boot_limit = boot_space->GetLimit();
   for (size_t i = 0; i < dex->NumClassDefs(); i++) {
-    const DexFile::ClassDef class_def = dex->GetClassDef(i);
+    const DexFile::ClassDef& class_def = dex->GetClassDef(i);
     const char* descriptor = dex->GetClassDescriptor(class_def);
     Class* klass = class_linker_->FindSystemClass(descriptor);
     EXPECT_TRUE(klass != NULL) << descriptor;