From 01f77f6d38283b4efbe2b55fc9c7c837fd6498dc Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 25 Mar 2010 13:47:43 +0200 Subject: Add support for union, enum, class/union template --- odb/plugin.cxx | 718 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 608 insertions(+), 110 deletions(-) (limited to 'odb/plugin.cxx') diff --git a/odb/plugin.cxx b/odb/plugin.cxx index 0f34a5b..bb50a3f 100644 --- a/odb/plugin.cxx +++ b/odb/plugin.cxx @@ -139,41 +139,12 @@ private: if (DECL_NAME (decl) != NULL_TREE) decls_.insert (decl); - /* - tree type (TREE_TYPE (decl)); - - if (TREE_CODE (type) == RECORD_TYPE) - { - tree name (DECL_NAME (decl)); - - if (name != NULL_TREE) - { - if (DECL_ARTIFICIAL (decl)) - { - // If we have an anonymous class typedef, use the user- - // supplied name instead of the synthesized one. ARM - // says that in typedef struct {} S; S becomes struct's - // name. - // - if (ANON_AGGRNAME_P (name)) - { - tree d (TYPE_NAME (type)); - - if (d != NULL_TREE && - !DECL_ARTIFICIAL (d) && - DECL_NAME (d) != NULL_TREE && - !ANON_AGGRNAME_P (DECL_NAME (d))) - { - decls_.insert (d); - } - } - else - decls_.insert (decl); - } - } - } - */ - + break; + } + case TEMPLATE_DECL: + { + if (DECL_CLASS_TEMPLATE_P (decl)) + decls_.insert (decl); break; } default: @@ -289,6 +260,7 @@ private: } case TEMPLATE_DECL: { + emit_template_decl (decl); break; } } @@ -302,10 +274,14 @@ private: emit_type_decl (tree decl) { tree t (TREE_TYPE (decl)); + int tc (TREE_CODE (t)); + tree decl_name (DECL_NAME (decl)); char const* name (IDENTIFIER_POINTER (decl_name)); - if (DECL_ARTIFICIAL (decl) && TREE_CODE (t) == RECORD_TYPE) + + if (DECL_ARTIFICIAL (decl) && + (tc == RECORD_TYPE || tc == UNION_TYPE || tc == ENUMERAL_TYPE)) { // If we have an anonymous class typedef, use the user- // supplied name instead of the synthesized one. ARM @@ -341,21 +317,42 @@ private: size_t line (DECL_SOURCE_LINE (decl)); size_t clmn (DECL_SOURCE_COLUMN (decl)); - warning (0, G_ ("start class declaration %s in %s:%d"), + warning (0, G_ ("start %s declaration %s in %s:%d"), + tree_code_name[tc], name, DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); - class_& node (emit_class (t, file, line, clmn)); + type* node (0); + + switch (tc) + { + case RECORD_TYPE: + { + node = &emit_class (t, file, line, clmn); + break; + } + case UNION_TYPE: + { + node = &emit_union (t, file, line, clmn); + break; + } + case ENUMERAL_TYPE: + { + node = &emit_enum (t, file, line, clmn); + break; + } + } if (COMPLETE_TYPE_P (t)) - unit_->new_edge (*scope_, node, name); + unit_->new_edge (*scope_, *node, name); else - unit_->new_edge (*scope_, node, name); + unit_->new_edge (*scope_, *node, name); - warning (0, G_ ("end class declaration %s (%p) in %s:%d"), + warning (0, G_ ("end %s declaration %s (%p) in %s:%d"), + tree_code_name[tc], name, - &node, + node, DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); } @@ -365,7 +362,9 @@ private: // class typedef case described above since we already used // this name to define the class. // - if (TREE_CODE (t) == RECORD_TYPE && + int tc (TREE_CODE (t)); + + if ((tc == RECORD_TYPE || tc == UNION_TYPE || tc == ENUMERAL_TYPE) && TYPE_NAME (TYPE_MAIN_VARIANT (t)) == decl) return; @@ -387,7 +386,215 @@ private: } } - class_& + // Emit a template declaration. + // + void + emit_template_decl (tree decl) + { + // Currently we only handle class/union templates. + // + tree t (TREE_TYPE (DECL_TEMPLATE_RESULT (decl))); + int tc (TREE_CODE (t)); + + warning (0, G_ ("%s template (%p) %s (%p) %s"), + tree_code_name[tc], + decl, + IDENTIFIER_POINTER (DECL_NAME (decl)), + t, + tree_code_name[TREE_CODE (t)]); + + warning (0, G_ ("specialization:")); + + for (tree s (DECL_TEMPLATE_SPECIALIZATIONS (decl)); + s != NULL_TREE; s = TREE_CHAIN (s)) + { + tree t (TREE_TYPE (s)); + tree d (TYPE_NAME (t)); + + warning (0, G_ ("\tspecialization %p at %s:%d"), + t, + DECL_SOURCE_FILE (d), + DECL_SOURCE_LINE (d)); + } + + warning (0, G_ ("instantiations:")); + + for (tree i (DECL_TEMPLATE_INSTANTIATIONS (decl)); + i != NULL_TREE; i = TREE_CHAIN (i)) + { + tree t (TREE_VALUE (i)); + tree d (TYPE_NAME (t)); + + warning (0, G_ ("\tinstantiation %p at %s:%d"), + t, + DECL_SOURCE_FILE (d), + DECL_SOURCE_LINE (d)); + } + + char const* name (IDENTIFIER_POINTER (DECL_NAME (decl))); + + warning (0, G_ ("start %s template %s in %s:%d"), + tree_code_name[tc], + name, + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + + type_template* t_node (0); + + if (tc == RECORD_TYPE) + t_node = &emit_class_template (decl); + else + t_node = &emit_union_template (decl); + + if (COMPLETE_TYPE_P (t)) + unit_->new_edge (*scope_, *t_node, name); + else + unit_->new_edge (*scope_, *t_node, name); + + warning (0, G_ ("end %s template %s (%p) in %s:%d"), + tree_code_name[tc], + name, + t_node, + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + } + + class_template& + emit_class_template (tree t, bool stub = false) + { + // See if there is a stub already for this template. + // + class_template* ct_node (0); + + if (node* n = unit_->find (t)) + { + ct_node = &dynamic_cast (*n); + } + else + { + path f (DECL_SOURCE_FILE (t)); + size_t l (DECL_SOURCE_LINE (t)); + size_t c (DECL_SOURCE_COLUMN (t)); + + ct_node = &unit_->new_node (f, l, c); + unit_->insert (t, *ct_node); + } + + tree c (TREE_TYPE (DECL_TEMPLATE_RESULT (t))); + + if (stub || !COMPLETE_TYPE_P (c)) + return *ct_node; + + // Collect member declarations so that we can traverse them in + // the source code order. For now we are only interested in + // nested class template declarations. + // + decl_set decls; + + for (tree d (TYPE_FIELDS (c)); d != NULL_TREE ; d = TREE_CHAIN (d)) + { + switch (TREE_CODE (d)) + { + case TEMPLATE_DECL: + { + if (DECL_CLASS_TEMPLATE_P (d)) + decls.insert (d); + break; + } + } + } + + scope* prev_scope (scope_); + scope_ = ct_node; + + for (decl_set::const_iterator i (decls.begin ()), e (decls.end ()); + i != e; ++i) + { + tree d (*i); + + switch (TREE_CODE (d)) + { + case TEMPLATE_DECL: + { + emit_template_decl (d); + break; + } + } + } + + scope_ = prev_scope; + return *ct_node; + } + + union_template& + emit_union_template (tree t, bool stub = false) + { + // See if there is a stub already for this template. + // + union_template* ut_node (0); + + if (node* n = unit_->find (t)) + { + ut_node = &dynamic_cast (*n); + } + else + { + path f (DECL_SOURCE_FILE (t)); + size_t l (DECL_SOURCE_LINE (t)); + size_t c (DECL_SOURCE_COLUMN (t)); + + ut_node = &unit_->new_node (f, l, c); + unit_->insert (t, *ut_node); + } + + tree u (TREE_TYPE (DECL_TEMPLATE_RESULT (t))); + + if (stub || !COMPLETE_TYPE_P (u)) + return *ut_node; + + // Collect member declarations so that we can traverse them in + // the source code order. For now we are only interested in + // nested class template declarations. + // + decl_set decls; + + for (tree d (TYPE_FIELDS (u)); d != NULL_TREE ; d = TREE_CHAIN (d)) + { + switch (TREE_CODE (d)) + { + case TEMPLATE_DECL: + { + if (DECL_CLASS_TEMPLATE_P (d)) + decls.insert (d); + break; + } + } + } + + scope* prev_scope (scope_); + scope_ = ut_node; + + for (decl_set::const_iterator i (decls.begin ()), e (decls.end ()); + i != e; ++i) + { + tree d (*i); + + switch (TREE_CODE (d)) + { + case TEMPLATE_DECL: + { + emit_template_decl (d); + break; + } + } + } + + scope_ = prev_scope; + return *ut_node; + } + + template + T& emit_class (tree c, path const& file, size_t line, @@ -398,20 +605,20 @@ private: // See if there is a stub already for this type. // - class_* class_node (0); + T* c_node (0); if (node* n = unit_->find (c)) { - class_node = &dynamic_cast (*n); + c_node = &dynamic_cast (*n); } else { - class_node = &unit_->new_node (file, line, clmn); - unit_->insert (c, *class_node); + c_node = &unit_->new_node (file, line, clmn); + unit_->insert (c, *c_node); } if (stub || !COMPLETE_TYPE_P (c)) - return *class_node; + return *c_node; // Traverse base information. // @@ -443,24 +650,39 @@ private: } bool virt (BINFO_VIRTUAL_P (bi)); - tree base (BINFO_TYPE (bi)); + tree base (TYPE_MAIN_VARIANT (BINFO_TYPE (bi))); + tree base_decl (TYPE_NAME (base)); // Typedef decl for this base. - warning (0, G_ ("\t%s%s base %s"), + // Find the corresponding graph node. If we cannot find one then + // the base is a template instantiation since an ordinary class + // has to be defined (complete) in order to be a base. + // + class_* b_node (0); + string name; + + if (node* n = unit_->find (base)) + { + b_node = &dynamic_cast (*n); + name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (base))); + } + else + { + b_node = &dynamic_cast (emit_type (base, file, line, clmn)); + name = emit_type_name (base); + } + + unit_->new_edge (*c_node, *b_node, a, virt); + + warning (0, G_ ("\t%s%s base %s (%p)"), a.string (), (virt ? " virtual" : ""), - IDENTIFIER_POINTER (DECL_NAME (base_decl))); - - // Find the corresponding graph node. - // - node* base_node (unit_->find (base)); - assert (base_node != 0); - unit_->new_edge ( - *class_node, dynamic_cast (*base_node), a, virt); + name.c_str (), + static_cast (b_node)); } - // Collect members so that we can traverse then in the source - // code order. + // Collect member declarations so that we can traverse them in + // the source code order. // decl_set decls; @@ -474,6 +696,12 @@ private: decls.insert (d); break; } + case TEMPLATE_DECL: + { + if (DECL_CLASS_TEMPLATE_P (d)) + decls.insert (d); + break; + } case FIELD_DECL: { if (!DECL_ARTIFICIAL (d)) @@ -504,6 +732,9 @@ private: } } + scope* prev_scope (scope_); + scope_ = c_node; + for (decl_set::const_iterator i (decls.begin ()), e (decls.end ()); i != e; ++i) { @@ -516,6 +747,11 @@ private: emit_type_decl (d); break; } + case TEMPLATE_DECL: + { + emit_template_decl (d); + break; + } case FIELD_DECL: { tree t (TREE_TYPE (d)); @@ -534,7 +770,7 @@ private: unit_->new_node (file, line, clmn)); unit_->new_edge (member_node, type_node); - unit_->new_edge (*class_node, member_node, name, a); + unit_->new_edge (*c_node, member_node, name, a); warning (0, G_ ("\t%s data member %s (%p) %s in %s:%i"), a.string (), @@ -549,7 +785,190 @@ private: } } - return *class_node; + scope_ = prev_scope; + return *c_node; + } + + template + T& + emit_union (tree u, + path const& file, + size_t line, + size_t clmn, + bool stub = false) + { + u = TYPE_MAIN_VARIANT (u); + + // See if there is a stub already for this type. + // + T* u_node (0); + + if (node* n = unit_->find (u)) + { + u_node = &dynamic_cast (*n); + } + else + { + u_node = &unit_->new_node (file, line, clmn); + unit_->insert (u, *u_node); + } + + if (stub || !COMPLETE_TYPE_P (u)) + return *u_node; + + // Collect member declarations so that we can traverse them in + // the source code order. + // + decl_set decls; + + for (tree d (TYPE_FIELDS (u)); d != NULL_TREE ; d = TREE_CHAIN (d)) + { + switch (TREE_CODE (d)) + { + case TYPE_DECL: + { + if (!DECL_SELF_REFERENCE_P (d)) + decls.insert (d); + break; + } + case TEMPLATE_DECL: + { + if (DECL_CLASS_TEMPLATE_P (d)) + decls.insert (d); + break; + } + case FIELD_DECL: + { + if (!DECL_ARTIFICIAL (d)) + decls.insert (d); + break; + } + default: + { + /* + tree name = DECL_NAME (d); + + if (name != NULL_TREE) + { + warning (0, G_ ("\tsome declaration %s in %s:%i"), + IDENTIFIER_POINTER (name), + DECL_SOURCE_FILE (d), + DECL_SOURCE_LINE (d)); + } + else + { + warning (0, G_ ("\tsome unnamed declaration in %s:%i"), + DECL_SOURCE_FILE (d), + DECL_SOURCE_LINE (d)); + } + */ + break; + } + } + } + + scope* prev_scope (scope_); + scope_ = u_node; + + for (decl_set::const_iterator i (decls.begin ()), e (decls.end ()); + i != e; ++i) + { + tree d (*i); + + switch (TREE_CODE (d)) + { + case TYPE_DECL: + { + emit_type_decl (d); + break; + } + case TEMPLATE_DECL: + { + emit_template_decl (d); + break; + } + case FIELD_DECL: + { + tree t (TREE_TYPE (d)); + char const* name (IDENTIFIER_POINTER (DECL_NAME (d))); + + path file (DECL_SOURCE_FILE (d)); + size_t line (DECL_SOURCE_LINE (d)); + size_t clmn (DECL_SOURCE_COLUMN (d)); + + string type_name (emit_type_name (t)); + + access a (decl_access (d)); + + type& type_node (emit_type (t, file, line, clmn)); + data_member& member_node ( + unit_->new_node (file, line, clmn)); + + unit_->new_edge (member_node, type_node); + unit_->new_edge (*u_node, member_node, name, a); + + warning (0, G_ ("\t%s union member %s (%p) %s in %s:%i"), + a.string (), + type_name.c_str (), + &type_node, + name, + file.string ().c_str (), + line); + + break; + } + } + } + + scope_ = prev_scope; + return *u_node; + } + + enum_& + emit_enum (tree e, + path const& file, + size_t line, + size_t clmn, + bool stub = false) + { + e = TYPE_MAIN_VARIANT (e); + + // See if there is a stub already for this type. + // + enum_* e_node (0); + + if (node* n = unit_->find (e)) + { + e_node = &dynamic_cast (*n); + } + else + { + e_node = &unit_->new_node (file, line, clmn); + unit_->insert (e, *e_node); + } + + if (stub || !COMPLETE_TYPE_P (e)) + return *e_node; + + // Traverse enumerators. + // + for (tree er (TYPE_VALUES (e)); er != NULL_TREE ; er = TREE_CHAIN (er)) + { + char const* name (IDENTIFIER_POINTER (TREE_PURPOSE (er))); + + // There doesn't seem to be a way to get the proper position for + // each enumerator. + // + enumerator& er_node = unit_->new_node (file, line, clmn); + unit_->new_edge (*e_node, er_node); + + warning (0, G_ ("\tenumerator %s in %s:%d"), + name, + file.string ().c_str (), + line); + } + + return *e_node; } // Create new or find existing semantic graph type. @@ -599,7 +1018,6 @@ private: return q; } - type& create_type (tree t, path const& file, @@ -607,13 +1025,15 @@ private: size_t clmn) { type* r (0); + int tc (TREE_CODE (t)); - switch (TREE_CODE (t)) + switch (tc) { // // User-defined types. // case RECORD_TYPE: + case UNION_TYPE: { tree ti (TYPE_TEMPLATE_INFO (t)); @@ -634,27 +1054,35 @@ private: t = TYPE_MAIN_VARIANT (t); tree d (TYPE_NAME (t)); - warning (0, G_ ("start anon/stub class declaration in %s:%d"), + warning (0, G_ ("start anon/stub %s declaration in %s:%d"), + tree_code_name[tc], file.string ().c_str (), line); if (d == NULL_TREE || ANON_AGGRNAME_P (DECL_NAME (d))) { - r = &emit_class (t, file, line, clmn); + if (tc == RECORD_TYPE) + r = &emit_class (t, file, line, clmn); + else + r = &emit_union (t, file, line, clmn); } else { // Use the "defining" declaration's file, line, and column // information to create the stub. // - r = &emit_class (t, - path (DECL_SOURCE_FILE (d)), - DECL_SOURCE_LINE (d), - DECL_SOURCE_COLUMN (d), - true); + path f (DECL_SOURCE_FILE (d)); + size_t l (DECL_SOURCE_LINE (d)); + size_t c (DECL_SOURCE_COLUMN (d)); + + if (tc == RECORD_TYPE) + r = &emit_class (t, f, l, c, true); + else + r = &emit_union (t, f, l, c, true); } - warning (0, G_ ("end anon/stub class declaration (%p) in %s:%d"), + warning (0, G_ ("end anon/stub %s declaration (%p) in %s:%d"), + tree_code_name[tc], r, file.string ().c_str (), line); @@ -663,50 +1091,105 @@ private: { // Template instantiation. // - /* + t = TYPE_MAIN_VARIANT (t); tree decl (TI_TEMPLATE (ti)); // DECL_TEMPLATE - string id (IDENTIFIER_POINTER (DECL_NAME (decl))); - id += '<'; + // Get to the most general template declaration. + // + while (DECL_TEMPLATE_INFO (decl)) + decl = DECL_TI_TEMPLATE (decl); - tree args (INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti))); + type_template* t_node (0); - int n (TREE_VEC_LENGTH (args)); - - for (size_t i (0), n (TREE_VEC_LENGTH (args)); i < n ; ++i) + // Find the template node or create a stub if none exist. + // + if (node* n = unit_->find (decl)) + t_node = &dynamic_cast (*n); + else { - tree a (TREE_VEC_ELT (args, i)); - - if (i != 0) - id += ", "; + warning (0, G_ ("start stub %s template for (%p) in %s:%d"), + tree_code_name[tc], + decl, + file.string ().c_str (), + line); + + if (tc == RECORD_TYPE) + t_node = &emit_class_template (decl, true); + else + t_node = &emit_union_template (decl, true); - // Assume type-only arguments. - // - id += emit_type (a); + warning (0, G_ ("end stub %s template (%p) in %s:%d"), + tree_code_name[tc], + t_node, + file.string ().c_str (), + line); } - id += '>'; + warning (0, G_ ("start %s instantiation (%p) for template (%p) in %s:%d"), + tree_code_name[tc], + t, + t_node, + file.string ().c_str (), + line); - r = id + r; - */ - } + type_instantiation* i_node (0); - break; - } + if (tc == RECORD_TYPE) + i_node = &emit_class (t, file, line, clmn); + else + i_node = &emit_union (t, file, line, clmn); - /* + warning (0, G_ ("end %s instantiation (%p) in %s:%d"), + tree_code_name[tc], + static_cast (i_node), + file.string ().c_str (), + line); + + unit_->new_edge (*i_node, *t_node); + r = i_node; + } - case UNION_TYPE: - { break; } case ENUMERAL_TYPE: { + // The same logic as in the "ordinary class" case above + // applies here. + // + + t = TYPE_MAIN_VARIANT (t); + tree d (TYPE_NAME (t)); + + warning (0, G_ ("start anon/stub %s declaration in %s:%d"), + tree_code_name[tc], + file.string ().c_str (), + line); + + if (d == NULL_TREE || ANON_AGGRNAME_P (DECL_NAME (d))) + { + r = &emit_enum (t, file, line, clmn); + } + else + { + // Use the "defining" declaration's file, line, and column + // information to create the stub. + // + path f (DECL_SOURCE_FILE (d)); + size_t l (DECL_SOURCE_LINE (d)); + size_t c (DECL_SOURCE_COLUMN (d)); + + r = &emit_enum (t, f, l, c, true); + } + + warning (0, G_ ("end anon/stub %s declaration (%p) in %s:%d"), + tree_code_name[tc], + r, + file.string ().c_str (), + line); + break; } - */ - // // Derived types. // @@ -772,15 +1255,28 @@ private: unit_->insert (TYPE_MAIN_VARIANT (t), p); r = &p; } + else + { + r = &unit_->new_node ( + file, line, clmn, "pointer_to_member_type"); + warning (0, G_ ("unsupported pointer_to_member_type (%p) in %s:%d"), + r, + file.string ().c_str (), + line); + } break; } default: { - error (G_ ("%s:%d: unexpected type %s"), - file.string ().c_str (), - line, - tree_code_name[TREE_CODE (t)]); + r = &unit_->new_node ( + file, line, clmn, tree_code_name[tc]); + + warning (0, G_ ("unsupported %s (%p) in %s:%d"), + tree_code_name[tc], + r, + file.string ().c_str (), + line); break; } } @@ -824,13 +1320,16 @@ private: if (CP_TYPE_RESTRICT_P (type)) r += " __restrict"; - switch (TREE_CODE (type)) + int tc (TREE_CODE (type)); + + switch (tc) { // // User-defined types. // case RECORD_TYPE: + case UNION_TYPE: { tree ti (TYPE_TEMPLATE_INFO (type)); @@ -876,16 +1375,13 @@ private: break; } - /* - case UNION_TYPE: - { - break; - } case ENUMERAL_TYPE: { + type = TYPE_MAIN_VARIANT (type); + tree decl (TYPE_NAME (type)); + r = IDENTIFIER_POINTER (DECL_NAME (decl)) + r; break; } - */ // // Derived types. @@ -946,6 +1442,8 @@ private: tree t (TREE_TYPE (type)); r = emit_type_name (t) + "*" + r; } + else + r = ""; break; } @@ -966,7 +1464,7 @@ private: } default: { - r = ""; + r = "<" + string (tree_code_name[tc]) + ">"; break; } } -- cgit v1.1