using declarations

Hi,

I’ve been experimenting with an implementation for using declarations that I’d like to bounce off you, to make sure I’m going down the right path. I’ve enclosed a patch of the current changes, in case you want to use them now. These are a high-level description of the key changes/additions so far:

  1. Create a new decl class, UsingAliasDecl, derived form NamedDecl, mainly storing a pointer to the target decl.

  2. Add parsing code to Parser::ParseUsingDeclaration. (Note: the ‘typename’ keyword is parsed, but the semantic actions elsewhere don’t support type using decls. No attempt to parse the ‘concept’ stuff yet)

  3. Handle parsing using declarations in classes (Parser::ParseCXXClassMemberDeclaration).

  4. Define and implement Action::ActOnUsingDeclaration (both MinimalAction.cpp and SemaDeclCXX.cpp).

  5. Where the declared using identifier is used in expressions (i.e. Sema::ActOnDeclarationNameExpr), substitute the target decl, i.e.:

if (UsingAliasDecl *UsingAlias = dyn_cast(D))
D = UsingAlias->getTargetDecl();

  1. For the case of global or member functions with the same name as the using declaration, in the semantic action functions dealing with same-named functions, don’t match a using declaration. I’m hoping it doesn’t matter if the using decl hides a previous declaration of the same name.

Question: Is the UsingAliasDecl class the right way to go, and is the name okay?

Question: When encountering a name corresponding to a using declaration in an expression, is just substituting the target declaration okay? I’m worried that losing the semantic information about an identifier in a statement or expression corresponding to a using declaration might be an issue. But just substituting the target decl makes for simpler code so far.

I’m writing a cxx-using-declaration.cpp test file, which will later have examples from the C++ standard draft or comparible ones. I’ve enclosed the simple non-error case version I’ve used so far. While I’m waiting for feedback, I’ll work on adding more test cases, and getting the ‘using typename’ to work.

using_decl_experimental.patch (16.9 KB)

cxx-using-declaration.cpp (497 Bytes)

Hello John,

I've been experimenting with an implementation for using declarations that I'd like to bounce off you, to make sure I'm going down the right path. I've enclosed a patch of the current changes, in case you want to use them now. These are a high-level description of the key changes/additions so far:

1. Create a new decl class, UsingAliasDecl, derived form NamedDecl, mainly storing a pointer to the target decl.

2. Add parsing code to Parser::ParseUsingDeclaration. (Note: the 'typename' keyword is parsed, but the semantic actions elsewhere don't support type using decls. No attempt to parse the 'concept' stuff yet)

3. Handle parsing using declarations in classes (Parser::ParseCXXClassMemberDeclaration).

4. Define and implement Action::ActOnUsingDeclaration (both MinimalAction.cpp and SemaDeclCXX.cpp).

5. Where the declared using identifier is used in expressions (i.e. Sema::ActOnDeclarationNameExpr), substitute the target decl, i.e.:

  if (UsingAliasDecl *UsingAlias = dyn_cast<UsingAliasDecl>(D))
    D = UsingAlias->getTargetDecl();
6. For the case of global or member functions with the same name as the using declaration, in the semantic action functions dealing with same-named functions, don't match a using declaration. I'm hoping it doesn't matter if the using decl hides a previous declaration of the same name.

Question: Is the UsingAliasDecl class the right way to go, and is the name okay?

Yes, I think it's the right way to go, and the name is fine.

Question: When encountering a name corresponding to a using declaration in an expression, is just substituting the target declaration okay? I'm worried that losing the semantic information about an identifier in a statement or expression corresponding to a using declaration might be an issue. But just substituting the target decl makes for simpler code so far.

I think this is the right thing to do, but I suspect that we should do this substitution of the target declaration much sooner, e.g., as part of name lookup (in SemaLookup.cpp) when we are not looking for a redeclaration.

I'm writing a cxx-using-declaration.cpp test file, which will later have examples from the C++ standard draft or comparible ones. I've enclosed the simple non-error case version I've used so far. While I'm waiting for feedback, I'll work on adding more test cases, and getting the 'using typename' to work.

Great! Some more detailed review follows.

Index: tools/clang/include/clang/AST/DeclCXX.h

Oh, and we might even consider storing the list of declarations that the using declaration refers to, because we need to model the semantics of paragraph 11:

  The entity declared by a using-declaration shall be known in the context using it according to its definition
at the point of the using-declaration . Definitions added to the namespace after the using-declaration are not
considered when a use of the name is made.

  - Doug

Douglas Gregor wrote:

Hello John,

Question: When encountering a name corresponding to a using
declaration in an expression, is just substituting the target
declaration okay? I'm worried that losing the semantic information
about an identifier in a statement or expression corresponding to a
using declaration might be an issue. But just substituting the
target decl makes for simpler code so far.
    
I think this is the right thing to do, but I suspect that we should do
this substitution of the target declaration much sooner, e.g., as part
of name lookup (in SemaLookup.cpp) when we are not looking for a
redeclaration.

But we cannot do this for C++0x-style type aliases with the using
keyword. We should probably build a different declaration for those
anyway, but I feel the name UsingAliasDecl is slightly misleading in
this case. Why not just UsingDecl?

Sebastian

Douglas Gregor wrote:

Hello John,

Question: When encountering a name corresponding to a using
declaration in an expression, is just substituting the target
declaration okay? I'm worried that losing the semantic information
about an identifier in a statement or expression corresponding to a
using declaration might be an issue. But just substituting the
target decl makes for simpler code so far.

I think this is the right thing to do, but I suspect that we should do
this substitution of the target declaration much sooner, e.g., as part
of name lookup (in SemaLookup.cpp) when we are not looking for a
redeclaration.

But we cannot do this for C++0x-style type aliases with the using
keyword.

Right. We'll want to handle those like typedefs.

We should probably build a different declaration for those
anyway, but I feel the name UsingAliasDecl is slightly misleading in
this case. Why not just UsingDecl?

Fine by me.

  - Doug

Thanks Doug! I’m afraid I’m still putting out some fires elsewhere, but I hope to get back to Clang soon and revise per the feedback.