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

Douglas Gregor dgregor at apple.com
Wed Aug 1 10:09:41 PDT 2012


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
> 
> 
> Function N::f() declares extern function `g(int)' and int object `var'.
> In the AST generated by clang, these two block-scope declarations have 
> function N::f() as their (semantic and lexical) DeclContext.
> 
> However, C++11 3.5p7 says:
> 
>   "When a block scope declaration of an entity with linkage is not
>    found to refer to some other declaration, then that entity is a
>    member of the innermost enclosing namespace. However such a
>    declaration does not introduce the member name in its
>    namespace scope."
> 
> This seems to suggest that both `g(int)' and `var' should have namespace 
> N as their semantic DeclContext (but be "hidden" there), while still 
> having f() as their lexical DeclContext. That is, things should be (more 
> or less) similar to the case of friend function h() in class S.
> 
> As an example where this DeclContext issue matters, when calling method
> 
>    NamedDecl::getQualifiedNameAsString()
> 
> on the three declarations we obtain:
> 
>    #1  var     // wrong, should be N::var
>    #2  g       // wrong, should be N::g
>    #3  N::h    // correct
> 
> We would appreciate if someone could confirm the issue and diagnosis 
> above, as well as hinting at the places in Sema that need to be modified 
> to obtain the correct behavior.

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!



More information about the cfe-dev mailing list