[cfe-commits] r65385 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDecl.cpp test/Sema/var-redecl.c test/Sema/vla.c
Douglas Gregor
dgregor at apple.com
Wed Feb 25 10:10:09 PST 2009
On Feb 24, 2009, at 4:30 PM, Eli Friedman wrote:
> On Tue, Feb 24, 2009 at 1:24 PM, Douglas Gregor <dgregor at apple.com>
> wrote:
>>
>> On Feb 24, 2009, at 1:02 PM, Eli Friedman wrote:
>>
>>> On Tue, Feb 24, 2009 at 11:23 AM, Douglas Gregor <dgregor at apple.com>
>>> wrote:
>>>>
>>>> + // FIXME: We don't do this in C++ because, although we would
>>>> like
>>>> + // to get the extra checking that this operation implies,
>>>> + // the declaration itself is not visible according to C++'s
>>>> rules.
>>>
>>> It isn't visible according to C's rules either... what exactly is
>>> the
>>> issue here?
>>
>>
>> The issue is that we want to diagnose cases where there are
>> incompatible
>> declarations even when those declarations aren't necessarily visible.
>
> I follow that, but is C++ different in this regard?
Technically, no. There are other issues that make this both hard to do
and less important in C++.
It's less important because functions aren't implicitly declared in C+
+, so we won't run into the case where a function shows up in a local
scope
void f() {
int otherfunc(int, int);
}
and then gets some (conflicting) implicit declaration later in the file:
void g() {
outerfunc(5);
}
The call inside g() is an error in C++, so the user will see the
problem anyway. Granted, we won't diagnose problems like this in C++:
void f2() {
int otherfunc(int); // conflicts with the declaration of otherfunc
in f
}
C++ has other features that make it hard to do this kind of checking.
In C, it's safe to take locally-declared functions like otherfunc and
"inject" them into the top-level scope (if there isn't anything else
there!), so we find them as a last resort.
In C++, we can't inject them into the top-level scope because they
aren't visible, and we could come up with some weird cases where a
semantically-correct program would fail if we made them visible.
Here's a fun one:
namespace N {
struct X { };
}
void f() {
int outerfunc(N::X);
}
namespace N {
void outerfunc(X);
}
void g(N::X x) {
outerfunc(x); // okay due to argument-dependent lookup
}
At the call inside g, name lookup of "outerfunc" does not find
anything. However, once we have the call arguments, argument-dependent
lookup finds N::outerfunc and calls it.
If we injected f's local declaration of outerfunc into the global
scope (as we do in C), name lookup would find f's outfunc and argument-
dependent lookup would find N::outerfunc. We'd then get a failure in
overload resolution.
I know there are ways around this problem: each namespace (including
the global scope) could have a map from names to "known but non-
visible" declarations within that namespace, and we could check that
as a last resort (e.g., if we're in a case where ADL doesn't work, or
we didn't find anything even with ADL). However, we have bigger fish
to fry in C++-land, so I'm not planning to tackle this now.
- Doug
More information about the cfe-commits
mailing list