Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
| From | Daniel Krügler <daniel.kruegler@googlemail.com> |
|---|---|
| Newsgroups | comp.std.c++ |
| Subject | Re: constants vs. ODR |
| Date | 2011-05-06 13:07 -0600 |
| Organization | A noiseless patient Spider |
| Message-ID | <ipva4o$aph$1@dont-email.me> (permalink) |
| References | <ipa3hd$1si1$1@news.ett.com.ua> <ipcd9c$3tu$1@dont-email.me> <iph2fg$19ns$1@news.ett.com.ua> |
Am 01.05.2011 18:14, schrieb Balog Pal:
>
> [identical repost after 40 hours]
> "Daniel Krügler"<daniel.kruegler@googlemail.com>
>> Am 28.04.2011 20:19, schrieb Balog Pal:
>>>
>>> If I have the following in a header:
>>>
>>> const int NUM = 42;
>>> inline void foo(const int&) { ... } // could be template, etc
>>> inline void bar()
>>> {
>>> foo(NUM);
>>> }
>>>
>>> If I understand correctly, by the current standard this will break the
>>> one
>>> definition rule, if the header is included in multiple translation
>>> units.
>>> Because of the const hack that makes it static, so NUM will really be
>>> different in every TU, therefore bar() will have non-identical
>>> definitions.
>>> Placing the program in UB land.
>>
>> — in each definition of D, corresponding names, looked up according to
>> 3.4, shall refer to an entity defined within the definition of D, or
>> shall refer to the same entity, after overload resolution (13.3) and
>> after matching of partial template specialization (14.8.3), except that
>> a name can refer to a const object with internal or no linkage if the
>> object has the same literal type in all definitions of D, and the object
>> is initialized with a constant expression (5.19), and the value (but not
>> the address) of the object is used, and the object has the same value in
>> all definitions of D;"
>
> At the end it says "and the value (but not the address) of the object is
> used".
> What is teh meaning of "used" there? I interpreted it as "taken". The
> function foo gets the argument by reference, that for me means taking (and
> "using") its address.
>
> If that is not really so, and taking the address this way is not use, it
> should better be expressed in the standard.
No, you are right, I did not recognize the actual problem, because I
concentrated on foo and it's argument, and not on bar().
>> You are not showing us any content of the body of foo(), so we don't
>> know whether foo() might violate the ODR when referring to it's function
>> argument. If foo would be written like this:
>
> This remark quite implies that taking the address to do the function
> call is
> not use, and the body is relevant. IMO that is far from obvious if so.
>
> If I look the code with compiler/code generator's eyes, foo will have code
> identical as if it were foo(const int *). And call to foo will generate
> code
> equivalent to passing&NUM. Resulting different bodies in all TUs. If the
> compiler does not do actual inlining, that is allowed, there's not much
> choice of other ways.
Yep.
>> #include<iostream>
>>
>> const int NUM = 42;
>> inline void foo(const int& arg) { std::cout<< &arg<< std::endl; }
>> inline void bar() { foo(NUM); }
>>
>> it would violate the ODR, yes. The same could happen for an analogously
>> written function bar_2() as follows:
>>
>> #include<iostream>
>>
>> const int NUM_2 = 42;
>> inline void bar_2() { std::cout<< &NUM_2<< std::endl; }
>>
>>> My question is whether this was fixed for C++0x?
>>
>> What do you want to have fixed?
>
> If my original interpretation is correct, then we don't need to use&
> explicitly, still have the ODR on very common cases, especially for
> templates, where taking arguments by const reference is the norm. That
> should not be so.
>
> If the provided interpretation is correct, and inside the function only the
> value is really used without explicit taking of the address, then I'd like
> to have a note or example with code like above stating it shal not worry on
> the user side (and certainly be looked after by implementation).
Unfortunately your problem is real and probably not easy to fix.
> The real world implementations I saw for inline use COMDEFs or __selectany
> for the function body, meaning the code is generated into all objects. Then
> the linker will use a random piece. By ODR they must be sufficiently
> identical, if not it is UB anyway.
>
> I'm thinking of an ill case from the above scenario. Let's change NUM's
> initializer to a function call.
OK, now we have no longer a constant expression, you mean?
> int ret_42(); // defined in a single TU as {return 42;}
> const int NUM = ret_42();
> inline void foo(const int& arg) { std::cout<< arg<< std::endl; }
> inline void bar() { foo(NUM); }
>
> Will bar print always 42? What if it is called before main(), during
> initialization of namespace variables? If every function used its "own"
> body, then NUM is initialized before that and have its value properly.
>
> But if it used the selectany method, the executing body could use
> address of
> NUM from another TU, one that will have that variable initialized only
> after
> my call -- printing 0.
>
> If using the value is what the standard really means, the implementation
> will need some extra measures to have it.
No, unfortunately it really refers to an address and this address is
indirectly used in bar(). Funny things can now also happen e.g. with
non-type templates, because as of C++0x it is now possible that these
are initialized with objects that have internal linkage, so this would
now be allowed to instantiate:
template<const int& R>
struct Ref {
[..]
};
const int NUM = 42;
inline void bar() { Ref<NUM> r; } // Is now possible...
and it would silently break the ODR similar to your original example.
So, yes, the problem in your original example is real and probably also
quite hard to solve correctly.
Greetings from Bremen,
Daniel Krügler
--
[ comp.std.c++ is moderated. To submit articles, try posting with your ]
[ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to comp.std.c++ | Previous | Next — Previous in thread | Find similar
constants vs. ODR "Balog Pal" <pasa@lib.hu> - 2011-04-28 12:19 -0600
Re: constants vs. ODR Johannes Schaub<schaub.johannes@googlemail.com> - 2011-04-28 15:47 -0600
Re: constants vs. ODR Daniel Krügler<daniel.kruegler@googlemail.com> - 2011-04-28 15:46 -0600
Re: constants vs. ODR "Balog Pal"<pasa@lib.hu> - 2011-05-01 10:14 -0600
Re: constants vs. ODR Johannes Schaub <schaub.johannes@googlemail.com> - 2011-05-01 12:52 -0600
Re: constants vs. ODR Daniel Krügler <daniel.kruegler@googlemail.com> - 2011-05-06 13:07 -0600
csiph-web