[cfe-dev] using declaration questions

Douglas Gregor dgregor at apple.com
Thu Jun 18 07:56:23 PDT 2009


On Jun 17, 2009, at 6:55 PM, John Thompson wrote:

> Hi Doug,
>
> I've been working on using declarations a bit over the last week,  
> amidst continued fire-fighting elsewhere, butI thought I'd better  
> address some parts of it in pieces, rather than in a big unwieldy  
> chunk.  Rather than a patch, I'll just list relevent pieces to  
> discuss, as I have questions about the code.  I hope it formats in a  
> readable way here.
>
>
> We'll probably want to store more location information, e.g., the  
> source range covering the nested-name-specifier, (e.g., "N::M::"),  
> the source location of the target declaration's name, and the source  
> location of the "using" itself. Also, how about keeping track of the  
> NestedNameSpecifier used to refer to the target declaration? It's  
> good for pretty-printing, and will also be needed when the using  
> directive occurs within a template and the nested-name-specifier is  
> dependent.
>
> I was a litte fuzzy about the exact meaning of these, but here's my  
> best guess.  First the new renamed UsingDecl:
>
> /// UsingDecl - Represents C++ using-directive. For example:
> /// using someNameSpace::someIdentifier;
>
> class UsingDecl : public NamedDecl {
>     /// \brief The source range that covers the nested-name-specifier
>     /// preceding the namespace name.
>     SourceRange NestedNameRange;

Typo: "preceding the *declaration* name."

>     /// \brief The source location of the target declaration name.
>     SourceLocation TargetNameLocation;
>     /// \brief The source location of the "using" location itself.
>     SourceLocation UsingLocation;
>     /// \brief Target declaration.
>     NamedDecl* TargetDecl;
>     /// \brief Target declaration.
>     NestedNameSpecifier* TargetNestedNameDecl;

This is often called the "qualifier" of  a qualified name (in the AST).

>     // Had 'typename' keyword.
>     bool IsTypeName;
>     UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
>             SourceLocation TargetNL, SourceLocation UL, NamedDecl*  
> Target,
>             NestedNameSpecifier* TargetNNS, bool IsTypeNameArg)
>         : NamedDecl(Decl::Using, DC, L, Target->getDeclName()),
>             NestedNameRange(NNR), TargetNameLocation(TargetNL),
>             UsingLocation(UL), TargetDecl(Target),
>             TargetNestedNameDecl(TargetNNS),  
> IsTypeName(IsTypeNameArg) { }
> public:\
>     /// \brief Returns the source range that covers the nested-name- 
> specifier
>     /// preceding the namespace name.
>     SourceRange getNestedNameRange() { return(NestedNameRange); }
>     /// \brief Returns the source location of the target declaration  
> name.
>     SourceLocation getTargetNameLocation() { return     
> (TargetNameLocation); }
>     /// \brief Returns the source location of the "using" location  
> itself.
>     SourceLocation getUsingLocation() { return(UsingLocation); }
>     /// \brief getTargetDecl - Returns target specified by using-decl.
>     NamedDecl *getTargetDecl() { return(TargetDecl); }
>     /// \brief Get target nested name declaration.
>     NestedNameSpecifier* getTargetNestedNameDecl()  
> { return(TargetNestedNameDecl); }
>     /// \brief isTypeName - Return true if using decl had 'typename'.
>     bool isTypeName() const { return(IsTypeName); }
>
>     static UsingDecl *Create(ASTContext &C, DeclContext *DC,
>         SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
>         SourceLocation UL, NamedDecl* Target,
>         NestedNameSpecifier* TargetNNS, bool IsTypeNameArg);
>
>     static bool classof(const Decl *D) {
>             return D->getKind() == Decl::Using;
>         }
>     static bool classof(const UsingDecl *D) { return true; }
> };

This looks right to me.
> Regarding the later comment:
>
> 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.
>
> I'm not sure what list of declarations is needed.  If later  
> definitions appear, it seems that a look up will find the using  
> declaration first, and return the refered-to declaration.  Or does  
> this have something to do with overloading?
>
Yes, it's for overloading. It will work as-is, because TargetDecl can  
be an OverloadedFunctionDecl, but in the longer term I'd like to  
eliminate OverloadedFunctionDecl.

> The additional source locations are handled in ActOnUsingDeclaration  
> like:
>
>
>     UsingAlias = UsingDecl::Create(Context, CurContext, IdentLoc,  
> SS.getRange(),
>         NS->getLocation(), UsingLoc, NS,
>         static_cast<NestedNameSpecifier *>(SS.getScopeRep()),
>         IsTypeName);
> Does this seem right?
>
Yes.

> Lastly, do you think Sema::LookupParsedName is the right place to do  
> the substitution for non-redeclaration lookups?  Or should it be  
> lower in LookupName, with more conditions to exclude certain lookup  
> types?
>
> I'll be experimenting with this next, as well as writing a bigger  
> test, to ring out some of the trickier cases.
>
Okay. If you'd like to submit a patch with just parsing + AST, then  
tackle semantic analysis as a separate step, that'd be fine.

	- Doug
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20090618/a78bd8bd/attachment.html>


More information about the cfe-dev mailing list