[llvm-bugs] [Bug 46313] New: clang unresolved symbol for protobuf RepeatedField template

via llvm-bugs llvm-bugs at lists.llvm.org
Sat Jun 13 09:49:15 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=46313

            Bug ID: 46313
           Summary: clang unresolved symbol for protobuf RepeatedField
                    template
           Product: clang
           Version: 10.0
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: steven at uplinklabs.net
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org,
                    neeilans at live.com, richard-llvm at metafoo.co.uk

Created attachment 23613
  --> https://bugs.llvm.org/attachment.cgi?id=23613&action=edit
testcase for bug

I first noticed this in an automated build for the GameNetworkingSockets
library:

https://travis-ci.org/github/ValveSoftware/GameNetworkingSockets/jobs/697717206#L1564

The builder is using Docker to run various distributions of Linux and build the
library against that distribution's system libraries, including protobuf.

In this case, the Docker image is for Arch Linux, which has Clang 10.0, GCC
10.1, and protobuf 3.12.0.

Building the shared library fails because it believes a symbol is missing at
link time:

google::protobuf::RepeatedField<unsigned
int>::RepeatedField(google::protobuf::RepeatedField<unsigned int> const&)

Mangled symbol name is: _ZN6google8protobuf13RepeatedFieldIiEC2ERKS2_

With GCC 10.1, this all compiles and links fine. But this one symbol gives
trouble on Clang 10.0.

This is the difference in unresolved symbols (wrt RepeatedField) in the objects
as compiled by clang/gcc:

# object built with Clang 10.0
$ nm
build-meson-sodium25519/src/25a6634@@GameNetworkingSockets at sha/meson-generated_steamnetworkingsockets_messages.pb.cc.o
 | grep RepeatedField
                 U _ZN6google8protobuf13RepeatedFieldIiE12InternalSwapEPS2_
                 U _ZN6google8protobuf13RepeatedFieldIiE7ReserveEi
                 U _ZN6google8protobuf13RepeatedFieldIiE9MergeFromERKS2_
                 U _ZN6google8protobuf13RepeatedFieldIiEC2ERKS2_
                 U _ZN6google8protobuf13RepeatedFieldIiED1Ev
                 U _ZNK6google8protobuf13RepeatedFieldIiE3GetEi

# object built with gcc 10.1
$ nm
build-meson-sodium25519-gcc/src/25a6634@@GameNetworkingSockets at sha/meson-generated_steamnetworkingsockets_messages.pb.cc.o
 | grep RepeatedField
                 U _ZN6google8protobuf13RepeatedFieldIiE7ReserveEi
                 U _ZN6google8protobuf13RepeatedFieldIiED1Ev

With some effort, I managed to create a reduced test case for this. It's a bit
of a challenge when g++ -E or clang++ -E will generate outputs that cannot be
compiled by the other compiler, but it was easier to tweak the output of "g++
-E -fdirectives-only" to be compilable with Clang than it was the other way
around. I wanted to ensure the test case compiled with both and satisfied the
constraint that _ZN6google8protobuf13RepeatedFieldIiEC2ERKS2_ was undefined in
the clang object and absent from the GCC object. My first attempt used only
clang to create a reduced test case and the symbol ended up being undefined for
*both* compilers, which isn't the desired scenario.

The reduced test case could probably be more concise if someone knows what's
going on with it:

---
namespace google {
namespace protobuf {
enum a { LOGLEVEL_FATAL };
class b {
public:
  b(a, const char *, int);
  ~b();
  b operator<<(const char *);
  b operator<<(char);
};
class c {
public:
  void operator=(b);
};
#define d(f) c() = b(LOGLEVEL_##f, __FILE__, __LINE__)
#define e(f, l) l ? (void)0 : d(f)
#define g(i) e(FATAL, i) << ""
#define h(k, j) g(j)
template <typename> class RepeatedField {
public:
  RepeatedField(const RepeatedField &);
  int o();
  int m;
};
template <typename p>
inline RepeatedField<p>::RepeatedField(const RepeatedField &p1) {
  if (p1.m) {
    int t = o(), n = t;
    h(, n) << m;
  }
}
extern template class RepeatedField<int>;
} // namespace protobuf
} // namespace google
class A {
  A(const A &);
  google::protobuf::RepeatedField<int> q;
};
A::A(const A &p1) : q(p1.q) {}
---

I've attached a tarball with the original partially preprocessed source, the
script I used for creduce, and the two objects built by clang/gcc.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200613/0dc4f3a5/attachment.html>


More information about the llvm-bugs mailing list