Recommit [ELF] - Versionscript: do not treat non-wildcarded names as wildcards.

Fixed code that was not checked before on windows for me, because of testcases that are
disabled on that platform atm.

Inital commit message:
"[ELF] - Versionscript: do not treat non-wildcarded names as wildcards."
Previously we incorrectly handled cases when symbol name in extern c++ tag
was enclosed in quotes. Next case was treated as wildcard:

GLIBCXX_3.4 {                                                                   
    extern "C++" {  
    "aaa*"
   }
But it should have not. Quotes around aaa here means that we should have do exact
name matching.
That is PR30268 which has name with pointer is interpreted as wildcard by lld:

extern "C++" {                                                              
    "operator delete[](void*)";

Patch fixes the issue.

Differential revision: https://reviews.llvm.org/D24229

llvm-svn: 281049
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 4d7cf3e2..98246c3 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -45,6 +45,7 @@
 struct SymbolVersion {
   llvm::StringRef Name;
   bool IsExternCpp;
+  bool HasWildcards;
 };
 
 // This struct contains symbols version definition that
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 9d6935f..ef8ccb9 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -785,7 +785,7 @@
   bool Orig = Config->AsNeeded;
   Config->AsNeeded = true;
   while (!Error && !skip(")"))
-    addFile(next());
+    addFile(unquote(next()));
   Config->AsNeeded = Orig;
 }
 
@@ -811,13 +811,13 @@
     if (Tok == "AS_NEEDED")
       readAsNeeded();
     else
-      addFile(Tok);
+      addFile(unquote(Tok));
   }
 }
 
 void ScriptParser::readInclude() {
   StringRef Tok = next();
-  auto MBOrErr = MemoryBuffer::getFile(Tok);
+  auto MBOrErr = MemoryBuffer::getFile(unquote(Tok));
   if (!MBOrErr) {
     setError("cannot open " + Tok);
     return;
@@ -833,7 +833,7 @@
   expect("(");
   StringRef Tok = next();
   if (Config->OutputFile.empty())
-    Config->OutputFile = Tok;
+    Config->OutputFile = unquote(Tok);
   expect(")");
 }
 
@@ -896,7 +896,7 @@
   expect("(");
   StringRef Tok = next();
   if (!Config->Nostdlib)
-    Config->SearchPaths.push_back(Tok);
+    Config->SearchPaths.push_back(unquote(Tok));
   expect(")");
 }
 
@@ -1004,7 +1004,7 @@
   expect("(");
   Expr E = readExpr();
   expect(",");
-  StringRef Msg = next();
+  StringRef Msg = unquote(next());
   expect(")");
   return [=](uint64_t Dot) {
     uint64_t V = E(Dot);
@@ -1421,13 +1421,14 @@
 }
 
 void ScriptParser::readExtern(std::vector<SymbolVersion> *Globals) {
-  expect("C++");
+  expect("\"C++\"");
   expect("{");
 
   for (;;) {
     if (peek() == "}" || Error)
       break;
-    Globals->push_back({next(), true});
+    bool HasWildcard = !peek().startswith("\"") && hasWildcard(peek());
+    Globals->push_back({unquote(next()), true, HasWildcard});
     expect(";");
   }
 
@@ -1450,7 +1451,7 @@
     if (Cur == "}" || Cur == "local:" || Error)
       return;
     next();
-    Globals->push_back({Cur, false});
+    Globals->push_back({unquote(Cur), false, hasWildcard(Cur)});
     expect(";");
   }
 }
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 19e20b6..97d68d9 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -60,14 +60,17 @@
     if (S.empty())
       return Ret;
 
-    // Quoted token.
+    // Quoted token. Note that double-quote characters are parts of a token
+    // because, in a glob match context, only unquoted tokens are interpreted
+    // as glob patterns. Double-quoted tokens are literal patterns in that
+    // context.
     if (S.startswith("\"")) {
       size_t E = S.find("\"", 1);
       if (E == StringRef::npos) {
         error("unclosed quote");
         return {};
       }
-      Ret.push_back(S.substr(1, E - 1));
+      Ret.push_back(S.take_front(E + 1));
       S = S.substr(E + 1);
       continue;
     }
diff --git a/lld/ELF/Strings.cpp b/lld/ELF/Strings.cpp
index fec7bd4..cd19612 100644
--- a/lld/ELF/Strings.cpp
+++ b/lld/ELF/Strings.cpp
@@ -24,6 +24,12 @@
   return S.find_first_of("?*[") != StringRef::npos;
 }
 
+StringRef elf::unquote(StringRef S) {
+  if (!S.startswith("\""))
+    return S;
+  return S.substr(1, S.size() - 2);
+}
+
 // Converts a glob pattern to a regular expression.
 static std::string toRegex(StringRef S) {
   std::string T;
diff --git a/lld/ELF/Strings.h b/lld/ELF/Strings.h
index ad99eb9..e08423a 100644
--- a/lld/ELF/Strings.h
+++ b/lld/ELF/Strings.h
@@ -20,6 +20,7 @@
 bool hasWildcard(StringRef S);
 std::vector<uint8_t> parseHex(StringRef S);
 bool isValidCIdentifier(StringRef S);
+StringRef unquote(StringRef S);
 
 // Returns a demangled C++ symbol name. If Name is not a mangled
 // name or the system does not provide __cxa_demangle function,
diff --git a/lld/ELF/SymbolListFile.cpp b/lld/ELF/SymbolListFile.cpp
index cd977c5..3fe83d4 100644
--- a/lld/ELF/SymbolListFile.cpp
+++ b/lld/ELF/SymbolListFile.cpp
@@ -16,6 +16,7 @@
 #include "SymbolListFile.h"
 #include "Config.h"
 #include "ScriptParser.h"
+#include "Strings.h"
 #include "llvm/Support/MemoryBuffer.h"
 
 using namespace llvm;
@@ -43,7 +44,7 @@
   while (!atEOF()) {
     expect("{");
     while (!Error) {
-      Config->DynamicList.push_back(next());
+      Config->DynamicList.push_back(unquote(next()));
       expect(";");
       if (skip("}"))
         break;
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index d80e512..f758247 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -18,7 +18,6 @@
 #include "Config.h"
 #include "Error.h"
 #include "LinkerScript.h"
-#include "Strings.h"
 #include "SymbolListFile.h"
 #include "Symbols.h"
 #include "llvm/Bitcode/ReaderWriter.h"
@@ -678,7 +677,7 @@
   // i.e. version definitions not containing any glob meta-characters.
   for (VersionDefinition &V : Config->VersionDefinitions) {
     for (SymbolVersion Sym : V.Globals) {
-      if (hasWildcard(Sym.Name))
+      if (Sym.HasWildcards)
         continue;
       StringRef N = Sym.Name;
       SymbolBody *B = Sym.IsExternCpp ? findDemangled(Demangled, N) : find(N);
@@ -693,7 +692,7 @@
   for (size_t I = Config->VersionDefinitions.size() - 1; I != (size_t)-1; --I) {
     VersionDefinition &V = Config->VersionDefinitions[I];
     for (SymbolVersion &Sym : V.Globals) {
-      if (!hasWildcard(Sym.Name))
+      if (!Sym.HasWildcards)
         continue;
       Regex Re = compileGlobPatterns({Sym.Name});
       std::vector<SymbolBody *> Syms =
diff --git a/lld/test/ELF/invalid-dynamic-list.test b/lld/test/ELF/invalid-dynamic-list.test
index 0e7c820..11b7900 100644
--- a/lld/test/ELF/invalid-dynamic-list.test
+++ b/lld/test/ELF/invalid-dynamic-list.test
@@ -34,4 +34,4 @@
 
 # RUN: echo "{ extern \"BOGUS\" { test }; };" > %t1
 # RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR6 %s
-# ERR6: line 1: ; expected, but got BOGUS
+# ERR6: line 1: ; expected, but got "BOGUS"
diff --git a/lld/test/ELF/version-script-extern-exact.s b/lld/test/ELF/version-script-extern-exact.s
new file mode 100644
index 0000000..b33ea35
--- /dev/null
+++ b/lld/test/ELF/version-script-extern-exact.s
@@ -0,0 +1,22 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "FOO { global: extern \"C++\" { \"aaa*\"; }; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck %s
+
+# CHECK: Symbol {
+# CHECK:   Name: _Z3aaaPf@ (1)
+# CHECK: Symbol {
+# CHECK:   Name: _Z3aaaPi@ (10)
+
+.text
+.globl _Z3aaaPi
+.type _Z3aaaPi,@function
+_Z3aaaPi:
+retq
+
+.globl _Z3aaaPf
+.type _Z3aaaPf,@function
+_Z3aaaPf:
+retq