Open rjmccall opened 14 years ago
Note that Chris's example only applies to inline definitions, where the ODR constrains both the tokens and the identity of the declarations referenced within the definition. Also note that non-ODR uses of const non-volatile internal objects of literal type with constant initializers are a (quite) specific exception to the rule.
I'd be kindof concerned about actually applying that rule, since nobody else does it, and since it's quite easy to make a spurious ODR use (canonical example: passing an argument to a forwarding function template that takes a const T& / T&&). But we might be able to be carefully broaden the exception enough to stay out of trouble.
We handle all the items in comment#0, but not the case in comment#1.
This is mostly implemented here:
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20100201/027083.html
See the laundry list at the end of the commit message for the bits that aren't done.
It goes beyond that, if an anonymous decl is referenced in any inline function definition, it should also be anonymous:
namespace { int x; }
inline int foo() { return x; }
int bar() { return foo(); }
'foo' can't be referenced outside the translation unit due to ODR. llvm-gcc gives it linkonce linkage, but giving it internal linkage would be better.
Extended Description
The current implementation of anonymous namespaces gives private linkage to all entities semantically contained in an anonymous namespace. This is conservative; I claim we can extend this to all "anonymous" objects, where an object is anonymous iff:
1) It is declared within an anonymous namespace. 2) It is declared static. 3) It is a class or function template specialization with an anonymous template argument. 4) it is a function with an anonymous argument type.
The rules of C++ forbid such objects from being referenced outside the current translation unit.
In fact, having them be non-private could theoretically cause spurious link errors.