7

so I think I've done something really stupid and I just can't figure this out. The following program is causing me a lot of pain:

#include <iostream>
int time = 0;
int main(int argc, char **argv) {
    std::cout << "hi" << std::endl;
    return 0;
}

My compile string is: clang++ -std=c++1y --verbose -stdlib=libc++ main.cpp -o main. The redefinition error is /usr/include/time.h:116:8: note: previous definition is here and the --verbose shows me this as the include path order:

Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
 "/Library/Developer/CommandLineTools/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.10.0 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 241.9 -v -resource-dir /Library/Developer/CommandLineTools/usr/bin/../lib/clang/6.0 -stdlib=libc++ -std=c++1y -fdeprecated-macro -fdebug-compilation-dir /Users/aliak/dev/atom/sim -ferror-limit 19 -fmessage-length 0 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.10.0 -fencode-extended-block-signature -fcxx-exceptions -fexceptions -fdiagnostics-show-option -vectorize-slp -o /var/folders/r_/pmd7rtcd4h35dqsf496nyzsh0000gn/T/main-d500bd.o -x c++ /Users/aliak/dev/atom/sim/main.cpp
clang -cc1 version 6.0 based upon LLVM 3.5svn default target x86_64-apple-darwin14.1.0
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
 /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1
 /usr/local/include
 /Library/Developer/CommandLineTools/usr/bin/../lib/clang/6.0/include
 /Library/Developer/CommandLineTools/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)

I just can't figure out what's wrong. If I add in -nostdinc++ to the command line args to clang and then remove the iostream include, but keep the time var, it's all ok. Which I guess means the iostream is including time.h. But I am quite confused, should it not include ctime instead of time.h, which would wrap everything in the std namespace?

I've tried deleting xcode and reinstalling as well.

Update:

The comment from Mats made me do a little bit more snooping. So passing in -H to clang++ prints out the header tree. And it turns out that pthread.h is the one actually including time.h. But ctime also actually includes time.h. And this seems according to the standard because: "In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations"

aliak
  • 428
  • 4
  • 12

1 Answers1

6

time() is a function in standard C, which means that it's living outside a namespace so that "old" C code can be compiled with C++ compilers without having lots of using namespace std thrown in all over the place.

The header time.h is apparently included when you include <iostream>, which is why you get a reference to that.

Either don't use that name, or add namespace MyName { int time; }; and then use MyName::time when you want to refer to your variable.

[I don't know the exact place, but I beleive the C++ standard states that "existing standard library functions may or may not exist outside of the std:: namespace when you include for example <ctime> - the actual implementation of <ctime> does almost certainly include regular <time.h> somewhere.]

For example in the g++ 4.9.2 headers on my linux box:

....
#pragma GCC system_header

#include <bits/c++config.h>
#include <time.h>

#ifndef _GLIBCXX_CTIME
#define _GLIBCXX_CTIME 1

 ...     
namespace std
{
  ...
  using ::time;
  ...
} // namespace

The one in libcxx looks almost identical.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Well, if `` includes ``, it's non-conformant. The same for including ``. – Deduplicator Feb 12 '15 at 00:27
  • Yeah I ended up doing the namespace thing. And aww man you're right about ctime actually including time.h. I still can't understand why though, I thought cname headers were exact copies of name.h headers but in the std namespace. If C code includes time.h it shouldn't be a problem for C++ compilers, but if C++ code wants to use ctime, it should get what it's after. – aliak Feb 12 '15 at 00:28
  • Seems like pthread.h is the culprit with the iostream. You can pass in -H to the compiler and it'll print out the include tree – aliak Feb 12 '15 at 00:31
  • Oh look at this lovely extract: "In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. **It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations**" :( – aliak Feb 12 '15 at 00:32
  • @aliak: What about it? No C header (or C++ header for C standard-library facilities) may be included by any C++ standard header. Though I agree it would be nice if the former guaranteed only to add to global scope and the latter to only add to namespace std... – Deduplicator Feb 12 '15 at 00:38
  • @duplicator: I guess for library implementors as long as the C++ header is conformant, it doesn't matter how it's made. Including a C header or some other random file that does exactly what that C header would've done anyway is irrelevant no? – aliak Feb 12 '15 at 00:46
  • [extern.names]/p3 says that "Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace." @Deduplicator What's non-conforming? [res.on.headers]/p1 says that "A C++ header may include other C++ headers." `` is a C++ header. – T.C. Feb 12 '15 at 02:43
  • @T.C.: Take a look at [res.on.headers]: "1 A C++ header may include other C++ headers. [...] 2 Certain types and macros are defined in more than one header. Every such entity shall be defined such that any header that defines it may be included after any other header that also defines it (3.2). 3 The C standard headers (D.5) shall include only their corresponding C++ standard header, as described in 17.6.1.2." If those headers for C standard library facilities were allowed to be included, paragraph 3 were nonsensical. And your quote does not touch upon which definitions are provided in headers – Deduplicator Feb 12 '15 at 03:17
  • 1
    @Deduplicator The alternative reading is just as nonsensical; it implies that, for instance, no C++ header may include `` for `nullptr_t` or `size_t`. I'm not aware of any implementation that follows that reading. – T.C. Feb 12 '15 at 03:47
  • @T.C.: Implementations ignoring the stadard in this regard would not make it nonsensical. And anyway, this seems not to be the case in e.g. libstdc++. – Deduplicator Feb 12 '15 at 04:08
  • @Deduplicator libstdc++'s ``, for instance, includes ``; its `` includes ``. – T.C. Feb 12 '15 at 04:16
  • @T.C.: Seems I looked in the wrong corner for non-conformancy then, as the headers I checked were ok. – Deduplicator Feb 12 '15 at 04:19
  • @Duplicator: "3 The C standard headers (D.5) shall include only their corresponding C++ standard header, as described in 17.6.1.2." And 17.6.1.2 goes back to the other thing, so it does seem like a correction somewhere is needed. See this too: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html (specifically, defect 456) – aliak Feb 12 '15 at 09:25