Multiple definition of static constexpr data member with C++11 and 17

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I had a multiple definition error while trying to link a c++17 program
against a c++11-compiled library. The error doesn't happen if I use Clang
so I want to ask whether this is supported by GCC or something is wrong
with my code. I have a very small reproducer that I extracted from the real
code:

The library:

===============================
$ cat lib.h
#pragma once

struct A {
    static constexpr int x{ -1 };
};

void f(const int &x);
===============================

===============================
$ cat lib.cpp
#include "lib.h"

constexpr int A::x;

void f(const int& x) {}
===============================

And my program:

===============================
$ cat main.cpp
#include "lib.h"

int main() {
    f(A::x);
    return 0;
}
===============================


I use the following commands to compile the library and the main program:
===============================
$ g++ -std=c++11 -o lib.o -c lib.cpp
$ g++ -std=c++17 -o main.o -c main.cpp
$ g++ -o main lib.o main.o
/usr/bin/ld: main.o:(.rodata._ZN1A1xE[_ZN1A1xE]+0x0): multiple definition
of `A::x'; lib.o:(.rodata+0x0): first defined here
collect2: error: ld returned 1 exit status
===============================

As shown, the last command fails with an error. If I replace "g++" with
"clang++", it works. Or if I use the same C++ standard (11 or 17) for both
object files, it works.

My questions are:
1. Is mixing C++11 and C++17-compiled object files like I do supported by
GCC?
2. If it is supported, then is something wrong with my code? The library is
compiled using C++11 and the C++11 standard requires that explicit
definition of constexpr static members are provided if they are odr-used
(which it is in my case), so lib.cpp has a definition of A::x. But if I try
to link the resulting object file with another object file that was
compiled using C++17, the linker gives a multiple definition error.

I have also compared symbol tables of main.o generated by GCC and Clang:
==================================================================
$ g++ -std=c++17 -o main.o -c main.cpp && readelf -s main.o | c++filt |
grep A::x
    11: 0000000000000000     4 OBJECT  UNIQUE DEFAULT    6 A::x
$ clang++ -std=c++17 -o main.o -c main.cpp && readelf -s main.o | c++filt |
grep A::x
     4: 0000000000000000     4 OBJECT  WEAK   DEFAULT    5 A::x
==================================================================
Clang generates a  WEAK symbol for A::x but GCC doesn't, maybe that's the
problem?

Relevant system and version info:
================================
$ g++ --version
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
$ clang++ --version
clang version 10.0.0-4ubuntu1
$ uname -a
Linux tp 5.10.0-1038-oem #40-Ubuntu SMP Fri Jul 16 15:08:30 UTC 2021 x86_64
x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.2 LTS
Release: 20.04
Codename: focal
================================

Thanks in advance.



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux