Compilers that support argument-dependent lookup - c++

In our codebase we use extensively boost::intrusive_ptr and after moving some headers around I started to get unexpected compilation errors from clang:
In file included from C:/code/Signal.cpp:1:
In file included from C:/code/signal.h:3:
In file included from c:/boost_1_56_0/include/boost/smart_ptr.hpp:26:
In file included from c:/boost_1_56_0/include/boost/intrusive_ptr.hpp:16:
c:/boost_1_56_0/include/boost/smart_ptr/intrusive_ptr.hpp:68:34: error: call to function 'intrusive_ptr_add_ref' that is neither visible in the template definition nor found by argument-dependent lookup
if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
There are similar issues reported elsewhere.
Our code that uses boost::intrusive_ptr was written a while ago and defines all these freestanding function (like intrusive_ptr_add_ref) in boost namespace. After checking what was the reason of compilation errors that I started to get, it appears that I should define these functions in my namespace instead. From description of intrusive_ptr:
On compilers that support argument-dependent lookup,
intrusive_ptr_add_ref and intrusive_ptr_release should be defined in
the namespace that corresponds to their parameter; otherwise, the
definitions need to go in namespace boost.
I assume most modern compilers do support ADL, however, I couldn't find definite information on what compilers support and what do not support ADL.
So, here's the question: what are these compilers that do not support ADL. I'm primarily interested in microsoft compilers (VS2012, VS2015), and faily recent versions of gcc and clang.

According to this page, ADL support was added in Visual Studio 2008.
With some difficulty, I was able to build EGCS 1.1, the first GCC version that claimed to support namespaces, released in 1997. I tested it by compiling and running the following program:
#include <stdio.h>
namespace foo {
class bar {};
void baz(bar&) {
puts("foo::baz");
}
}
void baz(const foo::bar&) {
puts("::baz");
}
int main() {
foo::bar bar;
baz(bar);
}
It printed foo::baz, which is correct. So basic ADL functionality existed in GCC even back in those days. I doubt you could even build Boost using a compiler that old.
Clang 2.7 also gets it right. Note that LLVM 2.7, released in 2010, was the first version of LLVM to ship with C++ support in Clang enabled by default. There are older versions of the Clang C++ frontend, but I don't think they were widely used, and I am too lazy to try to build them from SVN.

Related

clang insists on compiling uncalled functions

Moving from using Intel compiler & VC to Apple clang 12.0.
In my code there are functions that are never called for a certain project (but needed when included in other projects). Clang insists on compiling the uncalled functions and detects errors, where Intel and VC simply skipped compilation.
These are errors that are tricky to fix for that certain project.
Is there a Clang flag that means "Don't compile if not called"?
EDIT: example:
template <class T> class A
{
public:
void foo() { garbage }; // <--- syntax error
};
int main() {
A<int> my_obj;
//my_obj.foo(); // <--- when unremarked, will fail all compilers
}
Compiler Explorer demo: Intel vs. Clang
Intel and VC compilers are relaxed until the call to foo() enters the scene.
Clang has a mode in which is tries to behave as if it's MSVC. This was introduced as part clang-cl, the driver for clang that accepts a lot of the same arguments as MSVC. You can find some information about it on the user manual and the MSVC compatibility pages.
Long story short, there is an option -fdelayed-template-parsing in clang that takes over the faulty behavior of the templates. As far as I'm aware, this ain't a 100% match, however, it is good enough.
If we add this to the example of Artyer, it compiles the code, see compiler-explorer.
From my experience of adding clang as 2nd compiler next to MSVC (it was still both on Windows using clang-cl, I didn't have to deal with the complexity of multiple OS and/or STL), I want to recommend to you to take this option as a temporary thing to get things working. Take your time removing this, as it will help making your code more maintainable.
EDIT: If you want to know more about why the compilation error is the right thing to do, you can lookup the term 2 phase lookup. You can find the announcement of it's introduction in the MSVC compiler here: https://devblogs.microsoft.com/cppblog/two-phase-name-lookup-support-comes-to-msvc/
From what I can see online, the intel compiler ain't doing 2 phase lookup either, or at least not the reporting of the errors.

-O1/2/3 with -std=c++1y/11/98 - If <cmath> is included i'm getting error: '_hypot' was not declared in this scope

I've just updated MinGW using mingw-get-setup and i'm unable to build anyting that contains <cmath> header if I use anything larger than -O0 with -std=c++1y. (I also tried c++11 and c++98) I'm getting errors like this one:
g++.exe -pedantic-errors -pedantic -Wextra -Wall -std=c++1y -O3 -c Z:\Projects\C++\L6\src\events.cpp -o obj\src\events.o
In file included from z:\lander\mingw\lib\gcc\mingw32\4.8.1\include\c++\cmath:44:0,
from Z:\Projects\C++\L6\src\utils.h:4,
from Z:\Projects\C++\L6\src\events.cpp:10:
z:\lander\mingw\include\math.h: In function 'float hypotf(float, float)':
z:\lander\mingw\include\math.h:635:30: error: '_hypot' was not declared in this scope
{ return (float)(_hypot (x, y)); }
Is something wrong on my side?
Or version at mingw repo is bugged? And if so, is there any quick fix for this header?
To avoid any further speculation, and downright bad suggestions such as using #if 0, let me give an authoritative answer, from the perspective of a MinGW project contributor.
Yes, the MinGW.org implementation of include/math.h does have a bug in its inline implementation of hypotf (float, float); the bug is triggered when compiling C++, with the affected header included (as it is when cmath is included), and any compiler option which causes __STRICT_ANSI__ to become defined is specified, (as is the case for those -std=c... options noted by the OP). The appropriate solution is not to occlude part of the math.h file, with #if 0 or otherwise, but to correct the broken inline implementation of hypotf (float, float); simply removing the spurious leading underscore from the inline reference to _hypot (float, float), where its return value is cast to the float return type should suffice.
Alternatively, substituting an equivalent -std=gnu... for -std=c... in the compiler options should circumvent the bug, and may offer a suitable workaround.
FWIW, I'm not entirely happy with MinGW.org's current implementation of hypotl (long double, long double) either; correcting both issues is on my punch list for the next release of the MinGW runtime, but ATM, I have little time to devote to preparing this.
Update
This bug is no longer present in the current release of the MinGW.org runtime library (currently mingwrt-3.22.4, but fixed since release 3.22). If you are using anything older than this, (including any of the critically broken 4.x releases), you should upgrade.
As noted by Keith, this is a bug in the MinGW.org header.
As an alternative to editing the MinGW.org header, you can use MinGW-w64, which provides everything MinGW.org provides, and a whole lot more.
For a list of differences between the runtimes, see this wiki page.
MinGW uses gcc and the Microsoft runtime library. Microsoft's implementation support C90, but its support for later versions of the C standard (C99 and C11) is very poor.
The hypot function (along with hypotf and hypotl) was added in C99.
If you're getting this error with a program that calls hypot, such as:
#include <cmath>
int main() {
std::cout << std::hypot(3.0, 4.0)) << '\n';
}
then it's just a limitation of the Microsoft runtime library, and therefore of MinGW. If it occurs with any program that has #include <cmath>, then it's a bug, perhaps a configuration error, in MinGW.

how to enable __BEGIN_NAMESPACE_STD in stdlib.h

I am now trying to build a c++ library in linux with cmake. If I do not enable -std=c++0x option, I always get compilation errors error: 'div_t' was not declared in this scope for the following codes:
int xPos;
div_t divResult;
divResult = div(xPos,8);
Then if I enable -std-c++0x options with cmake: set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x", then everything is fine. However, in my library I did not use any c++0x features, so I am reluctant to set std=c++0x option. So I search the head file that defines div_t and find it is defined in stdlib.h within the following MACRO:
__BEGIN_NAMESPACE_STD
typedef struct
{
int quot;
int rem;
} div_t;
....
....
__END_NAMESPACE_STD
It seems to me that if I can enable these macros I can build the library without enabling c++0x feature. So my question is what I can do in this situation.
By the way, I can build the library very well without enabling c++0x feature if only g++4.4 is installed in the linux machine. When I also install g++4.6 and make g++4.6 the default g++, then the compilation error began to occur. Even I changed the default g++ to g++4.4, the compilation error still exists if I do not enable c++0x feature.
The macros expand to namespace std { and } respectively if the code is pulled in through a C++ standard library header. This leads me to believe that you're not #including stdlib.h directly (which is good!).
Earlier versions of libstdc++ pulled symbols from C legacy headers into the global namespace even if the C++ versions of these headers (e.g. <cstdlib> instead of <stdlib.h>) were used; newer ones place them only in namespace std.
The cleanest way to fix this is to
#include <cstdlib>
in all translation units where the problem occurs and to use std::div instead of div. If you're lazy, you can also
#include <stdlib.h>
in all translation units that use div, but mixing C and C++ is always icky. Not terribad in this particular case, though.

How to detect the libstdc++ version in Clang?

I would like to write a "portable" C++ library in Clang. "Portable" means that I detect (in C preprocessor) what C++ features are available in the compilation environment and use these features or provide my workarounds. This is similar to what Boost libraries are doing.
However, the presence of some features depends not on the language, but on the Standard Library implementation. In particular I am interested in:
type traits (which of them are available and with what spelling)
if initializer_list being constexpr.
I find this problematic because Clang by default does not use its own Standard Library implementation: it uses libstdc++. While Clang has predefined preprocessor macros __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__, they are hardcoded to values 4, 2, 1 respectively, and they tell me little about the available libstdc++ features.
How can I check in Clang preprocessor what version of libstdc++ it is using?
Clang does come with its own standard library implementation, it's called libc++. You can use it by adding -stdlib=libc++ to your compile command.
That being said, there are various ways to check Clang/libstdc++ C++ support:
Clang has the __has_feature macro (and friends) that can be used to detect language features and language extenstions.
Libstdc++ has its own version macros, see the documentation. You'll need to include a libstdc++ header to get these defined though.
GCC has its version macros which you already discovered, but those would need to be manually compared to the documentation.
And also, this took me 2 minutes of googling.
This is what I think would help. It prints the value of the _LIBCPP_VERSION macro:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, const char * argv[])
{
cout<<"Value = "<<_LIBCPP_VERSION<<endl;
return 0;
}
Compile it again the version of clang you want the info for.

Orwell Dev C++ doesn't work with C++11

I'm trying to use any of the C++11 features in Orwell Dev C++ but with no luck. I installed the version with minGW and whatever I set in the compiler options, I just get the "[Error] 'to_string' was not declared in this scope" in this code:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string test = to_string(5);
}
I tried setting -std=gnu++11 and -std=c++0x but neither does the job. What's the most curious is that when I click on to_string, it shows me the overloaded functions - for long, float, int and so on. Thus, it must somehow get what the function does - how come it doesn't compile it, then? The compiler is set correctly to MinGW GCC 4.7.2 (the one bundled with the installer).
If you want to use C++11 in Dev-C++ you should to this steps:
Go to Tools > Compiler Options
Go to the tab Settings > Code Generation
Change the parameter Language Standard (-std) to ISO C++11
It is a known bug that to_string does not work with MinGW yet (which is actually GCC's fault, to a degree):
http://sourceforge.net/p/mingw/bugs/1578/
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52015
Intellisense is often driven by a different engine than the compiler (as very few compilers have hooks to make intellisense easy), so that's likely why you're seeing it in your IDE when it's not supported by your compiler.