From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30398 invoked by alias); 6 Apr 2002 06:30:29 -0000 Mailing-List: contact gdb-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sources.redhat.com Received: (qmail 30390 invoked from network); 6 Apr 2002 06:30:28 -0000 Received: from unknown (HELO dberlin.org) (64.246.6.106) by sources.redhat.com with SMTP; 6 Apr 2002 06:30:28 -0000 Received: from [192.168.1.100] (pool-151-204-251-136.bos.east.verizon.net [151.204.251.136]) (authenticated (0 bits)) by dberlin.org (8.11.6/8.11.6) with ESMTP id g366UQm25178; Sat, 6 Apr 2002 01:30:26 -0500 Subject: Re: C++ nested classes, namespaces, structs, and compound statements From: Daniel Berlin To: Daniel Berlin Cc: Michael Elizabeth Chastain , gdb@sources.redhat.com, jimb@redhat.com, bkoz@redhat.com In-Reply-To: References: Content-Type: text/plain Content-Transfer-Encoding: 7bit Organization: Date: Fri, 05 Apr 2002 22:30:00 -0000 Message-Id: <1018074634.5033.11.camel@danberlin.com> Mime-Version: 1.0 X-SW-Source: 2002-04/txt/msg00078.txt.bz2 > > > - And what about ambiguous member names? > > > > The C++ language spec says: if class A inherits from both class B and > > class C, and both B and C have a member "foo_", then an unqualified > > reference to a.foo_ is illegal. The programmer has to say a::B.foo_ > > or a::C.foo_. > > Not quite. > > Watch this cuteness, copied from the C++ draft standard: > > struct U { static int i; }; > struct V : U { }; > struct W : U { using U::i; }; > struct X : V, W { void foo(); }; > void X::foo() > { > i; //Finds U::i in two ways: as W::i and U::i > // but no ambiguity because U::i is static > > } > > > "A static member, a nested type or an enumerator defined in a base class T > can unambiguously be found even if an object has more than one base class > subobject of type T. Two base class subobjects share the non-static > member subobjects of their common virtual base classes" > > In other words, it's not just statics. > Observe: > > class V { public: int v; }; > class A { > public: > int a; > static int s; > enum { e }; > }; > class B : public A, public virtual V {}; > class C : public A, public virtual V {}; > class D : public B, public C { }; > > void f(D* pd) > { > pd->v++; // ok: only one `v' (virtual) > pd->s++; // ok: only one `s' (static) > int i = pd->e; // ok: only one `e' (enumerator) > pd->a++; // error, ambiguous: two `a's in `D' > } > > > > I forgot to say, in general, you can come up with enough crazy lookup requirements for each language we support/want to support that it just makes sense to have the lookup function (by lookup function I mean whatever you call when you see the "." or "->" to try to get a symbol out of the environment) be a function pointer, filled in by whatever created the environment. For GDB internal symbols (IE $a = 5), we have a simple lookup. For the "global, all enclosing" environment, you probably want a lookup function that figures out the environment of the symbol you are trying to access, and then just looks there. None of these should have to care about what language that environment is, they should just get the "right" answer. I'm saying whatever thing creates the environment and puts symbols in it knows what language these symbols represent, and thus, can best set the lookup function. For the hypothetical mixed language environments (IE you find some way to embed java and C++ in the *same* frame or something, such that you need to install multiple language symbols in a single environment, they really are in the same exact scope), you'd just have an environment with two sub environments, and a lookup function that looked at the current language setting/something else to determine which one to look in first. --Dan