Using clang to parse C++ on Windows

Hi,

I’ve gotten stuck on a weird error message from Clang. I’m writing a Clang-based tool to analyze legacy C++ source code. The code relies heavily on Windows-specific headers files (MFC, etc) and I have never been able to get Clang to properly parse MS own header files. Running the tool on Linux works fine; I’ve created a set of dummy replacement header files which are complete enough to allow Clang to build a usable AST for me. However, running the tool on Windows turns out to be more difficult than I thought.

I’ve tried several approaches as to what header files should be used. Clang was never able to get through the MS header files without crashing or producing various errors. Since the tool worked fine on Linux, I imagined that it should be possible to use Linux header files instead. This got me pretty far, but now I’ve gotten stuck on an error which I cannot make sense of.

$ clang -fno-ms-extensions -D_GNU_SOURCE -c foo.cpp -isystem ./linux-glibc/include -isystem ./linux-glibc/include/c++/4
.7 -isystem ./linux-glibc/include/c++/4.7/bits -isystem linux-glibc/include/c++/4.7/x86_64-linux-gnu
In file included from foo.cpp:1:
In file included from ./linux-glibc/include/c++/4.7\vector:63:
In file included from ./linux-glibc/include/c++/4.7\bits/stl_construct.h:63:
In file included from ./linux-glibc/include/c++/4.7\ext/alloc_traits.h:35:
./linux-glibc/include/c++/4.7\bits/alloc_traits.h:56:35: error: in-class initializer for static data member is not a
constant expression
static const bool __value = _S_chk<_Alloc, _Tp>(nullptr);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./linux-glibc/include/c++/4.7\bits/alloc_traits.h:63:19: note: in instantiation of template class
‘std::__alloctr_rebind_helper<std::allocator, int>’ requested here
bool = __alloctr_rebind_helper<_Alloc, _Tp>::__value>
^
./linux-glibc/include/c++/4.7\bits/alloc_traits.h:201:9: note: in instantiation of default argument for
‘__alloctr_rebind<std::allocator, int>’ required here
using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;
^~~~~
./linux-glibc/include/c++/4.7\ext/alloc_traits.h:183:47: note: in instantiation of template type alias ‘rebind_alloc’
requested here
{ typedef typename _Base_type::template rebind_alloc<_Tp> other; };
^
./linux-glibc/include/c++/4.7\bits/stl_vector.h:75:59: note: in instantiation of template class
‘__gnu_cxx::__alloc_traits<std::allocator >::rebind’ requested here
typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
^
./linux-glibc/include/c++/4.7\bits/stl_vector.h:208:30: note: in instantiation of template class 'std::_Vector_base<int,

std::allocator >’ requested here
class vector : protected _Vector_base<_Tp, _Alloc>
^
foo.cpp:2:18: note: in instantiation of template class ‘std::vector<int, std::allocator >’ requested here
std::vector foo;
^

foo.cpp is a really simple source file which looks like this:

// foo.cpp
#include
std::vector foo;
// end

The “linux-glibc/include” is a pretty large directory containing the entire /usr/include directory from my Linux machine.

Compiling the same program on Linux works fine. I’ve compared the include file order, preprocessor symbols, and the list of options being passed to the compiler driver (‘clang -v … foo.cpp’), and I cannot find anything significant which is different. (Some things are naturally different; for example Clang on Windows is compiling 32-bit binaries, while my Linux-Clang is building 64-bit ones).

Are there other internal differences between Clang when run on Windows vs. Linux which may account for this?

Not sure if it helps your specific case, but you do need to patch gcc 4.7's libstdc++ before you can use it with clang.

http://clang.llvm.org/libstdc++4.7-clang11.patch

  - ½

Hm. On Linux the same (unpatched) header file works fine. Can this cause problem on Windows even if it works on Linux?

Hi,

I've gotten stuck on a weird error message from Clang. I'm writing a
Clang-based tool to analyze legacy C++ source code. The code relies heavily
on Windows-specific headers files (MFC, etc) and I have never been able to
get Clang to properly parse MS own header files. Running the tool on Linux
works fine; I've created a set of dummy replacement header files which are
complete enough to allow Clang to build a usable AST for me. However,
running the tool on Windows turns out to be more difficult than I thought.

I've tried several approaches as to what header files should be used.
Clang was never able to get through the MS header files without crashing or
producing various errors. Since the tool worked fine on Linux, I imagined
that it should be possible to use Linux header files instead. This got me
pretty far, but now I've gotten stuck on an error which I cannot make sense
of.

$ clang -fno-ms-extensions -D_GNU_SOURCE -c foo.cpp -isystem
./linux-glibc/include -isystem ./linux-glibc/include/c++/4
.7 -isystem ./linux-glibc/include/c++/4.7/bits -isystem
linux-glibc/include/c++/4.7/x86_64-linux-gnu
In file included from foo.cpp:1:
In file included from ./linux-glibc/include/c++/4.7\vector:63:
In file included from
./linux-glibc/include/c++/4.7\bits/stl_construct.h:63:
In file included from ./linux-glibc/include/c++/4.7\ext/alloc_traits.h:35:
./linux-glibc/include/c++/4.7\bits/alloc_traits.h:56:35: error: in-class
initializer for static data member is not a
      constant expression
      static const bool __value = _S_chk<_Alloc, _Tp>(nullptr);
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

At a guess, clang is implicitly running in -fdelayed-template-parsing mode,
and this is failing because _S_chk<...> is a constexpr function template
specialization that has not been parsed yet. That's a bug that was fixed
recently.

What target triple is clang using? IIRC we only turn on
-fdelayed-template-parsing in MSVC-compatibility mode, but it looks like
you're going for something more like a mingw target. (libstdc++ probably
won't work in MSVC-compatibility mode.)

    Hi,

    I've gotten stuck on a weird error message from Clang. I'm writing a
    Clang-based tool to analyze legacy C++ source code. The code relies
    heavily on Windows-specific headers files (MFC, etc) and I have
    never been able to get Clang to properly parse MS own header files.
    Running the tool on Linux works fine; I've created a set of dummy
    replacement header files which are complete enough to allow Clang to
    build a usable AST for me. However, running the tool on Windows
    turns out to be more difficult than I thought.

    I've tried several approaches as to what header files should be
    used. Clang was never able to get through the MS header files
    without crashing or producing various errors. Since the tool worked
    fine on Linux, I imagined that it should be possible to use Linux
    header files instead. This got me pretty far, but now I've gotten
    stuck on an error which I cannot make sense of.

    $ clang -fno-ms-extensions -D_GNU_SOURCE -c foo.cpp -isystem
    ./linux-glibc/include -isystem ./linux-glibc/include/c++/4
    .7 -isystem ./linux-glibc/include/c++/4.7/bits -isystem
    linux-glibc/include/c++/4.7/x86_64-linux-gnu
    In file included from foo.cpp:1:
    In file included from ./linux-glibc/include/c++/4.7\vector:63:
    In file included from
    ./linux-glibc/include/c++/4.7\bits/stl_construct.h:63:
    In file included from
    ./linux-glibc/include/c++/4.7\ext/alloc_traits.h:35:
    ./linux-glibc/include/c++/4.7\bits/alloc_traits.h:56:35: error:
    in-class initializer for static data member is not a
          constant expression
          static const bool __value = _S_chk<_Alloc, _Tp>(nullptr);
                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

At a guess, clang is implicitly running in -fdelayed-template-parsing
mode, and this is failing because _S_chk<...> is a constexpr function
template specialization that has not been parsed yet. That's a bug that
was fixed recently.

What target triple is clang using? IIRC we only turn on
-fdelayed-template-parsing in MSVC-compatibility mode, but it looks like
you're going for something more like a mingw target. (libstdc++ probably
won't work in MSVC-compatibility mode.)

i686-pc-win32. Also, I'm specifying -fdelayed-template-parsing explicitly in order to get some of the legacy C++ sources through the parser.

I managed to get around this by brutally removing the initialization in alloc_traits.h. Since I have my own copy of the header files, this is ok for me at the moment. At some point, however, it would be nice if clang could just use Microsofts own header files.

Thanks!

What's broken currently? I'm aware of some known broken things like
atlwin.h, but the STL headers should parse.

You'd probably need the full set of flags that clang-cl passes down to
clang -cc1, which includes things like -fms-extensions -fms-compatibility
-fdelayed-template-parsing -cxx-abi microsoft. I don't *think* the C++ ABI
matters for parsing, but I'd have to double check. There are many other
fun flags that can help too, like -fno-rtti, -fno-exceptions,
-D_HAS_EXCEPTIONS=0, and so on.