0

I have a source code structured as follows

foo.h (header from c library)

#pragma once
struct foo {...};

bar.h

#pragma once
extern "C" {
   #include "foo.h"
}
class Bar {
  foo val;
  ...
};

bar.cpp

// some Bar methods implementation

user.cpp

#include "bar.h"
...
extern "C" {
   #include "foo.h"
}
...
/* some additional foo usage */

What I expect to happen is that if foo.h included multiple times, #pragma once shall make it so it's included first time only. But what happens is that in bar.h it is not included at all, and include works in user.cpp only. So preprocessor output of user.cpp.i looks somewhat like that:

extern "C" {/* nothing is here, literally empty braces */}
class Bar {
  foo val;
  ...
};
extern "C" {/*actual header content*/}
...
/*the rest of user.cpp content*/

I'd expect foo.h pasted at very first include, but what happens is that struct foo is undefined in bar.h but defined in user.cpp.

I can solve the issue for now by reordering the includes, but why might that happen at all?

UPDATE:

And rearranging includes does nothing. Since bar.cpp still gets no include added by preprocessor.

273K
  • 29,503
  • 10
  • 41
  • 64
Roman
  • 1,396
  • 4
  • 15
  • 39
  • 1
    Put `#include "foo.h"` on a separate line – Paul Sanders Sep 05 '22 at 22:07
  • That's how it is done. I've just saved a couple of lines here in post. I'll reformat it. – Roman Sep 05 '22 at 22:08
  • 1
    Technically, `#` should be the first character of the line, although I doubt this is your problem here. – nickie Sep 05 '22 at 22:10
  • `extern "C"` is C++ feature only, a C compiler will fail, the tag [c] is odd. – 273K Sep 05 '22 at 22:35
  • Take the example out of the context of your actual project, and make it reproducible. Right now there is too much that might be going on in the code lines you are *not* showing us, or what you are showing us is not actually what you are compiling. In short, give us a [mcve]. – DevSolar Sep 05 '22 at 22:39
  • 1
    Random shot in the dark: There are reported situations where #pragma once fails, but standard include guards work. I don't see how those cases could explain what you are reporting, but does switching to include guards change things? – Avi Berger Sep 05 '22 at 22:46
  • I cannot reproduce this; it works correctly for Apple clang version 12.0.0. As `#pragma once` is implementation-defined behaviour, (a) give us a MRE, and (b) which compiler are you using? – nickie Sep 05 '22 at 22:48

1 Answers1

0

So. My set up was: Windows + Wsl. Source code lying on windows host and compiled on wsl. So I was writing with linux in mind and didn't notice that I ended up having c_functionality.h and C_FUNCTIONALITY.h (second one was supposed to be wrapper).

As far as I recall, that wouldn't be an issue on most linux FS'es, since most widely used of them do support case. BUT! Source code is on ntfs.

And GCC won't tell you that you have multiple headers with conflicting names. But clang will.

Roman
  • 1,396
  • 4
  • 15
  • 39