PR 10861
authorIan Lance Taylor <ian@airs.com>
Wed, 30 Dec 2009 22:35:49 +0000 (22:35 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 30 Dec 2009 22:35:49 +0000 (22:35 +0000)
* script.h (class Version_script_info): Define Language enum.
Update declarations.  Define Glob, Exact, and Lookup types.  Add
new fields globals_, locals_, and is_finalized_.
* script.cc: Various formatting fixes.
(class Parser_closure): Change language_stack_ from a vector of
std::string to one of Version_script_info::Language.  Adjust all
uses accordingly.
(class Lazy_demangler): Remove.
(struct Version_expression): Change language from std::string to
Version_script_info::Language.
(Version_script_info::Version_script_info): New function.
(Version_script_info::~Version_script_info): Don't call clear.
(Version_script_info::finalize): New function.
(Version_script_info::build_lookup_tables): New function.
(Version_script_info::build_expression_list_lookup): New
function.
(Version_script_info::get_symbol_version_helper): Rewrite to use
lookup tables.
(Version_script_info::print_expression_list): Adjust to use
Version_script_info::Language.
(script_push_lex_into_version_mode): Check that the version script
has not been finalized.
(version_script_push_lang): Change language string to
Version_script_info::Language.
* options.cc (Command_line::version_script): New function.
* options.h (class General_options): Add finalize_dynamic_list
function.  Change version_script from declaration to definition.
* testsuite/ver_test_4.script: Remove duplicate def of t2_2.
* testsuite/version_script.map: Remove duplicate def of foo.
* testsuite/Makefile.am (ver_matching_def.so): Depend upon
version_script.map.
* testsuite/Makefile.in: Rebuild.

gold/ChangeLog
gold/options.cc
gold/options.h
gold/script.cc
gold/script.h
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/ver_test_4.script
gold/testsuite/version_script.map

index 3dd3280dab770d02026f43640b27bacf0703bd9e..05aac4b1b652e8e7235360588f90bd857aba8e8a 100644 (file)
@@ -1,3 +1,39 @@
+2009-12-30  Ian Lance Taylor  <iant@google.com>
+
+       PR 10861
+       * script.h (class Version_script_info): Define Language enum.
+       Update declarations.  Define Glob, Exact, and Lookup types.  Add
+       new fields globals_, locals_, and is_finalized_.
+       * script.cc: Various formatting fixes.
+       (class Parser_closure): Change language_stack_ from a vector of
+       std::string to one of Version_script_info::Language.  Adjust all
+       uses accordingly.
+       (class Lazy_demangler): Remove.
+       (struct Version_expression): Change language from std::string to
+       Version_script_info::Language.
+       (Version_script_info::Version_script_info): New function.
+       (Version_script_info::~Version_script_info): Don't call clear.
+       (Version_script_info::finalize): New function.
+       (Version_script_info::build_lookup_tables): New function.
+       (Version_script_info::build_expression_list_lookup): New
+       function.
+       (Version_script_info::get_symbol_version_helper): Rewrite to use
+       lookup tables.
+       (Version_script_info::print_expression_list): Adjust to use
+       Version_script_info::Language.
+       (script_push_lex_into_version_mode): Check that the version script
+       has not been finalized.
+       (version_script_push_lang): Change language string to
+       Version_script_info::Language.
+       * options.cc (Command_line::version_script): New function.
+       * options.h (class General_options): Add finalize_dynamic_list
+       function.  Change version_script from declaration to definition.
+       * testsuite/ver_test_4.script: Remove duplicate def of t2_2.
+       * testsuite/version_script.map: Remove duplicate def of foo.
+       * testsuite/Makefile.am (ver_matching_def.so): Depend upon
+       version_script.map.
+       * testsuite/Makefile.in: Rebuild.
+
 2009-12-30  Ian Lance Taylor  <iant@google.com>
 
        PR 10843
index 73da963b1a1b725ac095f0a739622c6671d07aac..671f3d5db084af848b88139dce628bf3113a194a 100644 (file)
@@ -1209,4 +1209,15 @@ Command_line::process(int argc, const char** argv)
   this->options_.finalize();
 }
 
+// Finalize the version script options and return them.
+
+const Version_script_info&
+Command_line::version_script()
+{
+  this->options_.finalize_dynamic_list();
+  Version_script_info* vsi = this->script_options_.version_script_info();
+  vsi->finalize();
+  return *vsi;
+}
+
 } // End namespace gold.
index be7b018ab1443d9cdf19a5f89453d98bc3f62965..d8f5fb97505d881d45be45836106fbed8c11e29e 100644 (file)
@@ -1118,6 +1118,11 @@ class General_options
   in_dynamic_list(const char* symbol) const
   { return this->dynamic_list_.version_script_info()->symbol_is_local(symbol); }
 
+  // Finalize the dynamic list.
+  void
+  finalize_dynamic_list()
+  { this->dynamic_list_.version_script_info()->finalize(); }
+
   // The disposition given by the --incremental-changed,
   // --incremental-unchanged or --incremental-unknown option.  The
   // value may change as we proceed parsing the command line flags.
@@ -1552,10 +1557,9 @@ class Command_line
   script_options()
   { return this->script_options_; }
 
-  // Get the version-script options: a convenience routine.
+  // Finalize the version-script options and return them.
   const Version_script_info&
-  version_script() const
-  { return *this->script_options_.version_script_info(); }
+  version_script();
 
   // Get the input files.
   Input_arguments&
index fb35fb8b4ce153ed7a07f7e3dbc1b8efa3d7a750..fb1b2e111fd346ffc84ffd44649373ec156de66d 100644 (file)
@@ -1183,8 +1183,8 @@ class Parser_closure
       lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL)
   {
     // We start out processing C symbols in the default lex mode.
-    language_stack_.push_back("");
-    lex_mode_stack_.push_back(lex->mode());
+    this->language_stack_.push_back(Version_script_info::LANGUAGE_C);
+    this->lex_mode_stack_.push_back(lex->mode());
   }
 
   // Return the file name.
@@ -1314,16 +1314,18 @@ class Parser_closure
 
   // Return the current language being processed in a version script
   // (eg, "C++").  The empty string represents unmangled C names.
-  const std::string&
+  Version_script_info::Language
   get_current_language() const
   { return this->language_stack_.back(); }
 
   // Push a language onto the stack when entering an extern block.
-  void push_language(const std::string& lang)
+  void
+  push_language(Version_script_info::Language lang)
   { this->language_stack_.push_back(lang); }
 
   // Pop a language off of the stack when exiting an extern block.
-  void pop_language()
+  void
+  pop_language()
   {
     gold_assert(!this->language_stack_.empty());
     this->language_stack_.pop_back();
@@ -1362,7 +1364,7 @@ class Parser_closure
   std::vector<Lex::Mode> lex_mode_stack_;
   // A stack of which extern/language block we're inside. Can be C++,
   // java, or empty for C.
-  std::vector<std::string> language_stack_;
+  std::vector<Version_script_info::Language> language_stack_;
   // New input files found to add to the link.
   Input_arguments* inputs_;
 };
@@ -1776,90 +1778,49 @@ Keyword_to_parsecode::keyword_to_parsecode(const char* keyword,
   return ktt->parsecode;
 }
 
-// Helper class that calls cplus_demangle when needed and takes care of freeing
-// the result.
-
-class Lazy_demangler
-{
- public:
-  Lazy_demangler(const char* symbol, int options)
-    : symbol_(symbol), options_(options), demangled_(NULL), did_demangle_(false)
-  { }
-
-  ~Lazy_demangler()
-  { free(this->demangled_); }
-
-  // Return the demangled name. The actual demangling happens on the first call,
-  // and the result is later cached.
-
-  inline char*
-  get();
-
- private:
-  // The symbol to demangle.
-  const char *symbol_;
-  // Option flags to pass to cplus_demagle.
-  const int options_;
-  // The cached demangled value, or NULL if demangling didn't happen yet or
-  // failed.
-  char *demangled_;
-  // Whether we already called cplus_demangle
-  bool did_demangle_;
-};
-
-// Return the demangled name. The actual demangling happens on the first call,
-// and the result is later cached. Returns NULL if the symbol cannot be
-// demangled.
-
-inline char*
-Lazy_demangler::get()
-{
-  if (!this->did_demangle_)
-    {
-      this->demangled_ = cplus_demangle(this->symbol_, this->options_);
-      this->did_demangle_ = true;
-    }
-  return this->demangled_;
-}
-
 // The following structs are used within the VersionInfo class as well
 // as in the bison helper functions.  They store the information
 // parsed from the version script.
 
 // A single version expression.
 // For example, pattern="std::map*" and language="C++".
-// pattern and language should be from the stringpool
-struct Version_expression {
-  Version_expression(const std::string& pattern,
-                     const std::string& language,
-                     bool exact_match)
-      : pattern(pattern), language(language), exact_match(exact_match) {}
+// PATTERN should be from the stringpool.
+struct
+Version_expression
+{
+  Version_expression(const std::string& a_pattern,
+                    Version_script_info::Language a_language,
+                     bool a_exact_match)
+    : pattern(a_pattern), language(a_language), exact_match(a_exact_match)
+  { }
 
   std::string pattern;
-  std::string language;
+  Version_script_info::Language language;
   // If false, we use glob() to match pattern.  If true, we use strcmp().
   bool exact_match;
 };
 
 
 // A list of expressions.
-struct Version_expression_list {
+struct Version_expression_list
+{
   std::vector<struct Version_expression> expressions;
 };
 
-
 // A list of which versions upon which another version depends.
 // Strings should be from the Stringpool.
-struct Version_dependency_list {
+struct Version_dependency_list
+{
   std::vector<std::string> dependencies;
 };
 
-
 // The total definition of a version.  It includes the tag for the
 // version, its global and local expressions, and any dependencies.
-struct Version_tree {
+struct Version_tree
+{
   Version_tree()
-      : tag(), global(NULL), local(NULL), dependencies(NULL) {}
+      : tag(), global(NULL), local(NULL), dependencies(NULL)
+  { }
 
   std::string tag;
   const struct Version_expression_list* global;
@@ -1867,44 +1828,74 @@ struct Version_tree {
   const struct Version_dependency_list* dependencies;
 };
 
+// Class Version_script_info.
+
+Version_script_info::Version_script_info()
+  : dependency_lists_(), expression_lists_(), version_trees_(),
+    is_finalized_(false)
+{
+  for (int i = 0; i < LANGUAGE_COUNT; ++i)
+    {
+      this->globals_[i] = NULL;
+      this->locals_[i] = NULL;
+    }
+}
+
 Version_script_info::~Version_script_info()
 {
-  this->clear();
 }
 
+// Forget all the known version script information.
+
 void
 Version_script_info::clear()
 {
-  for (size_t k = 0; k < dependency_lists_.size(); ++k)
-    delete dependency_lists_[k];
+  for (size_t k = 0; k < this->dependency_lists_.size(); ++k)
+    delete this->dependency_lists_[k];
   this->dependency_lists_.clear();
-  for (size_t k = 0; k < version_trees_.size(); ++k)
-    delete version_trees_[k];
+  for (size_t k = 0; k < this->version_trees_.size(); ++k)
+    delete this->version_trees_[k];
   this->version_trees_.clear();
-  for (size_t k = 0; k < expression_lists_.size(); ++k)
-    delete expression_lists_[k];
+  for (size_t k = 0; k < this->expression_lists_.size(); ++k)
+    delete this->expression_lists_[k];
   this->expression_lists_.clear();
 }
 
+// Finalize the version script information.
+
+void
+Version_script_info::finalize()
+{
+  if (!this->is_finalized_)
+    {
+      this->build_lookup_tables();
+      this->is_finalized_ = true;
+    }
+}
+
+// Return all the versions.
+
 std::vector<std::string>
 Version_script_info::get_versions() const
 {
   std::vector<std::string> ret;
-  for (size_t j = 0; j < version_trees_.size(); ++j)
+  for (size_t j = 0; j < this->version_trees_.size(); ++j)
     if (!this->version_trees_[j]->tag.empty())
       ret.push_back(this->version_trees_[j]->tag);
   return ret;
 }
 
+// Return the dependencies of VERSION.
+
 std::vector<std::string>
 Version_script_info::get_dependencies(const char* version) const
 {
   std::vector<std::string> ret;
-  for (size_t j = 0; j < version_trees_.size(); ++j)
-    if (version_trees_[j]->tag == version)
+  for (size_t j = 0; j < this->version_trees_.size(); ++j)
+    if (this->version_trees_[j]->tag == version)
       {
         const struct Version_dependency_list* deps =
-          version_trees_[j]->dependencies;
+          this->version_trees_[j]->dependencies;
         if (deps != NULL)
           for (size_t k = 0; k < deps->dependencies.size(); ++k)
             ret.push_back(deps->dependencies[k]);
@@ -1913,6 +1904,58 @@ Version_script_info::get_dependencies(const char* version) const
   return ret;
 }
 
+// Build a set of fast lookup tables for a version script.
+
+void
+Version_script_info::build_lookup_tables()
+{
+  size_t size = this->version_trees_.size();
+  for (size_t j = 0; j < size; ++j)
+    {
+      const Version_tree* v = this->version_trees_[j];
+      this->build_expression_list_lookup(v->global, v, &this->globals_[0]);
+      this->build_expression_list_lookup(v->local, v, &this->locals_[0]);
+    }
+}
+
+// Build fast lookup information for EXPLIST and store it in LOOKUP.
+
+void
+Version_script_info::build_expression_list_lookup(
+    const Version_expression_list* explist,
+    const Version_tree* v,
+    Lookup** lookup)
+{
+  if (explist == NULL)
+    return;
+  size_t size = explist->expressions.size();
+  for (size_t j = 0; j < size; ++j)
+    {
+      const Version_expression& exp(explist->expressions[j]);
+      Lookup **pp = &lookup[exp.language];
+      if (*pp == NULL)
+       *pp = new Lookup();
+      Lookup* p = *pp;
+
+      if (!exp.exact_match && strpbrk(exp.pattern.c_str(), "?*[") != NULL)
+       p->globs.push_back(Glob(exp.pattern.c_str(), v));
+      else
+       {
+         std::pair<Exact::iterator, bool> ins =
+           p->exact.insert(std::make_pair(exp.pattern, v));
+         if (!ins.second)
+           {
+             const Version_tree* v1 = ins.first->second;
+             if (v1->tag != v->tag)
+               gold_error(_("'%s' appears in version script with both "
+                            "versions '%s' and '%s'"),
+                          exp.pattern.c_str(), v1->tag.c_str(),
+                          v->tag.c_str());
+           }
+       }
+    }
+}
+
 // Look up SYMBOL_NAME in the list of versions.  If CHECK_GLOBAL is
 // true look at the globally visible symbols, otherwise look at the
 // symbols listed as "local:".  Return true if the symbol is found,
@@ -1924,47 +1967,70 @@ Version_script_info::get_symbol_version_helper(const char* symbol_name,
                                                bool check_global,
                                               std::string* pversion) const
 {
-  Lazy_demangler cpp_demangled_name(symbol_name, DMGL_ANSI | DMGL_PARAMS);
-  Lazy_demangler java_demangled_name(symbol_name,
-                                     DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
-  for (size_t j = 0; j < version_trees_.size(); ++j)
+  gold_assert(this->is_finalized_);
+  const Lookup* const * pp = (check_global
+                             ? &this->globals_[0]
+                             : &this->locals_[0]);
+  for (int i = 0; i < LANGUAGE_COUNT; ++i)
     {
-      // Is it a global symbol for this version?
-      const Version_expression_list* explist =
-          check_global ? version_trees_[j]->global : version_trees_[j]->local;
-      if (explist != NULL)
-        for (size_t k = 0; k < explist->expressions.size(); ++k)
-          {
-            const char* name_to_match = symbol_name;
-            const struct Version_expression& exp = explist->expressions[k];
-            if (exp.language == "C++")
-              {
-                name_to_match = cpp_demangled_name.get();
-                // This isn't a C++ symbol.
-                if (name_to_match == NULL)
-                  continue;
-              }
-            else if (exp.language == "Java")
-              {
-                name_to_match = java_demangled_name.get();
-                // This isn't a Java symbol.
-                if (name_to_match == NULL)
-                  continue;
-              }
-            bool matched;
-            if (exp.exact_match)
-              matched = strcmp(exp.pattern.c_str(), name_to_match) == 0;
-            else
-              matched = fnmatch(exp.pattern.c_str(), name_to_match,
-                                FNM_NOESCAPE) == 0;
-            if (matched)
-             {
-               if (pversion != NULL)
-                 *pversion = this->version_trees_[j]->tag;
-               return true;
-             }
-          }
+      const Lookup* lookup = pp[i];
+      if (lookup == NULL)
+       continue;
+
+      const char* name_to_match;
+      char* allocated;
+      switch (i)
+       {
+       case LANGUAGE_C:
+         allocated = NULL;
+         name_to_match = symbol_name;
+         break;
+       case LANGUAGE_CXX:
+         allocated = cplus_demangle(symbol_name, DMGL_ANSI | DMGL_PARAMS);
+         if (allocated == NULL)
+           continue;
+         name_to_match = allocated;
+         break;
+       case LANGUAGE_JAVA:
+         allocated = cplus_demangle(symbol_name,
+                                    DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
+         if (allocated == NULL)
+           continue;
+         name_to_match = allocated;
+       default:
+         gold_unreachable();
+       }
+
+      Exact::const_iterator pe = lookup->exact.find(name_to_match);
+      if (pe != lookup->exact.end())
+       {
+         if (pversion != NULL)
+           *pversion = pe->second->tag;
+         if (allocated != NULL)
+           free (allocated);
+         return true;
+       }
+
+      for (std::vector<Glob>::const_iterator pg = lookup->globs.begin();
+          pg != lookup->globs.end();
+          ++pg)
+       {
+         // Check for * specially since it is fairly common.
+         if ((pg->pattern[0] == '*' && pg->pattern[1] == '\0')
+             || fnmatch(pg->pattern, name_to_match, FNM_NOESCAPE) == 0)
+           {
+             if (pversion != NULL)
+               *pversion = pg->version->tag;
+             if (allocated != NULL)
+               free (allocated);
+             return true;
+           }
+       }
+
+      if (allocated != NULL)
+       free (allocated);
     }
+
   return false;
 }
 
@@ -2042,21 +2108,33 @@ Version_script_info::print_expression_list(
     FILE* f,
     const Version_expression_list* vel) const
 {
-  std::string current_language;
+  Version_script_info::Language current_language = LANGUAGE_C;
   for (size_t i = 0; i < vel->expressions.size(); ++i)
     {
       const Version_expression& ve(vel->expressions[i]);
 
       if (ve.language != current_language)
        {
-         if (!current_language.empty())
+         if (current_language != LANGUAGE_C)
            fprintf(f, "      }\n");
-         fprintf(f, "      extern \"%s\" {\n", ve.language.c_str());
+         switch (ve.language)
+           {
+           case LANGUAGE_C:
+             break;
+           case LANGUAGE_CXX:
+             fprintf(f, "      extern \"C++\" {\n");
+             break;
+           case LANGUAGE_JAVA:
+             fprintf(f, "      extern \"Java\" {\n");
+             break;
+           default:
+             gold_unreachable();
+           }
          current_language = ve.language;
        }
 
       fprintf(f, "      ");
-      if (!current_language.empty())
+      if (current_language != LANGUAGE_C)
        fprintf(f, "  ");
 
       if (ve.exact_match)
@@ -2068,7 +2146,7 @@ Version_script_info::print_expression_list(
       fprintf(f, "\n");
     }
 
-  if (!current_language.empty())
+  if (current_language != LANGUAGE_C)
     fprintf(f, "      }\n");
 }
 
@@ -2403,6 +2481,9 @@ extern "C" void
 script_push_lex_into_version_mode(void* closurev)
 {
   Parser_closure* closure = static_cast<Parser_closure*>(closurev);
+  if (closure->version_script()->is_finalized())
+    gold_error(_("%s:%d:%d: invalid use of VERSION in input file"),
+              closure->filename(), closure->lineno(), closure->charpos());
   closure->push_lex_mode(Lex::VERSION_SCRIPT);
 }
 
@@ -2454,8 +2535,6 @@ script_add_vers_depend(void* closurev,
 }
 
 // Add a pattern expression to an existing list of expressions, if any.
-// TODO: In the old linker, the last argument used to be a bool, but I
-// don't know what it meant.
 
 extern "C" struct Version_expression_list *
 script_new_vers_pattern(void* closurev,
@@ -2507,7 +2586,25 @@ extern "C" void
 version_script_push_lang(void* closurev, const char* lang, int langlen)
 {
   Parser_closure* closure = static_cast<Parser_closure*>(closurev);
-  closure->push_language(std::string(lang, langlen));
+  std::string language(lang, langlen);
+  Version_script_info::Language code;
+  if (language.empty() || language == "C")
+    code = Version_script_info::LANGUAGE_C;
+  else if (language == "C++")
+    code = Version_script_info::LANGUAGE_CXX;
+  else if (language == "Java")
+    code = Version_script_info::LANGUAGE_JAVA;
+  else
+    {
+      char* buf = new char[langlen + 100];
+      snprintf(buf, langlen + 100,
+              _("unrecognized version script language '%s'"),
+              language.c_str());
+      yyerror(closurev, buf);
+      delete[] buf;
+      code = Version_script_info::LANGUAGE_C;
+    }
+  closure->push_language(code);
 }
 
 extern "C" void
index 71295658698ae782903b7321f9c9ed5a5fe6a3ce..a7e0186bde4497afc7b61dd310f0ad56781cc827 100644 (file)
@@ -128,12 +128,32 @@ class Expression
 class Version_script_info
 {
  public:
+  // The languages which can be specified in a versionn script.
+  enum Language
+  {
+    LANGUAGE_C,                // No demangling.
+    LANGUAGE_CXX,      // C++ demangling.
+    LANGUAGE_JAVA,     // Java demangling.
+    LANGUAGE_COUNT
+  };
+
+  Version_script_info();
+
   ~Version_script_info();
 
   // Clear everything.
   void
   clear();
 
+  // Finalize the version control information.
+  void
+  finalize();
+
+  // Return whether the information is finalized.
+  bool
+  is_finalized() const
+  { return this->is_finalized_; }
+
   // Return whether any version were defined in the version script.
   bool
   empty() const
@@ -152,8 +172,6 @@ class Version_script_info
   { return this->get_symbol_version_helper(symbol, false, NULL); }
 
   // Return the names of versions defined in the version script.
-  // Strings are allocated out of the stringpool given in the
-  // constructor.
   std::vector<std::string>
   get_versions() const;
 
@@ -174,6 +192,10 @@ class Version_script_info
   struct Version_tree*
   allocate_version_tree();
 
+  // Build the lookup tables after all data have been read.
+  void
+  build_lookup_tables();
+
   // Print contents to the FILE.  This is for debugging.
   void
   print(FILE*) const;
@@ -182,13 +204,58 @@ class Version_script_info
   void
   print_expression_list(FILE* f, const Version_expression_list*) const;
 
-  bool get_symbol_version_helper(const char* symbol,
-                                bool check_global,
-                                std::string* pversion) const;
+  bool
+  get_symbol_version_helper(const char* symbol,
+                           bool check_global,
+                           std::string* pversion) const;
+
+  // Fast lookup information for a glob pattern.
+  struct Glob
+  {
+    Glob()
+      : pattern(NULL), version(NULL)
+    { }
+
+    Glob(const char* p, const Version_tree* v)
+      : pattern(p), version(v)
+    { }
+
+    // A pointer to the glob pattern.  The pattern itself lives in a
+    // Version_expression structure.
+    const char* pattern;
+    // The Version_tree we use if this pattern matches.
+    const Version_tree* version;
+  };
+
+  // Fast lookup information for a given language.
+
+  typedef Unordered_map<std::string, const Version_tree*> Exact;
+
+  struct Lookup
+  {
+    // A hash table of all exact match strings mapping to a
+    // Version_tree.
+    Exact exact;
+    // A vector of glob patterns mapping to Version_trees.
+    std::vector<Glob> globs;
+  };
 
-  std::vector<struct Version_dependency_list*> dependency_lists_;
-  std::vector<struct Version_expression_list*> expression_lists_;
-  std::vector<struct Version_tree*> version_trees_;
+  void
+  build_expression_list_lookup(const Version_expression_list*,
+                              const Version_tree*, Lookup**);
+
+  // All the version dependencies we allocate.
+  std::vector<Version_dependency_list*> dependency_lists_;
+  // All the version expressions we allocate.
+  std::vector<Version_expression_list*> expression_lists_;
+  // The list of versions.
+  std::vector<Version_tree*> version_trees_;
+  // Lookup information for global symbols, by language.
+  Lookup* globals_[LANGUAGE_COUNT];
+  // Lookup information for local symbols, by language.
+  Lookup* locals_[LANGUAGE_COUNT];
+  // Whether this has been finalized.
+  bool is_finalized_;
 };
 
 // This class manages assignments to symbols.  These can appear in
index a0fcf5955b87f7b998606e67359dc9a902113c54..61934aa2bf33c78c0c28a1abdbf5aa0c3ee38f08 100644 (file)
@@ -1004,7 +1004,7 @@ binary.txt: $(srcdir)/binary.in
 check_SCRIPTS += ver_matching_test.sh
 check_DATA += ver_matching_test.stdout
 MOSTLYCLEANFILES += ver_matching_test.stdout
-ver_matching_def.so: ver_matching_def.cc gcctestdir/ld
+ver_matching_def.so: ver_matching_def.cc $(srcdir)/version_script.map gcctestdir/ld
        $(CXXLINK) -O0 -Bgcctestdir/ -shared $(srcdir)/ver_matching_def.cc -Wl,--version-script=$(srcdir)/version_script.map
 ver_matching_test.stdout: ver_matching_def.so
        $(TEST_OBJDUMP) -T ver_matching_def.so | $(TEST_CXXFILT) > ver_matching_test.stdout
index 696c05e51b8a276972b53e9c6840849e10a8d327..81b8b7f501c916d879c341b0f9aa27d3bcbeef9f 100644 (file)
@@ -2887,7 +2887,7 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@binary.txt: $(srcdir)/binary.in
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LN_S) $< $@
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_matching_def.so: ver_matching_def.cc gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_matching_def.so: ver_matching_def.cc $(srcdir)/version_script.map gcctestdir/ld
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -O0 -Bgcctestdir/ -shared $(srcdir)/ver_matching_def.cc -Wl,--version-script=$(srcdir)/version_script.map
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_matching_test.stdout: ver_matching_def.so
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -T ver_matching_def.so | $(TEST_CXXFILT) > ver_matching_test.stdout
index 9f7d3503af97fe024fe7ee0ae2eede6c6b7a67ed..e97c74eb2a0f1cf886e1baf1295b45b0fd82b570 100644 (file)
@@ -30,7 +30,6 @@ VER1 {
 VER2 {
   global:
     t1_2;
-    t2_2;
     t4_2a;
 } VER1;
 
index 3b7d1b6fef312279413eba5f417ba9b51a0b6def..d3ba02ef0c5903b34381bd09a83ef4a6cc628400 100644 (file)
@@ -29,7 +29,6 @@ V2 {
            otherns::stuff;
         };
         blaz*;
-       foo;
    local:
        _[^A-Z]*;
 } V1;