diff --git a/src/Type.h b/src/Type.h index 403ccffa89..082e950921 100644 --- a/src/Type.h +++ b/src/Type.h @@ -456,6 +456,8 @@ public: // Given an offset, returns the field's name. const char* FieldName(int field) const; + type_decl_list* Types() { return types; } + // Given an offset, returns the field's TypeDecl. const TypeDecl* FieldDecl(int field) const; TypeDecl* FieldDecl(int field); diff --git a/src/Var.cc b/src/Var.cc index 1211a5315b..d6d4cc10e4 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -242,22 +242,31 @@ void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */) // t->GetTypeID() is true. if ( generate_documentation ) { - SerializationFormat* form = new BinarySerializationFormat(); - form->StartWrite(); - CloneSerializer ss(form); - SerialInfo sinfo(&ss); - sinfo.cache = false; + if ( t->Tag() == TYPE_RECORD ) + { + // Only "shallow" copy record types because we want to be able + // to see additions to the original type's list of fields + tnew = new RecordType(t->AsRecordType()->Types()); + } + else + { + SerializationFormat* form = new BinarySerializationFormat(); + form->StartWrite(); + CloneSerializer ss(form); + SerialInfo sinfo(&ss); + sinfo.cache = false; - t->Serialize(&sinfo); - char* data; - uint32 len = form->EndWrite(&data); - form->StartRead(data, len); + t->Serialize(&sinfo); + char* data; + uint32 len = form->EndWrite(&data); + form->StartRead(data, len); - UnserialInfo uinfo(&ss); - uinfo.cache = false; - tnew = t->Unserialize(&uinfo); + UnserialInfo uinfo(&ss); + uinfo.cache = false; + tnew = t->Unserialize(&uinfo); - delete [] data; + delete [] data; + } tnew->SetTypeID(copy_string(id->Name())); } diff --git a/testing/btest/doc/autogen-reST-record-add.bro b/testing/btest/doc/autogen-reST-record-add.bro new file mode 100644 index 0000000000..5f95a27e8c --- /dev/null +++ b/testing/btest/doc/autogen-reST-record-add.bro @@ -0,0 +1,31 @@ +# @TEST-EXEC: bro --doc-scripts %INPUT + +# When in doc mode, bro will clone declared types (see add_type() in Var.cc) +# in order to keep track of the identifier name associated with the new type. +# This test makes sure that the cloning is done in a way that's compatible +# with adding fields to a record type -- we want to be sure that cloning +# a record that contains other record fields will correctly see field +# additions to those contained-records. + +type my_record: record { + field1: bool; + field2: string; +}; + +type super_record: record { + rec: my_record; +}; + +redef record my_record += { + field3: count &optional; +}; + +global a: my_record; + +global b: super_record; + +function test_func() +{ + a?$field3; + b$rec?$field3; +}