Tool oddity

Hi,

I'm seeing some odd behaviour that I hope someone can suggest a solution for:

Recently, when I run my tool on my test file I get errors that I don't get if I run clang++ with equivalent options -

In file included from /home/peter/Programming/llvm/llvm/tools/clang/tools/extra/quaff/dummy.cc:6:
In file included from /usr/include/taglib/taglib.h:47:
In file included from /../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/string:40:
In file included from /../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/bits/char_traits.h:39:
In file included from /../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:63:
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:58:35: error: invalid operands to binary expression ('float' and 'unsigned long')
       static const _Value __min = __glibcxx_min(_Value);
                                   ^~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:48:35: note: expanded from macro '__glibcxx_min'
   (__glibcxx_signed(_Tp) ? (_Tp)1 << __glibcxx_digits(_Tp) : (_Tp)0)
                            ~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:55:12: note: in instantiation of template class '__gnu_cxx::__numeric_traits_integer<float>' requested here
     struct __numeric_traits_integer
            ^
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:59:35: error: invalid operands to binary expression ('float' and 'unsigned long')
       static const _Value __max = __glibcxx_max(_Value);
                                   ^~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:52:15: note: expanded from macro '__glibcxx_max'
    (((((_Tp)1 << (__glibcxx_digits(_Tp) - 1)) - 1) << 1) + 1) : ~(_Tp)0)
        ~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:58:35: error: invalid operands to binary expression ('double' and 'unsigned long')
       static const _Value __min = __glibcxx_min(_Value);
                                   ^~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:48:35: note: expanded from macro '__glibcxx_min'
   (__glibcxx_signed(_Tp) ? (_Tp)1 << __glibcxx_digits(_Tp) : (_Tp)0)
                            ~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:55:12: note: in instantiation of template class '__gnu_cxx::__numeric_traits_integer<double>' requested here
     struct __numeric_traits_integer
            ^
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:59:35: error: invalid operands to binary expression ('double' and 'unsigned long')
       static const _Value __max = __glibcxx_max(_Value);
                                   ^~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:52:15: note: expanded from macro '__glibcxx_max'
    (((((_Tp)1 << (__glibcxx_digits(_Tp) - 1)) - 1) << 1) + 1) : ~(_Tp)0)
        ~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:58:35: error: invalid operands to binary expression ('long double' and 'unsigned long')
       static const _Value __min = __glibcxx_min(_Value);
                                   ^~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:48:35: note: expanded from macro '__glibcxx_min'
   (__glibcxx_signed(_Tp) ? (_Tp)1 << __glibcxx_digits(_Tp) : (_Tp)0)
                            ~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:55:12: note: in instantiation of template class '__gnu_cxx::__numeric_traits_integer<long double>' requested here
     struct __numeric_traits_integer
            ^
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:59:35: error: invalid operands to binary expression ('long double' and 'unsigned long')
       static const _Value __max = __glibcxx_max(_Value);
                                   ^~~~~~~~~~~~~~~~~~~~~
/../lib/gcc/x86_64-redhat-linux/4.9.2/../../../../include/c++/4.9.2/ext/numeric_traits.h:52:15: note: expanded from macro '__glibcxx_max'
    (((((_Tp)1 << (__glibcxx_digits(_Tp) - 1)) - 1) << 1) + 1) : ~(_Tp)0)
        ~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~

I extracted the command line produced by the FixedCompilationDatabase and printed it with quotes for extra paranoia:

'clang-tool' '-Wall' '-std=c++11' '-fcolor-diagnosticsoo' '/home/peter/Programming/llvm/llvm/tools/clang/tools/extra/quaff/dummy.cc'

First thing to observe is that -fcolor-diagnosticsoo seems a bit weird. Second is that running clang++ -Wall -std=c++11 /home/peter/Programming/llvm/llvm/tools/clang/tools/extra/quaff/dummy.cc doesn't error.

This is on a fedora box, if that makes a difference.

Does the error go away with ‘-fcolor-diagnostics’ instead of ‘-fcolor-diagnosticsoo’? If it does, then maybe ‘-fcolor-diagnosticsoo’ is generating an error that is not being handled correctly in the tool.

– Sean Silva

It doesn't, unfortunately (I had subsequently figured out where it was creeping in from).

Although the errors don’t look like it, could it be something like: http://clang.llvm.org/docs/FAQ.html#i-get-errors-about-some-headers-being-missing-stddef-h-stdarg-h ?

– Sean Silva

Some tests that I've done:

First to investigate what is said by -v:

[peter@fred llvm]$ which clang++
~/Programming/unix-built/clang/bin/clang++
[peter@fred llvm]$ clang++ -v
clang version 3.7.0 (trunk 233281)
Target: x86_64-unknown-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.9.2
Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.9.2
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64

[peter@fred llvm]$ which quaff
~/Programming/unix-built/clang/bin/quaff
[peter@fred llvm]$ quaff -- -v
clang version 3.7.0 (trunk 233281)
Target: x86_64-unknown-linux-gnu
Thread model: posix
Found candidate GCC installation: /../lib/gcc/x86_64-redhat-linux/4.9.2
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.9.2
Selected GCC installation: /../lib/gcc/x86_64-redhat-linux/4.9.2
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64

/lib is a symlink to /usr/lib, so there is really only one installation, but I'm not sure why they don't use the same list, either both should have one candidate, or both should have two.

I then tried (with only failure to show for it) a bunch of combinations of -isystem, and -I for the directory

/home/peter/Programming/unix-built/clang/lib/clang/3.7.0/include/

Which should be the right path for the builtin includes, since I use the install prefix

/home/peter/Programming/unix-built/clang/

  (The contents certainly looks right)

Any further suggestions?

Yeah, looks like the resource dir issue isn’t it (btw you can pass the -resource-dir option instead of -I in order to precisely match the behavior, but -I is usually enough).

The problem appears to be due to __gnu_cxx::__numeric_traits_integer being instantiated with a floating point type… can you look at that code path to see how it is getting there? Maybe it is relying on a particular compiler intrinsic that clang is not treating the same as GCC (or doesn’t support?)?

– Sean Silva

This is at the outer limits of my understanding of templates, but if I comment out the following

   inline string
   to_string(float __val)
{
     const int __n =
       __gnu_cxx::__numeric_traits<float>::__max_exponent10 + 20;
     return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
         "%f", __val);
}

   inline string
   to_string(double __val)
{
     const int __n =
       __gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
     return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
         "%f", __val);
}

   inline string
   to_string(long double __val)
{
     const int __n =
       __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 20;
     return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
         "%Lf", __val);
   }

Then the errors go away.

pre.cc (355 KB)

Looks like a bug in this:

template
struct __numeric_traits
: public __conditional_type<std::__is_integer<_Value>::__value,
__numeric_traits_integer<_Value>,
__numeric_traits_floating<_Value> >::__type
{ };

Which causes __numeric_traits_integer<_Value> to be evaluated with a floating point type (which is the error you’re seeing). std::conditional doesn’t “short circuit” (see e.g. http://stackoverflow.com/questions/24098278/stdconditional-compile-time-branch-evaluation )

That would suggest that this code would always trigger this issue… but I’m curious how this works with clang++ standalone, but not with the tool.

– Sean Silva

Might clang++ be suppressing the errors because they come from system headers?

Might clang++ be suppressing the errors because they come from system
headers?

Clang wouldn't suppress errors. Warnings yes, but errors no.

-- Sean Silva

I also have this issue with to_string(float/double/long double), and for
me assert() in ActOnFinishFunctionBody() failed, but this was because I
ignore errors (After
DiagnosticsEngine::{Reset(),setIgnoreAllWarnings()}, using ASTConsumer):

And I wrote a patch and a regression:
http://reviews.llvm.org/D8458 # patch for ParseExpr.cpp
http://reviews.llvm.org/D8457 # regression test