[cfe-dev] The DeclContext of block-scope function declarations.

Douglas Gregor dgregor at apple.com
Mon Aug 6 08:21:03 PDT 2012


On Aug 3, 2012, at 11:18 PM, Enea Zaffanella <zaffanella at cs.unipr.it> wrote:

> On 08/01/2012 07:09 PM, Douglas Gregor wrote:
> >
> > On Jul 9, 2012, at 1:57 AM, Enea Zaffanella <zaffanella at cs.unipr.it> wrote:
> >
> >> Consider the following program:
> >>
> >> $ cat block.cc
> >> namespace N {
> >>
> >> void f() {
> >>    extern int var;     // #1
> >>    extern void g(int); // #2
> >>    g(var);
> >> }
> >>
> >> class S {
> >>    friend void h();    // #3
> >> };
> >>
> >> } // namespace N
> >>
> 
> [...]
> 
> > This is a longstanding [*] problem in Clang's representation. The
> lexical DeclContext should be the function for #1 and #2, while the
> semantic DeclContext should be the nearest enclosing namespace. Ideally,
> name lookup for redeclarations (but not uses) would then be able to find
> these functions, so that in
> >
> > namespace N {
> >    void f() {
> >      extern int var; #1
> >    }
> >
> >    extern int var; // #2
> >
> >    void g() {
> >      extern int var; // #3
> >    }
> > }
> >
> > #1, #2, and #3 would all end up in the same redeclaration chain. That doesn't happen now.
> >
> >
> >
> > 	- Doug
> >
> > [*] Block-scope function declarations and extern variables predate the introduction of DeclContexts!
> 
> 
> Summarizing, the declaration of the local extern entity should be:
> 
> (a) visible when looked up for redeclaration purposes
>    in its lexical context;
> 
> (b) visible when looked up for redeclaration purposes
>    in its enclosing namespace (i.e., semantic context);
> 
> (c) visible when looked up for uses in its lexical context;
> 
> (d) *not* visible when looked up for uses in its enclosing
>    namespace (i.e., semantic context).
> 
> 
> Currently, we have (a) and (c), but not (b) nor (d).
> 
> By changing the semantic DeclContext to be the nearest enclosing namespace, we will get properties (a) and (b), but we won't obtain properties (c) and (d).
> 
> As for (c), maybe
>  DeclContext::makeDeclVisibleinContext(NamedDecl*)
> is a viable solution?

Yes.

> And then what about (d)?
> 
> Should we use another flag in the Decl::IdentifierNamespace enumeration (e.g., IDNS_LocalExtern) mimicking what was done for IDNS_OrdinaryFriend, but with its own specific visibility rules?
> Are there simpler approaches?

I *think* the best approach is to generalize the idea behind IDNS_OrdinaryFriend, because friends have the same visibility properties as local externs. The new IDNS_OrdinaryHidden (or whatever) would be found be redeclaration lookup for ordinary names, but not by normal name lookup for ordinary names.

	- Doug



More information about the cfe-dev mailing list