diff --git a/src/AggregateType.cpp b/src/AggregateType.cpp new file mode 100755 index 000000000..b4372c430 --- /dev/null +++ b/src/AggregateType.cpp @@ -0,0 +1,667 @@ +// -*- mode: C++ -*- +// +// Copyright (c) 2007, 2008, 2010, 2011, 2013, 2014 The University of Utah +// All rights reserved. +// +// Copyright (c) 2015-2016 Huawei Technologies Co., Ltd +// All rights reserved. +// +// This file is part of `csmith', a random generator of C programs. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// This file was derived from a random program generator written by Bryan +// Turner. The attributions in that file was: +// +// Random Program Generator +// Bryan Turner (bryan.turner@pobox.com) +// July, 2005 +// + +#include "AggregateType.h" +#include +#include +#include +#include "Common.h" +#include "CGOptions.h" +#include "random.h" +#include "Filter.h" +#include "util.h" +#include "Bookkeeper.h" +#include "Probabilities.h" + +using namespace std; + +static void OutputStructUnion(Type* type, std::ostream &out); +/////////////////////////////////////////////////////////////////////////////// + +// -------------------------------------------------------------- + /* constructor for struct or union types + *******************************************************/ +AggregateType::AggregateType(vector& struct_fields, bool isStruct, bool packed, + vector &qfers, vector &fields_length) : + fields(struct_fields), + printed(false), + packed_(packed), + qfers_(qfers), + bitfields_length_(fields_length) +{ + static unsigned int sequence = 0; + if (isStruct) + eType = eStruct; + else + eType = eUnion; + sid = sequence++; +} + +void +AggregateType::get_all_ok_struct_union_types(vector &ok_types, bool no_const, bool no_volatile, bool need_int_field, bool bStruct) +{ + vector::iterator i; + for(i = AllTypes.begin(); i != AllTypes.end(); ++i) { + Type* t = (*i); + if (bStruct && t->eType != eStruct) continue; + if (!bStruct && t->eType != eUnion) continue; + if ((no_const && t->is_const_struct_union()) || + (no_volatile && t->is_volatile_struct_union()) || + (need_int_field && (!t->has_int_field()))) { + continue; + } + ok_types.push_back(dynamic_cast(t)); + } +} + +const AggregateType* +AggregateType::choose_random_struct_union_type(vector &ok_types) +{ + size_t sz = ok_types.size(); + assert(sz > 0); + + int index = rnd_upto(ok_types.size()); + assert(index >= 0); + AggregateType *rv_type = ok_types[index]; + if (!rv_type->used) { + Bookkeeper::record_type_with_bitfields(rv_type); + rv_type->used = true; + } + return rv_type; +} + +const Type* +AggregateType::choose_random_struct_from_type(const Type* type, bool no_volatile) +{ + if (!type) + return NULL; + + const Type* t = type; + vector ok_struct_types; + get_all_ok_struct_union_types(ok_struct_types, no_volatile, false, true, true); + + if (ok_struct_types.size() > 0) { + t = AggregateType::choose_random_struct_union_type(ok_struct_types); + } + return t; +} + +void +AggregateType::make_one_bitfield(vector &random_fields, vector &qualifiers, + vector &fields_length) +{ + int max_length = CGOptions::int_size() * 8; + bool sign = rnd_flipcoin(BitFieldsSignedProb); + + const Type *type = sign ? &Type::get_simple_type(eInt) : &Type::get_simple_type(eUInt); + random_fields.push_back(type); + CVQualifiers qual = CVQualifiers::random_qualifiers(type, FieldConstProb, FieldVolatileProb); + + qualifiers.push_back(qual); + int length = rnd_upto(max_length); + + bool no_zero_len = fields_length.empty() || (fields_length.back() == 0); + // force length to be non-zero is required + if (length == 0 && no_zero_len) { + if (max_length <= 2) length = 1; + else length = rnd_upto(max_length - 1) + 1; + } + fields_length.push_back(length); +} + +// --------------------------------------------------------------------- +void +AggregateType::make_full_bitfields_struct_fields(size_t field_cnt, vector &random_fields, + vector &qualifiers, + vector &fields_length) +{ + for (size_t i=0; i &random_fields, + vector &qualifiers, + vector &fields_length) +{ + VectorFilter f; + unsigned int type_index = 0; + Type *typ = 0; + for( type_index = 0; type_index < AllTypes.size(); type_index++) { + typ = AllTypes[type_index]; + assert(typ); + if (typ->eType == eSimple) { + Filter *filter = SIMPLE_TYPES_PROB_FILTER; + if(filter->filter(typ->simple_type)) + f.add(type_index); + } + else if ((typ->eType == eStruct) && (!CGOptions::return_structs())) { + f.add(type_index); + } + if (typ->get_struct_depth() >= CGOptions::max_nested_struct_level()) { + f.add(type_index); + } + } + type_index = rnd_upto(AllTypes.size(), &f); + const Type* type = AllTypes[type_index]; + random_fields.push_back(type); + CVQualifiers qual = CVQualifiers::random_qualifiers(type, FieldConstProb, FieldVolatileProb); + qualifiers.push_back(qual); + fields_length.push_back(-1); +} + +void +AggregateType::make_one_union_field(vector &fields, vector &qfers, vector &lens) +{ + bool is_bitfield = CGOptions::bitfields() && !CGOptions::ccomp() && rnd_flipcoin(BitFieldInNormalStructProb); + if (is_bitfield) { + make_one_bitfield(fields, qfers, lens); + } + else { + size_t i; + vector ok_types; + // filter out struct types containing bit-fields. Their layout is implementation + // defined, we don't want to mess with them in unions for now + for (i=0; ihas_bitfields()) { + ok_types.push_back(AllTypes[i]); + } + } + + // find of struct types + vector struct_types; + for (size_t i=0; ieType == eStruct) { + struct_types.push_back(ok_types[i]); + } + } + const Type* type = NULL; + do { + // 10% chance to be struct field + if (!struct_types.empty() && pure_rnd_flipcoin(10)) { + type = struct_types[pure_rnd_upto(struct_types.size())]; + assert(type->eType == eStruct); + } + // 10% chance to be char* if pointer is allowed + else if (CGOptions::pointers() && CGOptions::int8() && pure_rnd_flipcoin(10)) { + type = PointerType::find_pointer_type(&get_simple_type(eChar), true); + } + else { + unsigned int i = pure_rnd_upto(ok_types.size()); + const Type* t = ok_types[i]; + // no union in union? + if (t->eType == eUnion || + (t->eType == eSimple && SIMPLE_TYPES_PROB_FILTER->filter(t->simple_type))) { + continue; + } + type = t; + } + } while (type == NULL); + + fields.push_back(type); + CVQualifiers qual = CVQualifiers::random_qualifiers(type, FieldConstProb, FieldVolatileProb); + qfers.push_back(qual); + lens.push_back(-1); + } +} + +void +AggregateType::make_normal_struct_fields(size_t field_cnt, vector &random_fields, + vector &qualifiers, + vector &fields_length) +{ + for (size_t i=0; i &fields) +{ + for (vector::const_iterator iter = fields.begin(), + iter_end = fields.end(); iter != iter_end; ++iter) { + if ((*iter)->is_aggregate()) + return true; + } + return false; +} + +AggregateType * +AggregateType::make_random_struct_type(void) +{ + size_t field_cnt = 0; + size_t max_cnt = CGOptions::max_struct_fields(); + if (CGOptions::fixed_struct_fields()) + field_cnt = max_cnt; + else + field_cnt = rnd_upto(max_cnt) + 1; + vector random_fields; + vector qualifiers; + vector fields_length; + bool is_bitfields = CGOptions::bitfields() && rnd_flipcoin(BitFieldsCreationProb); + + //if (CGOptions::bitfields()) + if (is_bitfields) + make_full_bitfields_struct_fields(field_cnt, random_fields, qualifiers, fields_length); + else + make_normal_struct_fields(field_cnt, random_fields, qualifiers, fields_length); + + // for now, no union type + bool packed = false; + if (CGOptions::packed_struct()) { + if (CGOptions::ccomp() && (has_aggregate_field(random_fields) || has_longlong_field(random_fields))) { + // Nothing to do + } + else { + packed = rnd_flipcoin(50); + } + } + + AggregateType* new_type = new AggregateType(random_fields, true, packed, qualifiers, fields_length); + return new_type; +} + +AggregateType * +AggregateType::make_random_union_type(void) +{ + size_t max_cnt = CGOptions::max_union_fields(); + size_t field_cnt = rnd_upto(max_cnt) + 1; + + vector fields; + vector qfers; + vector lens; + + for (size_t i=0; ihas_bitfields()); + } + AggregateType* new_type = new AggregateType(fields, false, false, qfers, lens); + return new_type; +} + +bool +AggregateType::has_longlong_field(const vector &fields) +{ + for (vector::const_iterator iter = fields.begin(), + iter_end = fields.end(); iter != iter_end; ++iter) { + if ((*iter)->is_long_long()) + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +bool +AggregateType::is_const_struct_union() const +{ + assert(fields.size() == qfers_.size()); + + for (size_t i = 0; i < fields.size(); ++i) { + const Type *field = fields[i]; + if (field->is_const_struct_union()) { + return true; + } + const CVQualifiers& cf = qfers_[i]; + if (cf.is_const()) return true; + } + return false; +} + +bool +AggregateType::is_volatile_struct_union() const +{ + assert(fields.size() == qfers_.size()); + + for (size_t i = 0; i < fields.size(); ++i) { + const Type *field = fields[i]; + if (field->is_volatile_struct_union()) { + return true; + } + const CVQualifiers& cf = qfers_[i]; + if (cf.is_volatile()) + return true; + } + return false; +} +// --------------------------------------------------------------------- +int +AggregateType::get_struct_depth() const +{ + int depth = 0; + if (eType == eStruct) { + depth++; + int max_depth = 0; + for (size_t i=0; iget_struct_depth(); + if(field_depth > max_depth) { + max_depth = field_depth; + } + } + depth += max_depth; + } + return depth; +} + +bool +AggregateType::is_unamed_padding(size_t index) const +{ + size_t sz = bitfields_length_.size(); + if (sz == 0) + return false; + + assert(index < sz); + return (bitfields_length_[index] == 0); +} + +bool +AggregateType::is_bitfield(size_t index) const +{ + assert(index < bitfields_length_.size()); + return (bitfields_length_[index] >= 0); +} + +bool +AggregateType::has_bitfields() const +{ + for (size_t i=0; i= 0) { + return true; + } + if (fields[i]->eType == eStruct && fields[i]->has_bitfields()) { + return true; + } + } + return false; +} + +// conservatively assume padding is present in all unpacked structures +// or whenever there is bitfields +bool +AggregateType::has_padding(void) const +{ + if (eType == eStruct && !packed_) return true; + for (size_t i=0; ihas_padding()) { + return true; + } + } + return false; +} + +bool +AggregateType::is_full_bitfields_struct() const +{ + if (eType != eStruct) return false; + size_t i; + for (i = 0; i < bitfields_length_.size(); ++i) { + if (bitfields_length_[i] < 0) + return false; + } + return true; +} + +bool +AggregateType::has_int_field() const +{ + for (size_t i=0; ihas_int_field()) return true; + } + return false; +} + +unsigned long +AggregateType::SizeInBytes(void) const +{ + size_t i; + switch (eType) { + case eUnion: { + unsigned int max_size = 0; + for (i=0; iSizeInBytes(); + } + if (sz == SIZE_UNKNOWN) return sz; + if (sz > max_size) { + max_size = sz; + } + } + return max_size; + } + case eStruct: { + if (!this->packed_) return SIZE_UNKNOWN; + // give up if there are bitfields, too much compiler-dependence and machine-dependence + if (this->has_bitfields()) return SIZE_UNKNOWN; + unsigned int total_size = 0; + for (i=0; iSizeInBytes(); + if (sz == SIZE_UNKNOWN) return sz; + total_size += sz; + } + return total_size; + } + } + return 0; +} + + + +void +AggregateType::get_int_subfield_names(string prefix, vector& names, const vector& excluded_fields) const +{ + size_t i; + size_t j = 0; + for (i=0; i empty; + fields[i]->get_int_subfield_names(oss.str(), names, empty); + } +} + +bool +AggregateType::contain_pointer_field(void) const +{ + if (eType == eStruct || eType == eUnion) { + for (size_t i=0; icontain_pointer_field()) { + return true; + } + } + } + return false; +} + +// --------------------------------------------------------------------- +void +AggregateType::Output(std::ostream &out) const +{ + switch (eType) { + case eUnion: out << "union U" << sid; break; + case eStruct: out << "struct S" << sid; break; + } +} + +// --------------------------------------------------------------------- +/* print struct definition (fields etc) + *************************************************************/ +static void +OutputStructUnion(Type* aggregate_type, std::ostream &out) +{ + size_t i; + // sanity check + assert (aggregate_type->is_aggregate()); + AggregateType * type = dynamic_cast(aggregate_type); + if (!type->printed) { + // output dependent structs, if any + for (i=0; ifields.size(); i++) { + if (type->fields[i]->is_aggregate()) { + OutputStructUnion((Type*)type->fields[i], out); + } + } + // output myself + if (type->packed_) { + if (!CGOptions::ccomp()) { + out << "#pragma pack(push)"; + really_outputln(out); + } + out << "#pragma pack(1)"; + really_outputln(out); + } + type->Output(out); + out << " {"; + really_outputln(out); + + assert(type->fields.size() == type->qfers_.size()); + unsigned int j = 0; + for (i=0; ifields.size(); i++) { + out << " "; + const Type *field = type->fields[i]; + bool is_bitfield = type->is_bitfield(i); + if (is_bitfield) { + assert(field->eType == eSimple); + type->qfers_[i].OutputFirstQuals(out); + if (field->simple_type == eInt) + out << "signed"; + else if (field->simple_type == eUInt) + out << "unsigned"; + else + assert(0); + int length = type->bitfields_length_[i]; + assert(length >= 0); + if (length == 0) + out << " : "; + else + out << " f" << j++ << " : "; + out << length << ";"; + } + else { + type->qfers_[i].output_qualified_type(field, out); + out << " f" << j++ << ";"; + } + really_outputln(out); + } + out << "};"; + really_outputln(out); + if (type->packed_) { + if (CGOptions::ccomp()) { + out << "#pragma pack()"; + } + else { + out << "#pragma pack(pop)"; + } + really_outputln(out); + } + type->printed = true; + really_outputln(out); + } +} + +// --------------------------------------------------------------------- +/* print all struct definitions (fields etc) + *************************************************************/ +void +OutputStructUnionDeclarations(std::ostream &out) +{ + size_t i; + output_comment_line(out, "--- Struct/Union Declarations ---"); + for (i=0; iused && (t->eType == eStruct || t->eType == eUnion)) { + OutputStructUnion(Type::AllTypes[i], out); + } + } +} +/* + * return the printf directive string for the type. for example, int -> "%d" + */ +std::string +AggregateType::printf_directive(void) const +{ + string ret; + size_t i; + switch (eType) { + case eUnion: + case eStruct: + ret = "{"; + for (i=0; i 0) ret += ", "; + ret += fields[i]->printf_directive(); + } + ret += "}"; + break; + } + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// c-basic-offset: 4 +// tab-width: 4 +// End: + +// End of file. diff --git a/src/AggregateType.h b/src/AggregateType.h new file mode 100755 index 000000000..fe8dca7ca --- /dev/null +++ b/src/AggregateType.h @@ -0,0 +1,136 @@ +// -*- mode: C++ -*- +// +// Copyright (c) 2007, 2008, 2010, 2011, 2013, 2014 The University of Utah +// All rights reserved. +// +// Copyright (c) 2015-2016 Huawei Technologies Co., Ltd +// All rights reserved. +// +// This file is part of `csmith', a random generator of C programs. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// This file was derived from a random program generator written by Bryan +// Turner. The attributions in that file was: +// +// Random Program Generator +// Bryan Turner (bryan.turner@pobox.com) +// July, 2005 +// + +#ifndef AGGREGATETYPE_H +#define AGGREGATETYPE_H + +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "CommonMacros.h" +#include "StatementAssign.h" +#include "CVQualifiers.h" +#include "Type.h" +#include "PointerType.h" + +using namespace std; + +/* + * + */ +class AggregateType : public Type +{ +public: + + static void get_all_ok_struct_union_types(vector &ok_types, bool no_const, bool no_volatile, bool need_int_field, bool bStruct); + + static const Type *choose_random_struct_from_type(const Type* type, bool no_volatile); + + static const AggregateType* choose_random_struct_union_type(vector &ok_types); + + // make a random struct or union type + static AggregateType* make_random_struct_type(void); + + static AggregateType* make_random_union_type(void); + + AggregateType(vector& struct_fields, bool isStruct, bool packed, + vector &qfers, vector &fields_length); + ~AggregateType() { /* Nothing else to do. */ } + + bool has_int_field() const ; + int get_struct_depth(void) const ; + bool is_unamed_padding(size_t index) const ; + bool is_full_bitfields_struct() const ; + bool is_bitfield(size_t index) const ; + bool has_bitfields() const ; + bool has_padding(void) const ; + bool contain_pointer_field(void) const ; + bool is_const_struct_union() const ; + bool is_volatile_struct_union() const ; + void get_int_subfield_names(string prefix, vector& names, const vector& excluded_fields) const ; + + unsigned long SizeInBytes(void) const ; + void Output(std::ostream &) const ; + std::string printf_directive(void) const ; + + vector fields; // for struct/union types + unsigned int sid; // sequence id, for struct/union types + + bool printed; // whether this struct/union has been printed in the random program + const bool packed_; // whether this struct/union should be packed + vector qfers_; // conresponds to each element of fields + // It's a tradeoff between the current implementation and the + // need of struct's level type qualifiers. + vector bitfields_length_; // -1 means it's a regular field + + +private: + + + static void make_one_bitfield(vector &random_fields, + vector &qualifiers, + vector &fields_length); + + static void make_one_struct_field(vector &random_fields, + vector &qualifiers, + vector &fields_length); + + static void make_one_union_field(vector &fields, vector &qfers, vector &lens); + + static void make_full_bitfields_struct_fields(size_t field_cnt, vector &random_fields, + vector &qualifiers, + vector &fields_length); + + static void make_normal_struct_fields(size_t field_cnt, vector &random_fields, + vector &qualifiers, + vector &fields_length); + + static bool has_aggregate_field(const vector &fields); + + static bool has_longlong_field(const vector &fields); + +}; + +void OutputStructUnionDeclarations(std::ostream &); + +#endif // AGGREGATETYPE_H \ No newline at end of file diff --git a/src/PointerType.cpp b/src/PointerType.cpp new file mode 100755 index 000000000..555ce7742 --- /dev/null +++ b/src/PointerType.cpp @@ -0,0 +1,229 @@ +// -*- mode: C++ -*- +// +// Copyright (c) 2007, 2008, 2010, 2011, 2013, 2014 The University of Utah +// All rights reserved. +// +// Copyright (c) 2015-2016 Huawei Technologies Co., Ltd +// All rights reserved. +// +// This file is part of `csmith', a random generator of C programs. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// This file was derived from a random program generator written by Bryan +// Turner. The attributions in that file was: +// +// Random Program Generator +// Bryan Turner (bryan.turner@pobox.com) +// July, 2005 +// + +#include "PointerType.h" +#include +#include +#include +#include "Common.h" +#include "CGOptions.h" +#include "random.h" +#include "Filter.h" +#include "util.h" +#include "Bookkeeper.h" +#include "Probabilities.h" + +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// + +// --------------------------------------------------------------------- +// List of all types used in the program +vector PointerType::derived_types; + +/////////////////////////////////////////////////////////////////////////////// + +// -------------------------------------------------------------- + /* constructor for pointers + *******************************************************/ +PointerType::PointerType(const Type* t) : + ptr_type(t) +{ + eType = ePointer; +} + +// --------------------------------------------------------------------- +/* find the pointer type to the given type in existing types, + * return 0 if not found + *************************************************************/ +PointerType * +PointerType::find_pointer_type(const Type* t, bool add) +{ + for (size_t i=0; iptr_type == t) { + return derived_types[i]; + } + } + if (add) { + PointerType* ptr_type = new PointerType(t); + derived_types.push_back(ptr_type); + return ptr_type; + } + return 0; +} + +// --------------------------------------------------------------------- +PointerType* +PointerType::make_random_pointer_type(void) +{ + //Type* new_type = 0; + //Type* ptr_type = 0; + // occasionally choose pointer to pointers + if (rnd_flipcoin(20)) { + if (derived_types.size() > 0) { + unsigned int rnd_num = rnd_upto(derived_types.size()); + const PointerType* t = derived_types[rnd_num]; + if (t->get_indirect_level() < CGOptions::max_indirect_level()) { + return find_pointer_type(t, true); + } + } + } + + // choose a pointer to basic/aggregate types + const Type* t = choose_random(); + // consolidate all integer pointer types into "int*", hopefully this increase + // chance of pointer assignments and dereferences + if (t->eType == eSimple) { + t = get_int_type(); + } + return find_pointer_type(t, true); +} + +const PointerType * +PointerType::choose_random_pointer_type(void) +{ + unsigned int index = rnd_upto(derived_types.size()); + return derived_types[index]; +} + +bool +PointerType::has_pointer_type(void) +{ + return derived_types.size() > 0; +} + +/* + * + */ +void +PointerType::doFinalization(void) +{ + vector::iterator j; + for(j = derived_types.begin(); j != derived_types.end(); ++j) + delete (*j); + derived_types.clear(); +} + +// --------------------------------------------------------------------- +int +PointerType::get_indirect_level() const +{ + int level = 0; + const Type* pt = ptr_type; + while (pt != 0) { + level++; + pt = (pt->eType == ePointer) ? (dynamic_cast(pt))->ptr_type : NULL; + } + return level; +} + +const Type* +PointerType::get_base_type(void) const +{ + const Type* tmp = this; + while (tmp->eType == ePointer) { + tmp = (dynamic_cast(tmp))->ptr_type; + } + return tmp; +} + +// --------------------------------------------------------------------- +/* generally integer types can be converted to any other interger types + * void / struct / union / array types are not. Pointers depend on the + * type they point to. (unsigned int*) is convertable to (int*), etc + *************************************************************/ +bool +PointerType::is_convertable(const Type* t) const +{ + if (this == t) + return true; + if (t->eType == ePointer) { + if (ptr_type == (dynamic_cast(t))->ptr_type) { + return true; + } + if (ptr_type->eType == eSimple && (dynamic_cast(t))->ptr_type->eType == eSimple) { + if(ptr_type->simple_type == eFloat && (dynamic_cast(t))->ptr_type->simple_type == eFloat) + return true; + else + return ptr_type->SizeInBytes() == (dynamic_cast(t))->ptr_type->SizeInBytes(); + } + } + return false; +} + +// --------------------------------------------------------------------- +/* return true if this type can be derived from the given type + * by taking address(one level) or dereferencing (multi-level) + * question: allow interger conversion? i.e. char* p = &(int)i? + *************************************************************/ +bool +PointerType::is_derivable(const Type* t) const +{ + if (this == t) { + return true; + } + return is_convertable(t) || is_dereferenced_from(t) || (ptr_type==t); +} + +// --------------------------------------------------------------------- +void +PointerType::Output(std::ostream &out) const +{ + ptr_type->Output( out ); out << "*"; +} + +/* + * return the printf directive string for the type. for example, int -> "%d" + */ +std::string +PointerType::printf_directive(void) const +{ + return "0x%0x"; +} + +/////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// c-basic-offset: 4 +// tab-width: 4 +// End: + +// End of file. diff --git a/src/PointerType.h b/src/PointerType.h new file mode 100755 index 000000000..1eae2759c --- /dev/null +++ b/src/PointerType.h @@ -0,0 +1,95 @@ +// -*- mode: C++ -*- +// +// Copyright (c) 2007, 2008, 2010, 2011, 2013, 2014 The University of Utah +// All rights reserved. +// +// Copyright (c) 2015-2016 Huawei Technologies Co., Ltd +// All rights reserved. +// +// This file is part of `csmith', a random generator of C programs. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// This file was derived from a random program generator written by Bryan +// Turner. The attributions in that file was: +// +// Random Program Generator +// Bryan Turner (bryan.turner@pobox.com) +// July, 2005 +// + +#ifndef POINTERTYPE_H +#define POINTERTYPE_H + +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "CommonMacros.h" +#include "StatementAssign.h" +#include "CVQualifiers.h" +#include "Type.h" + +using namespace std; + +/* + * + */ +class PointerType : public Type +{ +public: + explicit PointerType(const Type* t); + + ~PointerType() { /* Nothing else to do. */ } + + static bool has_pointer_type(void); + + // make a random pointer type + static PointerType* make_random_pointer_type(void); + + static PointerType* find_pointer_type(const Type* t, bool add); + + // choose a random pointer type + static const PointerType* choose_random_pointer_type(void); + + static void doFinalization(void); + + const Type* get_base_type(void) const ; + int get_indirect_level(void) const ; + bool is_pointer_to_char(void) const { return ptr_type && ptr_type->eType == eSimple && (ptr_type->simple_type==eChar || ptr_type->simple_type==eUChar);} + bool is_convertable(const Type* t) const ; + bool is_derivable(const Type* t) const ; + + void Output(std::ostream &) const ; + std::string printf_directive(void) const ; + + const Type *ptr_type; + +private: + static vector derived_types; + +}; + +#endif // POINTERTYPE_H \ No newline at end of file