4

This code behaves surprising on Clang. Is there a bug in Clang, or are gcc and MSVC++ wrong? Or is the behaviour undefined?:

typedef set<int> A;
typedef map<int,A> B;
B gcctest;
A def;

A const& get(int key)
{
    B::const_iterator j = gcctest.find(key);
    if (j != gcctest.end())
        return j->second;
    return def;
}

int main()
{
    def.insert(1);
    int t = 47;
    gcctest[t] = get(t);
    cerr << (gcctest[t].size() ? "gcc or msvc++" : "clang") << endl;
}

It seems Clang inserts a default constructed element in my map before calling get. This does not happen if A is a simple type, e.g. int.

on GCC and MSVC++++ it prints gcc or msvc++. On clang in prints clang.

GCC on linux version 4.6.3

Clang on MacOS Xcode 5.0.2

MSVC++ on Windows VS2012

(PS: please help me with a better title for this question.)

XPlatformer
  • 1,148
  • 8
  • 18
  • 3
    How exactly does clang differ from MSVC++ and GCC on this specific code? You commented on the apparent action the code clang generates takes, but never mentioned a word about the other implementations. (and these do the same thing on my rigs, so dunno what you're seeing as output). – WhozCraig Nov 22 '13 at 20:08
  • on gcc and msvc++ it prints `gcc or msvc++`. On clang in prints `clang` – XPlatformer Nov 22 '13 at 20:15
  • 1
    @WhozCraig, it is clear in the code. The code prints the compiler name based on the behaviour and I see different output with g++ and clang++. – perreal Nov 22 '13 at 20:16
  • Ah.ok. If you're talking about what I think you are, you're seeing a side-effect of the lvalue-reference resolution of `gcctest[t]` on the left side of the assignment prior to the `get` invoke. Is that correct ? (and I have an older clang, which probably explains why I'm not seeing what you are). – WhozCraig Nov 22 '13 at 20:17
  • yes, exactly what I wanted to say. – XPlatformer Nov 22 '13 at 20:19
  • @crashmstr it isn't that. the lvalue resolution of the assignment op is taking place *before* the invoke to `get`, which then finds the value inserted by that resolution rather then returning the default due to lookup failure. Is that about right, user3001464 ? – WhozCraig Nov 22 '13 at 20:20
  • all compilers I have available (sun, ibm, and a gcc on ibm) print "clang", but it should be obvious by now that it's just another indeterminately-sequenced (not undefined!) expression – Cubbi Nov 22 '13 at 20:21
  • @sharth That link is pretty much spot-on with what I think is being seen here. – WhozCraig Nov 22 '13 at 20:22
  • @WhozCraig: Also, I can duplicate this with the following compilers gcc 4.6.3 (linux, libstdc++ 4.6.3), gcc 4.8.1 (linux, libstdc++ 4.8.1), clang 3.3 (linux, libstdc++ 4.8.1) and clang (os x 10.9, libc++) – Bill Lynch Nov 22 '13 at 20:23
  • @sharth well wtf is wrong with my clang then, because it apparently does the same thing the gcc and mcvc on this question do. Its from Xcode 5.0 (I haven't upgraded to 5.0.2 yet), with devtools et'al. weird. – WhozCraig Nov 22 '13 at 20:24
  • @WhozCraig: It's always possible that the behavior is different on different version of clang. On linux, clang 3.0, 3.1, 3.2 and 3.3 all report "clang". The OS X releases are not usually a llvm release though, so it's hard to see if I can reproduce your result. Either way, it's just unspecified so it's not a big deal that your env is different. – Bill Lynch Nov 22 '13 at 20:50

1 Answers1

2

When you use the subscript operator on a std::map<K, T> it finds the element and, if the element is not present, inserts one. Thus, depending on whether the left-hand side or the right-hand side of

gcctest[t] = get(t);

is evaluated first, you'll get different results. The result of the program is, however, just unspecified.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380