Bug 1206815

Summary: Link failure with -fno-implicit-templates
Product: [Fedora] Fedora Reporter: Paulo Andrade <paulo.cesar.pereira.de.andrade>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED CURRENTRELEASE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: medium    
Version: rawhideCC: davejohansen, jakub, jwakely, law, mpolacek
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: All   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-05-30 21:18:33 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Paulo Andrade 2015-03-28 19:50:50 UTC
This simple test:
---%<---
#include <string>
std::string test(int i)
{
    std::string t;
    std::string s = "(";
    t = "";
    for (int r = i; r; r>>=1) {
	if (r & 1)
	    t = "1" + t;
	else
	    t = "0" + t;
    }
    s += t;
    s += ")";
    return s;
}

int
main(int argc, char *argv[])
{
    std::string s = test(16);
    return 0;
}
---%<---

fails to link if compiled with -fno-implicit-templates

I believe it is a bug because, it did work before
(the above is a reduced test case), and if using
a temporary, or explicitly cast it works, e.g.:

-        t = "1" + t;
+        t = std::string("1") + t;

Comment 1 Jonathan Wakely 2015-03-30 13:25:48 UTC
The operator+ overloads for the new std::string are present but are not being exported from the library, I'll fix it upstream.

Comment 2 Jonathan Wakely 2015-03-30 14:57:10 UTC
What was the testcase reduced from?

The code has never been guaranteed to work, and is completely non-portable, but did happen to work with older versions of GCC.

Comment 3 Paulo Andrade 2015-03-30 17:22:44 UTC
It is in the Singular package. The patch I plan to
use is:

---8<---
diff -up Singular-3-1-6/Singular/Minor.cc.orig Singular-3-1-6/Singular/Minor.cc
--- Singular-3-1-6/Singular/Minor.cc.orig	2015-03-28 20:41:36.396539843 -0300
+++ Singular-3-1-6/Singular/Minor.cc	2015-03-28 20:42:33.458542028 -0300
@@ -799,7 +802,7 @@ string MinorKey::toString() const
     z = this->getRowKey(r);
     while (z != 0)
     {
-      if ((z % 2) != 0) t = "1" + t; else t = "0" + t;
+      if ((z % 2) != 0) t = string("1") + t; else t = string("0") + t;
       z = z / 2;
     }
     if (r < this->getNumberOfRowBlocks() - 1)
@@ -813,7 +816,7 @@ string MinorKey::toString() const
     z = this->getColumnKey(c);
     while (z != 0)
     {
-      if ((z % 2) != 0) t = "1" + t; else t = "0" + t;
+      if ((z % 2) != 0) t = string("1") + t; else t = string("0") + t;
       z = z / 2;
     }
     if (c < this->getNumberOfColumnBlocks() - 1)
---8<---

In master branch this function was even commented out:
https://github.com/Singular/Sources/blob/master/Singular/Minor.cc#L793

One of the README files still say need to use -fno-implicit-templates:
https://github.com/Singular/Sources/blob/master/factory/README#L358

Comment 4 Jonathan Wakely 2015-03-30 17:42:17 UTC
(In reply to Paulo Andrade from comment #3)
> -      if ((z % 2) != 0) t = "1" + t; else t = "0" + t;
> +      if ((z % 2) != 0) t = string("1") + t; else t = string("0") + t;

I would do simply t.insert(t.begin(), (z % 2) ? '1' : '0');

(Even that is still horribly inefficient, resulting in lots of bytes being shuffled around every time a new character is inserted at the beginning).


> One of the README files still say need to use -fno-implicit-templates:
> https://github.com/Singular/Sources/blob/master/factory/README#L358

That claim about "the most reliable way" is about 10 years out of date, but if the code is using -fno-implicit-templates then it should be explicitly instantiating the operator+ template in ftmpl_inst.cc instead of relying on undocumented instantiations in libstdc++.so. They shouldn't insist on doing their own manual instantations and then fail to actually instantiate them!

This seems like a bug in the package, and your patch just hides it.

Comment 5 Jonathan Wakely 2015-03-30 18:04:09 UTC
This is now fixed in upstream GCC by https://gcc.gnu.org/r221775

Comment 6 Paulo Andrade 2015-05-30 21:18:33 UTC
This bug can be closed, in the worst case, a simple patch
was already applied, and with time upstream will work
on it as well.