]> sourceware.org Git - libabigail.git/commitdiff
Fix type lookup algorithm
authorDodji Seketeli <dodji@redhat.com>
Fri, 28 Aug 2015 14:45:18 +0000 (16:45 +0200)
committerDodji Seketeli <dodji@redhat.com>
Sat, 29 Aug 2015 14:23:15 +0000 (16:23 +0200)
Until now, the type lookup algorithm was broken for c++.  For two
reasons:

  1/ The algorithm to break a fully qualified type name into name
    components is buggy.  When given the type name:
      foo<ns1::t1, ns1::t2>::t3
    the components making up the name are: "foo<ns1", "t1, ns1", "t2>"
    and "t3.  That is wrong.  The components should be:
    "foo<ns1::t1, ns2::t2>" and "t3".

  2/ When a type is found, if it's a declaration, it's skipped.  This
  is wrong because if the declaration is accompanied with a
  definition, it should be returned.

This patch addresses the two issues above.  It allows more
declaration-only classes to be resolved and so reduces the number of
spurious hashing differences between two instances of the same type
which should otherwise have the same hash.

There is no regression test update with this patch because we really
need the full series this patch is part of, to fix the type hashing
correctness issues we have.  So the regression test updates are coming
at the end of the series.

* src/abg-ir.cc (find_next_delim_in_cplus_type): Define new static
function.
(fqn_to_components): Use the new function above to break up a
fully qualified name into components, rather than the too simple
string::find_first_of() we were using previously.
(lookup_node_in_scope): If the found type (class) is a
declaration-only and if it has a definition, then return it.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
src/abg-ir.cc

index be27b3ce845caefeb8dce908e66d442106b9db3f..6f24fbf52c79fd542077d2fa6df63199a58ad6b5 100644 (file)
@@ -4672,6 +4672,60 @@ enum lookup_entity_kind
   LOOKUP_ENTITY_VAR,
 };
 
+/// Find the first relevant delimiter (the "::" string) in a fully
+/// qualified C++ type name, starting from a given position.  The
+/// delimiter returned separates a type name from the name of its
+/// context.
+///
+/// This is supposed to work correctly on names in cases like this:
+///
+///    foo<ns1::name1, ns2::name2>
+///
+/// In that case when called with with parameter @p begin set to 0, no
+/// delimiter is returned, because the type name in this case is:
+/// 'foo<ns1::name1, ns2::name2>'.
+///
+/// But in this case:
+///
+///   foo<p1, bar::name>::some_type
+///
+/// The "::" returned is the one right before 'some_type'.
+///
+/// @param fqn the fully qualified name of the type to consider.
+///
+/// @param begin the position from which to look for the delimiter.
+///
+/// @param delim_pos out parameter. Is set to the position of the
+/// delimiter iff the function returned true.
+///
+/// @return true iff the function found and returned the delimiter.
+static bool
+find_next_delim_in_cplus_type(const string&    fqn,
+                             size_t            begin,
+                             size_t&           delim_pos)
+{
+  int angle_count = 0;
+  bool found = false;
+  size_t i = begin;
+  for (; i < fqn.size(); ++i)
+    {
+      if (fqn[i] == '<')
+       ++angle_count;
+      else if (fqn[i] == '>')
+       --angle_count;
+      else if (i + 1 < fqn.size()
+              && !angle_count
+              && fqn[i] == ':'
+              && fqn[i+1] == ':')
+       {
+         delim_pos = i;
+         found = true;
+         break;
+       }
+    }
+  return found;
+}
+
 /// Decompose a fully qualified name into the list of its components.
 ///
 /// @param fqn the fully qualified name to decompose.
@@ -4681,11 +4735,10 @@ void
 fqn_to_components(const string& fqn,
                  list<string>& comps)
 {
-  string::size_type comp_begin = 0, comp_end = 0, fqn_size = fqn.size();
+  string::size_type fqn_size = fqn.size(), comp_begin = 0, comp_end = fqn_size;
   do
     {
-      comp_end = fqn.find_first_of("::", comp_begin);
-      if (comp_end == fqn.npos)
+      if (!find_next_delim_in_cplus_type(fqn, comp_begin, comp_end))
        comp_end = fqn_size;
 
       string comp = fqn.substr(comp_begin, comp_end - comp_begin);
@@ -5100,7 +5153,8 @@ lookup_node_in_scope(const list<string>& fqn,
                {
                  if (class_decl_sptr cl =
                      dynamic_pointer_cast<class_decl>(node))
-                   if (cl->get_is_declaration_only())
+                   if (cl->get_is_declaration_only()
+                       && !cl->get_definition_of_declaration())
                      continue;
                  resulting_decl = convert_node_to_decl(node);
                  break;
This page took 0.046609 seconds and 5 git commands to generate.