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

Enea Zaffanella zaffanella at cs.unipr.it
Fri Aug 3 23:18:36 PDT 2012


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?

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?

Enea.




More information about the cfe-dev mailing list