From: Dodji Seketeli Date: Fri, 7 Nov 2014 11:13:53 +0000 (+0100) Subject: Fix template parameter hashing: make it know about enclosing template X-Git-Tag: 1.0.rc0~446 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=d3b188f859001353df9e39ab4c7a2264627fbf86;p=libabigail.git Fix template parameter hashing: make it know about enclosing template * include/abg-ir.h (template_parameter_sptr, template_decl_sptr) (template_decl_wptr): Declare new typedefs. (class template_decl): Make this virtually inherit decl_base and pimpl-ify it. (class template_parameter): Pimpl-ify this. Make the constructor take the enclosing template parameter. (struct template_decl::hash): Declare this here, rather than in src/abg-hash.cc (class type_tparameter, non_type_tparameter, template_tparameter) (class type_composition, function_tdecl, class_tdecl): Pimpl-ify this. * src/abg-hash.cc (template_parameter::hash::operator()): Hash the enclosing template parameter. Avoid infinite recursion due to the loop hash parameter -> hash template -> hash parameter. (template_decl::hash::operator()) Define this here, now that it's declared in abg-ir.h. Also, avoid infinite recursion here; this is complementary to what is done in the hashing for template_parameter. ({type_tparameter, template_tparameter, }::hash::operator()): Cache the calculated hash just as what is done for other types hashed. (template_decl::priv): Define this new type. (template_decl::{add_template_parameter, get_template_parameters, ~template_decl}): Define these here to pimpl-ify template_decl. (template_parameter::priv): Define this new type. (template_parameter::template_parameter): Define this here to pimpl-ify template_parameter. Note also that this now takes the enclosing template decl. (template_parameter::{get_index, get_enclosing_template_decl, get_hashing_has_started, set_hashing_has_started, operator::==}): Define these here to pimpl-ify template_parameter. (type_tparameter::priv): Define this new type. (type_tparameter::type_tparameter): Define this here to pimpl-ify type_tparameter. Also, not that this constructor now takes the enclosing template decl. (class non_type_tparameter::priv): Define new type. (non_type_tparameter::{non_type_tparameter, get_type}): Define these here to pimpl-ify non_type_tparameter. The constructor now takes the enclosing template. (template_tparameter::priv): Define new type. (template_tparameter::template_tparameter): Define this here to pimpl-ify template_tparameter. This constructor now takes the enclosing template. (class type_composition::priv): New type. (type_composition::{type_composition, get_composed_type, set_composed_type}): Define these here to pimpl-ify type_composition. The constructor now takes the enclosing template decl. (class function_tdecl::priv): Define new type. (function_tdecl::{function_tdecl, set_pattern, get_pattern, get_binding}): Define this here to pimpl-ify function_tdecl. (class class_tdecl::priv): Define this new type. (class_tdecl::class_tdecl): Define this here to pimpl-ify class_tdecl. (class_tdecl::set_pattern): Adjust to pimpl-ify. (class_tdecl::get_pattern): Define new pimpl-ified getter. * src/abg-reader.cc (build_function_tdecl, build_class_tdecl): Cleanup. Pass the enclosing template to the template parameters that are built. (build_type_tparameter, build_type_composition) (build_non_type_tparameter, build_template_tparameter) (build_template_parameter): Take the enclosing template declaration and pass it to the template parameter being created. * tests/data/test-read-write/test12.xml: Fix and Adjust. * tests/data/test-read-write/test13.xml: Likewise. Signed-off-by: Dodji Seketeli --- diff --git a/include/abg-ir.h b/include/abg-ir.h index eae03995..a1753012 100644 --- a/include/abg-ir.h +++ b/include/abg-ir.h @@ -2067,27 +2067,38 @@ public: virtual ~method_type(); };// end class method_type. +/// Convenience typedef for shared pointer to template parameter +typedef shared_ptr template_parameter_sptr; + +/// Convenience typedef for a shared pointer to template_decl +typedef shared_ptr template_decl_sptr; + +/// Convenience typedef for a weak pointer to template_decl +typedef weak_ptr template_decl_wptr; + /// The base class of templates. -class template_decl +class template_decl : public virtual decl_base { - // XXX - std::list > parms_; + class priv; + typedef shared_ptr priv_sptr; + priv_sptr priv_; + + template_decl(); public: /// Hasher. struct hash; - template_decl() - {} + template_decl(const string& name, + location locus, + visibility vis = VISIBILITY_DEFAULT); void - add_template_parameter(shared_ptr p) - {parms_.push_back(p);} + add_template_parameter(const template_parameter_sptr p); - const std::list >& - get_template_parameters() const - {return parms_;} + const std::list& + get_template_parameters() const; virtual bool operator==(const template_decl& o) const; @@ -2100,7 +2111,9 @@ public: /// non_type_template_parameter and template_template_parameter below. class template_parameter { - unsigned index_; + class priv; + typedef shared_ptr priv_sptr; + priv_sptr priv_; // Forbidden template_parameter(); @@ -2112,22 +2125,44 @@ class template_parameter struct dynamic_hash; struct shared_ptr_hash; - template_parameter(unsigned index) : index_(index) - {} + template_parameter(unsigned index, + template_decl_sptr enclosing_tdecl); virtual bool operator==(const template_parameter&) const; unsigned - get_index() const - {return index_;} + get_index() const; + + const template_decl_sptr + get_enclosing_template_decl() const; + + bool + get_hashing_has_started() const; + + void + set_hashing_has_started(bool f) const; virtual ~template_parameter(); };//end class template_parameter +struct template_decl::hash +{ + size_t + operator()(const template_decl& t) const; +};// end struct template_decl::hash + +/// Convenience typedef for a shared pointer to @ref type_tparameter. +typedef shared_ptr type_tparameter_sptr; + /// Abstracts a type template parameter. class type_tparameter : public template_parameter, public virtual type_decl { + class priv; + typedef shared_ptr priv_sptr; + + priv_sptr priv_; + // Forbidden type_tparameter(); @@ -2136,14 +2171,10 @@ public: /// Hasher. struct hash; - type_tparameter(unsigned index, - const std::string& name, - location locus) - : decl_base(name, locus), - type_base(0, 0), - type_decl(name, 0, 0, locus), - template_parameter(index) - {} + type_tparameter(unsigned index, + template_decl_sptr enclosing_tdecl, + const std::string& name, + location locus); virtual bool operator==(const type_base&) const; @@ -2157,9 +2188,18 @@ public: virtual ~type_tparameter(); };// end class type_tparameter. +/// Convenience typedef for shared pointer to @ref +/// non_type_template_parameter +typedef shared_ptr non_type_tparameter_sptr; + /// Abstracts non type template parameters. class non_type_tparameter : public template_parameter, public virtual decl_base { + class priv; + typedef shared_ptr priv_sptr; + + priv_sptr priv_; + type_base_wptr type_; // Forbidden @@ -2169,13 +2209,11 @@ public: /// Hasher. struct hash; - non_type_tparameter(unsigned index, const std::string& name, - shared_ptr type, location locus) - : decl_base(name, locus, ""), - template_parameter(index), - type_(type) - {} - + non_type_tparameter(unsigned index, + template_decl_sptr enclosing_tdecl, + const std::string& name, + shared_ptr type, + location locus); virtual size_t get_hash() const; @@ -2185,13 +2223,8 @@ public: virtual bool operator==(const template_parameter&) const; - type_base_sptr - get_type() const - { - if (type_.expired()) - return type_base_sptr(); - return type_base_sptr(type_); - } + const type_base_sptr + get_type() const; virtual ~non_type_tparameter(); };// end class non_type_tparameter @@ -2206,9 +2239,18 @@ struct non_type_tparameter::hash operator()(const non_type_tparameter* t) const; }; +class template_tparameter; + +/// Convenience typedef for a shared_ptr to @ref template_tparameter. +typedef shared_ptr template_tparameter_sptr; + /// Abstracts a template template parameter. class template_tparameter : public type_tparameter, public template_decl { + class priv; + typedef shared_ptr priv_sptr; + priv_sptr priv_; + // Forbidden template_tparameter(); @@ -2218,13 +2260,9 @@ public: struct hash; template_tparameter(unsigned index, - const std::string& name, - location locus) - : decl_base(name, locus), - type_base(0, 0), - type_decl(name, 0, 0, locus, name, VISIBILITY_DEFAULT), - type_tparameter(index, name, locus) - {} + template_decl_sptr enclosing_tdecl, + const std::string& name, + location locus); virtual bool operator==(const type_base&) const; @@ -2238,6 +2276,9 @@ public: virtual ~template_tparameter(); }; +/// Convenience typedef for shared pointer to type_composition +typedef shared_ptr type_composition_sptr; + /// This abstracts a composition of types based on template type /// parameters. The result of the composition is a type that can be /// referred to by a template non-type parameter. Instances of this @@ -2245,27 +2286,25 @@ public: /// scope of a template_decl. class type_composition : public template_parameter, public virtual decl_base { - type_base_wptr type_; + class priv; + typedef shared_ptr priv_sptr; + + priv_sptr priv_; type_composition(); public: struct hash; - type_composition(unsigned index, - shared_ptr composed_type); + type_composition(unsigned index, + template_decl_sptr tdecl, + type_base_sptr composed_type); - type_base_sptr - get_composed_type() const - { - if (type_.expired()) - return type_base_sptr(); - return type_base_sptr(type_); - } + const type_base_sptr + get_composed_type() const; void - set_composed_type(type_base_sptr t) - {type_ = t;} + set_composed_type(type_base_sptr t); virtual size_t get_hash() const; @@ -2290,8 +2329,10 @@ typedef shared_ptr function_tdecl_sptr; /// Abstract a function template declaration. class function_tdecl : public template_decl, public scope_decl { - shared_ptr pattern_; - binding binding_; + class priv; + typedef shared_ptr priv_sptr; + + priv_sptr priv_; // Forbidden function_tdecl(); @@ -2302,22 +2343,14 @@ public: struct hash; struct shared_ptr_hash; - function_tdecl(location locus, - visibility vis = VISIBILITY_DEFAULT, - binding bind = BINDING_NONE) - : decl_base("", locus, "", vis), scope_decl("", locus), - binding_(bind) - {} + function_tdecl(location locus, + visibility vis = VISIBILITY_DEFAULT, + binding bind = BINDING_NONE); - function_tdecl(shared_ptr pattern, - location locus, - visibility vis = VISIBILITY_DEFAULT, - binding bind = BINDING_NONE) - : decl_base(pattern->get_name(), locus, - pattern->get_name(), vis), - scope_decl(pattern->get_name(), locus), - binding_(bind) - {set_pattern(pattern);} + function_tdecl(function_decl_sptr pattern, + location locus, + visibility vis = VISIBILITY_DEFAULT, + binding bind = BINDING_NONE); virtual bool operator==(const decl_base&) const; @@ -2326,20 +2359,13 @@ public: operator==(const template_decl&) const; void - set_pattern(shared_ptr p) - { - pattern_ = p; - add_decl_to_scope(p, this); - set_name(p->get_name()); - } + set_pattern(shared_ptr p); shared_ptr - get_pattern() const - {return pattern_;} + get_pattern() const; binding - get_binding() const - {return binding_;} + get_binding() const; virtual bool traverse(ir_node_visitor& v); @@ -2353,7 +2379,10 @@ typedef shared_ptr class_tdecl_sptr; /// Abstract a class template. class class_tdecl : public template_decl, public scope_decl { - shared_ptr pattern_; + class priv; + typedef shared_ptr priv_sptr; + + priv_sptr priv_; // Forbidden class_tdecl(); @@ -2364,9 +2393,7 @@ public: struct hash; struct shared_ptr_hash; - class_tdecl(location locus, visibility vis = VISIBILITY_DEFAULT) - : decl_base("", locus, "", vis), scope_decl("", locus) - {} + class_tdecl(location locus, visibility vis = VISIBILITY_DEFAULT); class_tdecl(shared_ptr pattern, location locus, visibility vis = VISIBILITY_DEFAULT); @@ -2381,11 +2408,10 @@ public: operator==(const class_tdecl&) const; void - set_pattern(shared_ptr p); + set_pattern(class_decl_sptr p); shared_ptr - get_pattern() const - {return pattern_;} + get_pattern() const; virtual bool traverse(ir_node_visitor& v); diff --git a/src/abg-hash.cc b/src/abg-hash.cc index a27660bc..7d9ad2a3 100644 --- a/src/abg-hash.cc +++ b/src/abg-hash.cc @@ -688,11 +688,26 @@ struct template_parameter::hash size_t operator()(const template_parameter& t) const { + // Let's avoid infinite recursion triggered from the fact that + // hashing a template parameter triggers hashing the enclosed + // template decl, which in turn triggers the hashing of its + // template parameters; so the initial template parameter that + // triggered the hashing could be hashed again ... + if (t.get_hashing_has_started()) + return 0; + + t.set_hashing_has_started(true); + std::tr1::hash hash_unsigned; std::tr1::hash hash_string; + template_decl::hash hash_template_decl; size_t v = hash_string(typeid(t).name()); v = hashing::combine_hashes(v, hash_unsigned(t.get_index())); + v = hashing::combine_hashes(v, hash_template_decl + (*t.get_enclosing_template_decl())); + + t.set_hashing_has_started(false); return v; } @@ -708,44 +723,46 @@ struct template_parameter::shared_ptr_hash { size_t operator()(const shared_ptr t) const - { return template_parameter::dynamic_hash()(t.get()); } + {return template_parameter::dynamic_hash()(t.get());} }; -struct template_decl::hash +size_t +template_decl::hash::operator()(const template_decl& t) const { - size_t - operator()(const template_decl& t) const - { - std::tr1::hash hash_string; - template_parameter::shared_ptr_hash hash_template_parameter; + std::tr1::hash hash_string; + template_parameter::shared_ptr_hash hash_template_parameter; - size_t v = hash_string(typeid(t).name()); + size_t v = hash_string(typeid(t).name()); + v = hash_string(t.get_qualified_name()); - for (list >::const_iterator p = - t.get_template_parameters().begin(); - p != t.get_template_parameters().end(); - ++p) - { - v = hashing::combine_hashes(v, hash_template_parameter(*p)); - } - return v; - } -}; + for (list::const_iterator p = + t.get_template_parameters().begin(); + p != t.get_template_parameters().end(); + ++p) + if (!(*p)->get_hashing_has_started()) + v = hashing::combine_hashes(v, hash_template_parameter(*p)); + + return v; +} struct type_tparameter::hash { size_t operator()(const type_tparameter& t) const { - std::tr1::hash hash_string; - template_parameter::hash hash_template_parameter; - type_decl::hash hash_type; + if (t.peek_hash_value() == 0 || t.hashing_started()) + { + std::tr1::hash hash_string; + template_parameter::hash hash_template_parameter; + type_decl::hash hash_type; - size_t v = hash_string(typeid(t).name()); - v = hashing::combine_hashes(v, hash_template_parameter(t)); - v = hashing::combine_hashes(v, hash_type(t)); + size_t v = hash_string(typeid(t).name()); + v = hashing::combine_hashes(v, hash_template_parameter(t)); + v = hashing::combine_hashes(v, hash_type(t)); - return v; + t.set_hash(v); + } + return t.peek_hash_value(); } }; @@ -783,15 +800,19 @@ struct template_tparameter::hash size_t operator()(const template_tparameter& t) const { - std::tr1::hash hash_string; - type_tparameter::hash hash_template_type_parm; - template_decl::hash hash_template_decl; + if (t.peek_hash_value() == 0 || t.hashing_started()) + { + std::tr1::hash hash_string; + type_tparameter::hash hash_template_type_parm; + template_decl::hash hash_template_decl; - size_t v = hash_string(typeid(t).name()); - v = hashing::combine_hashes(v, hash_template_type_parm(t)); - v = hashing::combine_hashes(v, hash_template_decl(t)); + size_t v = hash_string(typeid(t).name()); + v = hashing::combine_hashes(v, hash_template_type_parm(t)); + v = hashing::combine_hashes(v, hash_template_decl(t)); + t.set_hash(v); + } - return v; + return t.peek_hash_value(); } }; diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 2c6b7412..90aa2b09 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -7517,10 +7517,43 @@ operator<<(std::ostream& o, access_specifier a) // -template_decl::~template_decl() +/// Data type of the private data of the @template_decl type. +class template_decl::priv +{ + friend class template_decl; + + std::list parms_; +public: + + priv() + {} +}; // end class template_decl::priv + +/// Add a new template parameter to the current instance of @ref +/// template_decl. +/// +/// @param p the new template parameter to add. +void +template_decl::add_template_parameter(const template_parameter_sptr p) +{priv_->parms_.push_back(p);} + +/// Get the list of template parameters of the current instance of +/// @ref template_decl. +/// +/// @return the list of template parameters. +const std::list& +template_decl::get_template_parameters() const +{return priv_->parms_;} + +template_decl::template_decl(const string& name, location locus, visibility vis) + : decl_base(name, locus, /*mangled_name=*/"", vis), + priv_(new priv) { } +template_decl::~template_decl() +{} + bool template_decl::operator==(const template_decl& o) const { @@ -7551,15 +7584,85 @@ template_decl::operator==(const template_decl& o) const // -bool -template_parameter::operator==(const template_parameter& o) const +/// The type of the private data of the @ref template_parameter type. +class template_parameter::priv { - return (get_index() == o.get_index()); + friend class template_parameter; + + unsigned index_; + template_decl_wptr template_decl_; + mutable bool hashing_started_; + + priv(); + +public: + + priv(unsigned index, template_decl_sptr enclosing_template_decl) + : index_(index), + template_decl_(enclosing_template_decl), + hashing_started_() + {} +}; // end class template_parameter::priv + +template_parameter::template_parameter(unsigned index, + template_decl_sptr enclosing_template) + : priv_(new priv(index, enclosing_template)) + {} + +unsigned +template_parameter::get_index() const +{return priv_->index_;} + +const template_decl_sptr +template_parameter::get_enclosing_template_decl() const +{ + if (priv_->template_decl_.expired()) + return template_decl_sptr(); + return template_decl_sptr(priv_->template_decl_); } +bool +template_parameter::get_hashing_has_started() const +{return priv_->hashing_started_;} + +void +template_parameter::set_hashing_has_started(bool f) const +{priv_->hashing_started_ = f;} + +bool +template_parameter::operator==(const template_parameter& o) const +{return (get_index() == o.get_index());} + template_parameter::~template_parameter() {} +/// The type of the private data of the @ref type_tparameter type. +class type_tparameter::priv +{ + friend class type_tparameter; +}; // end class type_tparameter::priv + +/// Constructor of the @ref type_tparameter type. +/// +/// @param index the index the type template parameter. +/// +/// @param enclosing_tdecl the enclosing template declaration. +/// +/// @param name the name of the template parameter. +/// +/// @param locus the location of the declaration of this type template +/// parameter. +type_tparameter::type_tparameter(unsigned index, + template_decl_sptr enclosing_tdecl, + const std::string& name, + location locus) + : decl_base(name, locus), + type_base(0, 0), + type_decl(name, 0, 0, locus), + template_parameter(index, enclosing_tdecl), + priv_(new priv) +{} + bool type_tparameter::operator==(const type_base& other) const { @@ -7594,6 +7697,56 @@ type_tparameter::operator==(const type_tparameter& other) const type_tparameter::~type_tparameter() {} +/// The type of the private data of the @ref non_type_tparameter type. +class non_type_tparameter::priv +{ + friend class non_type_tparameter; + + type_base_wptr type_; + + priv(); + +public: + + priv(type_base_sptr type) + : type_(type) + {} +}; // end class non_type_tparameter::priv + +/// The constructor for the @ref non_type_tparameter type. +/// +/// @param index the index of the template parameter. +/// +/// @param enclosing_tdecl the enclosing template declaration that +/// holds this parameter parameter. +/// +/// @param name the name of the template parameter. +/// +/// @param type the type of the template parameter. +/// +/// @param locus the location of the declaration of this template +/// parameter. +non_type_tparameter::non_type_tparameter(unsigned index, + template_decl_sptr enclosing_tdecl, + const std::string& name, + type_base_sptr type, + location locus) + : decl_base(name, locus, ""), + template_parameter(index, enclosing_tdecl), + priv_(new priv(type)) +{} + +/// Getter for the type of the template parameter. +/// +/// @return the type of the template parameter. +const type_base_sptr +non_type_tparameter::get_type() const +{ + if (priv_->type_.expired()) + return type_base_sptr(); + return type_base_sptr(priv_->type_); +} + /// Get the hash value of the current instance. /// /// @return the hash value. @@ -7636,6 +7789,35 @@ non_type_tparameter::operator==(const template_parameter& other) const non_type_tparameter::~non_type_tparameter() {} +// + +/// Type of the private data of the @ref template_tparameter type. +class template_tparameter::priv +{ +}; //end class template_tparameter::priv + +/// Constructor for the @ref template_tparameter. +/// +/// @param index the index of the template parameter. +/// +/// @param enclosing_tdecl the enclosing template declaration. +/// +/// @param name the name of the template parameter. +/// +/// @param locus the location of the declaration of the template +/// parameter. +template_tparameter::template_tparameter(unsigned index, + template_decl_sptr enclosing_tdecl, + const std::string& name, + location locus) + : decl_base(name, locus), + type_base(0, 0), + type_decl(name, 0, 0, locus, name, VISIBILITY_DEFAULT), + type_tparameter(index, enclosing_tdecl, name, locus), + template_decl(name, locus), + priv_(new priv) +{} + bool template_tparameter::operator==(const type_base& other) const { @@ -7679,11 +7861,61 @@ template_tparameter::operator==(const template_decl& o) const template_tparameter::~template_tparameter() {} -type_composition::type_composition(unsigned index, shared_ptr t) -: decl_base("", location()), template_parameter(index), - type_(std::tr1::dynamic_pointer_cast(t)) +// + +// + +/// The type of the private data of the @ref type_composition type. +class type_composition::priv +{ + friend class type_composition; + + type_base_wptr type_; + + // Forbid this. + priv(); + +public: + + priv(type_base_wptr type) + : type_(type) + {} +}; //end class type_composition::priv + +/// Constructor for the @ref type_composition type. +/// +/// @param index the index of the template type composition. +/// +/// @param tdecl the enclosing template parameter that owns the +/// composition. +/// +/// @param t the resulting type. +type_composition::type_composition(unsigned index, + template_decl_sptr tdecl, + type_base_sptr t) + : decl_base("", location()), + template_parameter(index, tdecl), + priv_(new priv(t)) {} +/// Getter for the resulting composed type. +/// +/// @return the composed type. +const type_base_sptr +type_composition::get_composed_type() const +{ + if (priv_->type_.expired()) + return type_base_sptr(); + return type_base_sptr(priv_->type_); +} + +/// Setter for the resulting composed type. +/// +/// @param t the composed type. +void +type_composition::set_composed_type(type_base_sptr t) +{priv_->type_ = t;} + /// Get the hash value for the current instance. /// /// @return the hash value. @@ -7697,9 +7929,99 @@ type_composition::get_hash() const type_composition::~type_composition() {} -// +// + +// // + +class function_tdecl::priv +{ + friend class function_tdecl; + + function_decl_sptr pattern_; + binding binding_; + + priv(); + +public: + + priv(function_decl_sptr pattern, binding bind) + : pattern_(pattern), binding_(bind) + {} + + priv(binding bind) + : binding_(bind) + {} +}; // end class function_tdecl::priv + +/// Constructor for a function template declaration. +/// +/// @param locus the location of the declaration. +/// +/// @param vis the visibility of the declaration. This is the +/// visibility the functions instantiated from this template are going +/// to have. +/// +/// @param bind the binding of the declaration. This is the binding +/// the functions instantiated from this template are going to have. +function_tdecl::function_tdecl(location locus, + visibility vis, + binding bind) + : decl_base("", locus, "", vis), + template_decl("", locus, vis), + scope_decl("", locus), + priv_(new priv(bind)) +{} + +/// Constructor for a function template declaration. +/// +/// @param pattern the pattern of the template. +/// +/// @param locus the location of the declaration. +/// +/// @param vis the visibility of the declaration. This is the +/// visibility the functions instantiated from this template are going +/// to have. +/// +/// @param bind the binding of the declaration. This is the binding +/// the functions instantiated from this template are going to have. +function_tdecl::function_tdecl(function_decl_sptr pattern, + location locus, + visibility vis, + binding bind) + : decl_base(pattern->get_name(), locus, + pattern->get_name(), vis), + template_decl(pattern->get_name(), locus, vis), + scope_decl(pattern->get_name(), locus), + priv_(new priv(pattern, bind)) +{} + +/// Set a new pattern to the function template. +/// +/// @param p the new pattern. +void +function_tdecl::set_pattern(function_decl_sptr p) +{ + priv_->pattern_ = p; + add_decl_to_scope(p, this); + set_name(p->get_name()); +} + +/// Get the pattern of the function template. +/// +/// @return the pattern. +function_decl_sptr +function_tdecl::get_pattern() const +{return priv_->pattern_;} + +/// Get the binding of the function template. +/// +/// @return the binding +decl_base::binding +function_tdecl::get_binding() const +{return priv_->binding_;} + bool function_tdecl::operator==(const decl_base& other) const { @@ -7758,7 +8080,37 @@ function_tdecl::~function_tdecl() // -/// Constructor for the class_tdecl type. +/// Type of the private data of the the @ref class_tdecl type. +class class_tdecl::priv +{ + friend class class_tdecl; + class_decl_sptr pattern_; + +public: + + priv() + {} + + priv(class_decl_sptr pattern) + : pattern_(pattern) + {} +}; // end class class_tdecl::priv + +/// Constructor for the @ref class_tdecl type. +/// +/// @param locus the location of the declaration of the class_tdecl +/// type. +/// +/// @param vis the visibility of the instance of class instantiated +/// from this template. +class_tdecl::class_tdecl(location locus, visibility vis) + : decl_base("", locus, "", vis), + template_decl("", locus, vis), + scope_decl("", locus), + priv_(new priv) +{} + +/// Constructor for the @ref class_tdecl type. /// /// @param pattern The details of the class template. This must NOT be a /// null pointer. If you really this to be null, please use the @@ -7768,21 +8120,33 @@ function_tdecl::~function_tdecl() /// /// @param vis the visibility of the instances of class instantiated /// from this template. -class_tdecl::class_tdecl(shared_ptr pattern, +class_tdecl::class_tdecl(class_decl_sptr pattern, location locus, visibility vis) : decl_base(pattern->get_name(), locus, pattern->get_name(), vis), - scope_decl(pattern->get_name(), locus) -{set_pattern(pattern);} + template_decl(pattern->get_name(), locus, vis), + scope_decl(pattern->get_name(), locus), + priv_(new priv(pattern)) +{} +/// Setter of the pattern of the template. +/// +/// @param p the new template. void -class_tdecl::set_pattern(shared_ptr p) +class_tdecl::set_pattern(class_decl_sptr p) { - pattern_ = p; + priv_->pattern_ = p; add_decl_to_scope(p, this); set_name(p->get_name()); } +/// Getter of the pattern of the template. +/// +/// @return p the new template. +class_decl_sptr +class_tdecl::get_pattern() const +{return priv_->pattern_;} + bool class_tdecl::operator==(const decl_base& other) const { diff --git a/src/abg-reader.cc b/src/abg-reader.cc index da7ffaf7..fb9bbac7 100644 --- a/src/abg-reader.cc +++ b/src/abg-reader.cc @@ -606,20 +606,25 @@ build_function_tdecl(read_context&, const xmlNodePtr, bool); static shared_ptr build_class_tdecl(read_context&, const xmlNodePtr, bool); -static shared_ptr -build_type_tparameter(read_context&, const xmlNodePtr, unsigned); +static type_tparameter_sptr +build_type_tparameter(read_context&, const xmlNodePtr, + unsigned, template_decl_sptr); -static shared_ptr -build_type_composition(read_context&, const xmlNodePtr, unsigned); +static type_composition_sptr +build_type_composition(read_context&, const xmlNodePtr, + unsigned, template_decl_sptr); -static shared_ptr -build_non_type_tparameter(read_context&, const xmlNodePtr, unsigned); +static non_type_tparameter_sptr +build_non_type_tparameter(read_context&, const xmlNodePtr, + unsigned, template_decl_sptr); -static shared_ptr -build_template_tparameter(read_context&, const xmlNodePtr, unsigned); +static template_tparameter_sptr +build_template_tparameter(read_context&, const xmlNodePtr, + unsigned, template_decl_sptr); -static shared_ptr -build_template_parameter(read_context&, const xmlNodePtr, unsigned); +static template_parameter_sptr +build_template_parameter(read_context&, const xmlNodePtr, + unsigned, template_decl_sptr); // Please make this build_type function be the last one of the list. // Note that it should call each type-building function above. So @@ -2918,8 +2923,7 @@ build_function_tdecl(read_context& ctxt, decl_base::binding bind = decl_base::BINDING_NONE; read_binding(node, bind); - shared_ptr fn_tmpl_decl - (new function_tdecl(loc, vis, bind)); + function_tdecl_sptr fn_tmpl_decl(new function_tdecl(loc, vis, bind)); ctxt.push_decl_to_current_scope(fn_tmpl_decl, add_to_current_scope); @@ -2929,8 +2933,8 @@ build_function_tdecl(read_context& ctxt, if (n->type != XML_ELEMENT_NODE) continue; - if (shared_ptr parm = - build_template_parameter(ctxt, n, parm_index)) + if (template_parameter_sptr parm = + build_template_parameter(ctxt, n, parm_index, fn_tmpl_decl)) { fn_tmpl_decl->add_template_parameter(parm); ++parm_index; @@ -2980,8 +2984,7 @@ build_class_tdecl(read_context& ctxt, decl_base::visibility vis = decl_base::VISIBILITY_NONE; read_visibility(node, vis); - shared_ptr class_tmpl - (new class_tdecl(loc, vis)); + class_tdecl_sptr class_tmpl (new class_tdecl(loc, vis)); ctxt.push_decl_to_current_scope(class_tmpl, add_to_current_scope); @@ -2991,8 +2994,8 @@ build_class_tdecl(read_context& ctxt, if (n->type != XML_ELEMENT_NODE) continue; - if (shared_ptr parm= - build_template_parameter(ctxt, n, parm_index)) + if (template_parameter_sptr parm= + build_template_parameter(ctxt, n, parm_index, class_tmpl)) { class_tmpl->add_template_parameter(parm); ++parm_index; @@ -3017,14 +3020,18 @@ build_class_tdecl(read_context& ctxt, /// @param index the index (occurrence index, starting from 0) of the /// template parameter. /// +/// @param tdecl the enclosing template declaration that holds the +/// template type parameter. +/// /// @return a pointer to a newly created instance of /// type_tparameter, a null pointer otherwise. -static shared_ptr -build_type_tparameter(read_context& ctxt, - const xmlNodePtr node, - unsigned index) +static type_tparameter_sptr +build_type_tparameter(read_context& ctxt, + const xmlNodePtr node, + unsigned index, + template_decl_sptr tdecl) { - shared_ptr nil, result; + type_tparameter_sptr nil, result; if (!xmlStrEqual(node->name, BAD_CAST("template-type-parameter"))) return nil; @@ -3050,7 +3057,7 @@ build_type_tparameter(read_context& ctxt, location loc; read_location(ctxt, node,loc); - result.reset(new type_tparameter(index, name, loc)); + result.reset(new type_tparameter(index, tdecl, name, loc)); if (id.empty()) ctxt.push_decl_to_current_scope(dynamic_pointer_cast(result), @@ -3071,20 +3078,24 @@ build_type_tparameter(read_context& ctxt, /// /// @param index the index of the previous normal template parameter. /// +/// @param tdecl the enclosing template declaration that holds this +/// template parameter type composition. +/// /// @return a pointer to a new instance of tmpl_parm_type_composition /// upon successful completion, a null pointer otherwise. -static shared_ptr -build_type_composition(read_context& ctxt, - const xmlNodePtr node, - unsigned index) +static type_composition_sptr +build_type_composition(read_context& ctxt, + const xmlNodePtr node, + unsigned index, + template_decl_sptr tdecl) { - shared_ptr nil, result; + type_composition_sptr nil, result; if (!xmlStrEqual(node->name, BAD_CAST("template-parameter-type-composition"))) return nil; - shared_ptr composed_type; - result.reset(new type_composition(index, composed_type)); + type_base_sptr composed_type; + result.reset(new type_composition(index, tdecl, composed_type)); ctxt.push_decl_to_current_scope(dynamic_pointer_cast(result), /*add_to_current_scope=*/true); @@ -3123,15 +3134,19 @@ build_type_composition(read_context& ctxt, /// /// @param index the index of the parameter. /// +/// @param tdecl the enclosing template declaration that holds this +/// non type template parameter. +/// /// @return a pointer to a newly created instance of /// non_type_tparameter upon successful completion, a null /// pointer code otherwise. -static shared_ptr -build_non_type_tparameter(read_context& ctxt, - const xmlNodePtr node, - unsigned index) +static non_type_tparameter_sptr +build_non_type_tparameter(read_context& ctxt, + const xmlNodePtr node, + unsigned index, + template_decl_sptr tdecl) { - shared_ptr r; + non_type_tparameter_sptr r; if (!xmlStrEqual(node->name, BAD_CAST("template-non-type-parameter"))) return r; @@ -3139,7 +3154,7 @@ build_non_type_tparameter(read_context& ctxt, string type_id; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id")) type_id = CHAR_STR(s); - shared_ptr type; + type_base_sptr type; if (type_id.empty() || !(type = ctxt.build_or_get_type_decl(type_id, true))) abort(); @@ -3151,7 +3166,7 @@ build_non_type_tparameter(read_context& ctxt, location loc; read_location(ctxt, node,loc); - r.reset(new non_type_tparameter(index, name, type, loc)); + r.reset(new non_type_tparameter(index, tdecl, name, type, loc)); ctxt.push_decl_to_current_scope(dynamic_pointer_cast(r), /*add_to_current_scope=*/true); @@ -3167,14 +3182,18 @@ build_non_type_tparameter(read_context& ctxt, /// /// @param index the index of the template parameter. /// +/// @param tdecl the enclosing template declaration that holds this +/// template template parameter. +/// /// @return a pointer to a new instance of template_tparameter /// upon successful completion, a null pointer otherwise. -static shared_ptr -build_template_tparameter(read_context& ctxt, - const xmlNodePtr node, - unsigned index) +static template_tparameter_sptr +build_template_tparameter(read_context& ctxt, + const xmlNodePtr node, + unsigned index, + template_decl_sptr tdecl) { - shared_ptr nil; + template_tparameter_sptr nil; if (!xmlStrEqual(node->name, BAD_CAST("template-template-parameter"))) return nil; @@ -3201,8 +3220,8 @@ build_template_tparameter(read_context& ctxt, location loc; read_location(ctxt, node, loc); - shared_ptr result - (new template_tparameter(index, name, loc)); + template_tparameter_sptr result(new template_tparameter(index, tdecl, + name, loc)); ctxt.push_decl_to_current_scope(result, /*add_to_current_scope=*/true); @@ -3214,7 +3233,7 @@ build_template_tparameter(read_context& ctxt, continue; if (shared_ptr p = - build_template_parameter(ctxt, n, parm_index)) + build_template_parameter(ctxt, n, parm_index, result)) { result->add_template_parameter(p); ++parm_index; @@ -3236,19 +3255,23 @@ build_template_tparameter(read_context& ctxt, /// /// @param index the index of the template parameter we are parsing. /// +/// @param tdecl the enclosing template declaration that holds this +/// template parameter. +/// /// @return a pointer to a newly created instance of /// template_parameter upon successful completion, a null pointer /// otherwise. -static shared_ptr +static template_parameter_sptr build_template_parameter(read_context& ctxt, const xmlNodePtr node, - unsigned index) + unsigned index, + template_decl_sptr tdecl) { shared_ptr r; - ((r = build_type_tparameter(ctxt, node, index)) - || (r = build_non_type_tparameter(ctxt, node, index)) - || (r = build_template_tparameter(ctxt, node, index)) - || (r = build_type_composition(ctxt, node, index))); + ((r = build_type_tparameter(ctxt, node, index, tdecl)) + || (r = build_non_type_tparameter(ctxt, node, index, tdecl)) + || (r = build_template_tparameter(ctxt, node, index, tdecl)) + || (r = build_type_composition(ctxt, node, index, tdecl))); return r; } diff --git a/tests/data/test-read-write/test12.xml b/tests/data/test-read-write/test12.xml index c97a2ab0..76e1cfa0 100644 --- a/tests/data/test-read-write/test12.xml +++ b/tests/data/test-read-write/test12.xml @@ -17,9 +17,9 @@ - + - + diff --git a/tests/data/test-read-write/test13.xml b/tests/data/test-read-write/test13.xml index 6ffea598..42cad52b 100644 --- a/tests/data/test-read-write/test13.xml +++ b/tests/data/test-read-write/test13.xml @@ -19,9 +19,9 @@ - + - +