OSDN Git Service

2011-05-25 Paolo Carlini <paolo.carlini@oracle.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / testsuite / util / testsuite_abi.cc
index e26f009..f1f5ad6 100644 (file)
@@ -1,10 +1,11 @@
 // -*- C++ -*-
 
-// Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Free Software Foundation, Inc.
 
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2, or (at
+// published by the Free Software Foundation; either version 3, or (at
 // your option) any later version.
 
 // This library is distributed in the hope that it will be useful, but
 // General Public License for more details.
 
 // You should have received a copy of the GNU General Public License
-// along with this library; see the file COPYING.  If not, write to
-// the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
-// MA 02110-1301, USA.
-
-// As a special exception, you may use this file as part of a free
-// software library without restriction.  Specifically, if other files
-// instantiate templates or use macros or inline functions from this
-// file, or you compile this file and link it with other files to
-// produce an executable, this file does not by itself cause the
-// resulting executable to be covered by the GNU General Public
-// License.  This exception does not however invalidate any other
-// reasons why the executable file might be covered by the GNU General
-// Public License.
+// along with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
 
 // Benjamin Kosnik  <bkoz@redhat.com>
 
 #include "testsuite_abi.h"
+#include <cstdlib>
 #include <sstream>
 #include <fstream>
 #include <iostream>
+#include <vector>
+#include <algorithm>
 
 using namespace std;
 
@@ -49,19 +43,21 @@ symbol::init(string& data)
     type = symbol::function;
   else if (data.find("OBJECT") == 0)
     type = symbol::object;
+  else if (data.find("TLS") == 0)
+    type = symbol::tls;
 
   n = data.find_first_of(delim);
   if (n != npos)
     data.erase(data.begin(), data.begin() + n + 1);
 
-  // Iff object, get size info.
-  if (type == symbol::object)
+  // Iff object or TLS, get size info.
+  if (type == symbol::object || type == symbol::tls)
     {
       n = data.find_first_of(delim);
       if (n != npos)
        {
-         string size(data.begin(), data.begin() + n);
-         istringstream iss(size);
+         string objectsize(data.begin(), data.begin() + n);
+         istringstream iss(objectsize);
          int x;
          iss >> x;
          if (!iss.fail())
@@ -136,6 +132,9 @@ symbol::print() const
     case object:
       type_string = "object";
       break;
+    case tls:
+      type_string = "tls";
+      break;
     case uncategorized:
       type_string = "uncategorized";
       break;
@@ -144,7 +143,7 @@ symbol::print() const
     }
   cout << "type: " << type_string << endl;
   
-  if (type == object)
+  if (type == object || type == tls)
     cout << "type size: " << size << endl;
 
   string status_string;
@@ -189,10 +188,22 @@ check_version(symbol& test, bool added)
       known_versions.push_back("GLIBCXX_3.4.8");
       known_versions.push_back("GLIBCXX_3.4.9");
       known_versions.push_back("GLIBCXX_3.4.10");
+      known_versions.push_back("GLIBCXX_3.4.11");
+      known_versions.push_back("GLIBCXX_3.4.12");
+      known_versions.push_back("GLIBCXX_3.4.13");
+      known_versions.push_back("GLIBCXX_3.4.14");
+      known_versions.push_back("GLIBCXX_3.4.15");
+      known_versions.push_back("GLIBCXX_3.4.16");
+      known_versions.push_back("GLIBCXX_3.4.17");
       known_versions.push_back("GLIBCXX_LDBL_3.4");
       known_versions.push_back("GLIBCXX_LDBL_3.4.7");
+      known_versions.push_back("GLIBCXX_LDBL_3.4.10");
       known_versions.push_back("CXXABI_1.3");
       known_versions.push_back("CXXABI_1.3.1");
+      known_versions.push_back("CXXABI_1.3.2");
+      known_versions.push_back("CXXABI_1.3.3");
+      known_versions.push_back("CXXABI_1.3.4");
+      known_versions.push_back("CXXABI_1.3.5");
       known_versions.push_back("CXXABI_LDBL_1.3");
     }
   compat_list::iterator begin = known_versions.begin();
@@ -208,10 +219,23 @@ check_version(symbol& test, bool added)
       else
        test.version_status = symbol::incompatible;
       
-      // Check that added symbols aren't added in the base version.
-      if (added && test.version_name == known_versions[0])
+      // Check that added symbols aren't added in the base versions.
+      if (added
+         && (test.version_name == known_versions[0]
+             || test.version_name == "CXXABI_1.3"
+             || test.version_name == "GLIBCXX_LDBL_3.4"
+             || test.version_name == "CXXABI_LDBL_1.3"))
        test.version_status = symbol::incompatible;
-      
+
+      // Check that long double compatibility symbols demangled as
+      // __float128 are put into some _LDBL_ version name.
+      if (added && test.demangled_name.find("__float128") != std::string::npos)
+       {
+         // Has to be in _LDBL_ version name.
+         if (test.version_name.find("_LDBL_") == std::string::npos)
+           test.version_status = symbol::incompatible;
+       }
+
       // Check for weak label.
       if (it1 == end && it2 == end)
        test.version_status = symbol::incompatible;
@@ -288,28 +312,22 @@ check_compatible(symbol& lhs, symbol& rhs, bool verbose)
 }
 
 
-bool
-has_symbol(const string& mangled, const symbols& s) throw()
-{
-  const symbol_names& names = s.first;
-  symbol_names::const_iterator i = find(names.begin(), names.end(), mangled);
-  return i != names.end();
-}
+inline bool
+has_symbol(const string& name, const symbols& s) throw()
+{ return s.find(name) != s.end(); }
 
-symbol&
-get_symbol(const string& mangled, const symbols& s)
+const symbol&
+get_symbol(const string& name, const symbols& s)
 {
-  const symbol_names& names = s.first;
-  symbol_names::const_iterator i = find(names.begin(), names.end(), mangled);
-  if (i != names.end())
+  symbols::const_iterator i = s.find(name);
+  if (i != s.end())
     {
-      symbol_objects objects = s.second;
-      return objects[mangled];
+      return i->second;
     }
   else
     {
       ostringstream os;
-      os << "get_symbol failed for symbol " << mangled;
+      os << "get_symbol failed for symbol " << name;
       __throw_logic_error(os.str().c_str());
     }
 }
@@ -320,7 +338,7 @@ examine_symbol(const char* name, const char* file)
   try
     {
       symbols s = create_symbols(file);
-      symbol& sym = get_symbol(name, s);
+      const symbol& sym = get_symbol(name, s);
       sym.print();
     }
   catch(...)
@@ -334,78 +352,95 @@ compare_symbols(const char* baseline_file, const char* test_file,
   // Input both lists of symbols into container.
   symbols baseline = create_symbols(baseline_file);
   symbols test = create_symbols(test_file);
-  symbol_names& baseline_names = baseline.first;
-  symbol_objects& baseline_objects = baseline.second;
-  symbol_names& test_names = test.first;
-  symbol_objects& test_objects = test.second;
 
   //  Sanity check results.
-  const symbol_names::size_type baseline_size = baseline_names.size();
-  const symbol_names::size_type test_size = test_names.size();
-  if (!baseline_size || !test_size)
+  if (!baseline.size() || !test.size())
     {
       cerr << "Problems parsing the list of exported symbols." << endl;
       exit(2);
     }
 
+  // Check to see if any long double compatibility symbols are produced.
+  bool ld_version_found(false);
+  symbols::iterator li(test.begin());
+  while (!ld_version_found && li != test.end())
+    {
+      if (li->second.version_name.find("_LDBL_") != std::string::npos)
+       ld_version_found = true;
+      ++li;
+    }
+
   // Sort out names.
-  // Assuming baseline_names, test_names are both unique w/ no duplicates.
+  // Assuming all baseline names and test names are both unique w/ no
+  // duplicates.
   //
-  // The names added to missing_names are baseline_names not found in
-  // test_names 
+  // The names added to missing_names are baseline names not found in
+  // test names 
   // -> symbols that have been deleted.
   //
-  // The names added to added_names are test_names not in
-  // baseline_names
+  // The names added to added_names are test names not in
+  // baseline names
   // -> symbols that have been added.
+  typedef std::vector<std::string> symbol_names;
   symbol_names shared_names;
   symbol_names missing_names;
-  symbol_names added_names = test_names;
-  for (size_t i = 0; i < baseline_size; ++i)
+  symbol_names added_names;
+  for (li = test.begin(); li != test.end(); ++li)
+    added_names.push_back(li->first);
+
+  for (symbols::iterator i = baseline.begin(); i != baseline.end(); ++i)
     {
-      string what(baseline_names[i]);
+      string name(i->first);
       symbol_names::iterator end = added_names.end();
-      symbol_names::iterator it = find(added_names.begin(), end, what);
+      symbol_names::iterator it = find(added_names.begin(), end, name);
       if (it != end)
        {
          // Found.
-         shared_names.push_back(what);
+         shared_names.push_back(name);
          added_names.erase(it);
        }
-      else
-       missing_names.push_back(what);
+       else
+       {
+         // Iff no test long double compatibility symbols at all and the symbol
+         // missing is a baseline long double compatibility symbol, skip.
+         string version_name(i->second.version_name);
+         bool base_ld(version_name.find("_LDBL_") != std::string::npos);
+         if (!base_ld || base_ld && ld_version_found)
+           missing_names.push_back(name);
+       }
     }
 
-  // Check missing names for compatibility.
+  // Fill out list of incompatible symbols.
   typedef pair<symbol, symbol> symbol_pair;
   vector<symbol_pair> incompatible;
-  const symbol_names::size_type missing_size = missing_names.size();
-  for (size_t j = 0; j < missing_size; ++j)
+
+  // Check missing names for compatibility.
+  for (size_t j = 0; j < missing_names.size(); ++j)
     {
-      symbol& base = baseline_objects[missing_names[j]];
-      base.status = symbol::subtracted;
-      incompatible.push_back(symbol_pair(base, base));
+      symbol& sbase = baseline[missing_names[j]];
+      sbase.status = symbol::subtracted;
+      incompatible.push_back(symbol_pair(sbase, sbase));
     }
 
   // Check shared names for compatibility.
   const symbol_names::size_type shared_size = shared_names.size();
   for (size_t k = 0; k < shared_size; ++k)
     {
-      symbol& base = baseline_objects[shared_names[k]];
-      symbol& test = test_objects[shared_names[k]];
-      test.status = symbol::existing;
-      if (!check_compatible(base, test))
-       incompatible.push_back(symbol_pair(base, test));
+      symbol& sbase = baseline[shared_names[k]];
+      symbol& stest = test[shared_names[k]];
+      stest.status = symbol::existing;
+      if (!check_compatible(sbase, stest))
+       incompatible.push_back(symbol_pair(sbase, stest));
     }
 
   // Check added names for compatibility.
   const symbol_names::size_type added_size = added_names.size();
   for (size_t l = 0; l < added_size; ++l)
     {
-      symbol& test = test_objects[added_names[l]];
-      test.status = symbol::added;
-      if (!check_version(test, true))
-       incompatible.push_back(symbol_pair(test, test));
+      symbol& stest = test[added_names[l]];
+      stest.status = symbol::added;
+      if (!check_version(stest, true))
+       incompatible.push_back(symbol_pair(stest, stest));
     }
 
   // Report results.
@@ -415,7 +450,7 @@ compare_symbols(const char* baseline_file, const char* test_file,
       for (size_t j = 0; j < added_names.size() ; ++j)
        {
          cout << j << endl;
-         test_objects[added_names[j]].print();
+         test[added_names[j]].print();
        }
     }
   
@@ -425,7 +460,7 @@ compare_symbols(const char* baseline_file, const char* test_file,
       for (size_t j = 0; j < missing_names.size() ; ++j)
        {
          cout << j << endl;
-         baseline_objects[missing_names[j]].print();
+         baseline[missing_names[j]].print();
        }
     }
   
@@ -438,12 +473,12 @@ compare_symbols(const char* baseline_file, const char* test_file,
          cout << j << endl;
 
          // Second, report name.
-         symbol& base = incompatible[j].first;
-         symbol& test = incompatible[j].second;
-         test.print();
+         symbol& sbase = incompatible[j].first;
+         symbol& stest = incompatible[j].second;
+         stest.print();
          
          // Second, report reason or reasons incompatible.
-         check_compatible(base, test, true);
+         check_compatible(sbase, stest, true);
        }
     }
   
@@ -466,18 +501,16 @@ create_symbols(const char* file)
   ifstream ifs(file);
   if (ifs.is_open())
     {
-      // Organize file data into container of symbol objects, and a
-      // container of mangled names without versioning information.
-      symbol_names& names = s.first;
-      symbol_objects& objects = s.second;
+      // Organize file data into an associated container (symbols) of symbol
+      // objects mapped to mangled names without versioning
+      // information.
       const string empty;
       string line = empty;
       while (getline(ifs, line).good())
        {
          symbol tmp;
          tmp.init(line);
-         objects[tmp.name] = tmp;
-         names.push_back(tmp.name);
+         s[tmp.name] = tmp;
          line = empty;
        }
     }