[cfe-dev] Attempt 2 at CXX Namespaces

Steve Naroff snaroff at apple.com
Mon Feb 25 15:04:56 PST 2008


I don't believe namespace are a "ScopedDecl".

For now, I suggest NamespaceDecl inherits from Decl (like  
LinkageSpecDecl).

snaroff

On Feb 25, 2008, at 2:52 PM, Kevin Tew wrote:

> I've tried to incorporate both Chris and your suggestions.
>
> Kevin
> Eli Friedman wrote:
>> On Mon, Feb 25, 2008 at 11:32 AM, Kevin Tew <tewk at cs.utah.edu> wrote:
>>
>>> I've gotten serious and have written some code.
>>>
>>> Following the clang web page's advice, I've tried to start  
>>> implementing
>>> c++ namespaces.
>>> Currently, I'm trying to figure out how to add namespace members  
>>> to my
>>> NamespaceDecl.
>>>
>>
>> Hmm, not a bad start.  A couple of comments from reading your patch.
>> First, make sure you don't go over 80 characters per line.  Second, I
>> don't think that making NamespaceDecl a subclass of RecordDecl really
>> makes sense: a namespace doesn't have members in the same sense  
>> that a
>> class or struct does.  Maybe make it a direct subclass of ScopedDecl?
>> Also, a few more tests might be appropriate.
>>
>> Doesn't necessarily need to be done in this patch, but it would be
>> nice if the places that print out namespaced identifiers (like dump()
>> and related) would print out the associated namespace, so that things
>> don't get so confusing.
>>
>> Also, here's a testcase which I'm not sure your patch handles:
>> namespace a { double i; }
>> int i;
>> namespace a {double* j = &i;}
>> should not print a warning with -pedantic.
>>
>> I can't really come up with any other tests that have to do with
>> namespaces in particular... namespaces are pretty simple without
>> "using" and the :: operator.
>>
>> -Eli
>>
>
> Index: test/Parser/cxx-namespace.cpp
> ===================================================================
> --- test/Parser/cxx-namespace.cpp	(revision 0)
> +++ test/Parser/cxx-namespace.cpp	(revision 0)
> @@ -0,0 +1,13 @@
> +// RUN: clang -fsyntax-only -verify %s
> +int intone;
> +namespace one {
> +  namespace two {
> +    namespace three {
> +      int intone;
> +    }
> +  }
> +}
> +
> +namespace a { double i; }
> +int i;
> +namespace a {double* j = &i;}
> Index: include/clang/AST/Decl.h
> ===================================================================
> --- include/clang/AST/Decl.h	(revision 47574)
> +++ include/clang/AST/Decl.h	(working copy)
> @@ -60,6 +60,7 @@
>     //           RecordDecl,
>                    Struct,
>                    Union,
> +                   Namespace,
>                    Class,
>     //       ValueDecl
>                EnumConstant,
> @@ -771,6 +772,19 @@
>   friend Decl* Decl::Create(llvm::Deserializer& D);
> };
>
> +/// NamespaceDecl - Represents a cxx namespace .  For example:
> +//.   namespace X { };
> +/// This decl will be marked invalid if *any* members are invalid.
> +///
> +class NamespaceDecl : public ScopedDecl {
> +
> +public:
> +  NamespaceDecl(SourceLocation L, IdentifierInfo *Id,  
> ScopedDecl*PrevDecl)
> +    : ScopedDecl(Decl::Namespace, L, Id, PrevDecl) {
> +    assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
> +  }
> +};
> +
> class FileScopeAsmDecl : public Decl {
>   StringLiteral *AsmString;
> public:
> Index: include/clang/Parse/Action.h
> ===================================================================
> --- include/clang/Parse/Action.h	(revision 47574)
> +++ include/clang/Parse/Action.h	(working copy)
> @@ -122,6 +122,16 @@
>   virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group) {
>     return Group;
>   }
> +
> +  virtual DeclTy *ActOnStartOfNamespace(Scope *NamespaceScope,
> +                                        SourceLocation NameLoc,
> +                                        IdentifierInfo *Name,  
> DeclTy *Attr) {
> +    return 0;
> +  }
> +
> +  virtual DeclTy *ActOnFinishNamespace(DeclTy *Decl) {
> +    return Decl;
> +  }
>
>   /// ActOnStartOfFunctionDef - This is called at the start of a  
> function
>   /// definition, instead of calling ActOnDeclarator.  The  
> Declarator includes
> @@ -303,7 +313,7 @@
>     return 0;
>   }
>   virtual StmtResult ActOnAsmStmt(SourceLocation AsmLoc,
> -                                  bool IsSimple,
> +                                  bool IsSimple,
>                                   bool IsVolatile,
>                                   unsigned NumOutputs,
>                                   unsigned NumInputs,
> Index: Sema/Sema.h
> ===================================================================
> --- Sema/Sema.h	(revision 47574)
> +++ Sema/Sema.h	(working copy)
> @@ -195,6 +195,9 @@
>
>   virtual DeclTy *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
>   virtual void ObjCActOnStartOfMethodDef(Scope *S, DeclTy *D);
> +  virtual DeclTy *ActOnStartOfNamespace(Scope *NamespaceScope,
> +                                        SourceLocation NameLoc,
> +                                        IdentifierInfo *Name,  
> DeclTy *Attr);
>
>   virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtTy *Body);
>   virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc,  
> SourceLocation LBrace,
> @@ -256,7 +259,7 @@
>   /// The raw attribute contains 1 argument, the id of the address  
> space
>   /// for the type.
>   QualType HandleAddressSpaceTypeAttribute(QualType curType,
> -                                           AttributeList *rawAttr);
> +                                           AttributeList *rawAttr);
>
>   // HandleVectorTypeAttribute - this attribute is only applicable to
>   // integral and float scalars, although arrays, pointers, and  
> function
> @@ -775,7 +778,7 @@
>   // returns true if the cast is invalid
>   bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty);
>
> -  // returns true if there were any incompatible arguments.
> +  // returns true if there were any incompatible arguments.
>   bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
>                                  ObjCMethodDecl *Method);
>
> Index: Sema/SemaDecl.cpp
> ===================================================================
> --- Sema/SemaDecl.cpp	(revision 47574)
> +++ Sema/SemaDecl.cpp	(working copy)
> @@ -1972,3 +1972,11 @@
>
>   d->addAttr(new AlignedAttr(Align));
> }
> +
> +Sema::DeclTy *Sema::ActOnStartOfNamespace(Scope *NamespaceScope,
> +                                          SourceLocation NameLoc,
> +                                          IdentifierInfo *Name,  
> DeclTy *Attr) {
> +  NamespaceDecl* ND = new NamespaceDecl(NameLoc, Name, 0);
> +  return ND;
> +}
> +
> Index: AST/Decl.cpp
> ===================================================================
> --- AST/Decl.cpp	(revision 47574)
> +++ AST/Decl.cpp	(working copy)
> @@ -28,6 +28,7 @@
> static unsigned nEnumConst = 0;
> static unsigned nEnumDecls = 0;
> static unsigned nTypedef = 0;
> +static unsigned nNamespace = 0;
> static unsigned nFieldDecls = 0;
> static unsigned nInterfaceDecls = 0;
> static unsigned nClassDecls = 0;
> @@ -186,6 +187,9 @@
>
> void Decl::addDeclKind(const Kind k) {
>   switch (k) {
> +    case Namespace:
> +      nNamespace++;
> +      break;
>     case Typedef:
>       nTypedef++;
>       break;
> Index: Driver/ASTConsumers.cpp
> ===================================================================
> --- Driver/ASTConsumers.cpp	(revision 47574)
> +++ Driver/ASTConsumers.cpp	(working copy)
> @@ -40,6 +40,7 @@
>     void PrintDecl(Decl *D);
>     void PrintFunctionDeclStart(FunctionDecl *FD);
>     void PrintTypeDefDecl(TypedefDecl *TD);
> +    void PrintNamespaceDecl(NamespaceDecl *ND);
>     void PrintLinkageSpec(LinkageSpecDecl *LS);
>     void PrintObjCMethodDecl(ObjCMethodDecl *OMD);
>     void PrintObjCImplementationDecl(ObjCImplementationDecl *OID);
> @@ -92,6 +93,9 @@
>     PrintObjCCompatibleAliasDecl(OID);
>   } else if (isa<ObjCClassDecl>(D)) {
>     Out << "@class [printing todo]\n";
> +  } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) {
> +    Out << "Read top-level tag decl: '" << ND->getName() << "'\n";
> +    PrintNamespaceDecl(ND);
>   } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
>     Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
>   } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
> @@ -160,6 +164,12 @@
>   Out << "typedef " << S << ";\n";
> }
>
> +void DeclPrinter::PrintNamespaceDecl(NamespaceDecl *ND) {
> +  std::string S = ND->getName();
> +  //ND->getUnderlyingType().getAsStringInternal(S);
> +  Out << "namespace " << S << ";\n";
> +}
> +
> void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) {
>   const char *l;
>   if (LS->getLanguage() == LinkageSpecDecl::lang_c)
> Index: Parse/ParseDeclCXX.cpp
> ===================================================================
> --- Parse/ParseDeclCXX.cpp	(revision 47574)
> +++ Parse/ParseDeclCXX.cpp	(working copy)
> @@ -62,6 +62,9 @@
>     // FIXME: parse this.
>   } else if (Tok.is(tok::l_brace)) {
>     SourceLocation LBrace = ConsumeBrace();
> +    EnterScope(Scope::DeclScope);
> +    DeclTy *Res = Actions.ActOnStartOfNamespace(CurScope, IdentLoc,  
> Ident,
> +                                                AttrList);
>     // FIXME: push a scope, push a namespace decl.
>
>     while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
> @@ -70,8 +73,11 @@
>     }
>
>     SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
> -
> +    ExitScope();
> +
>     // FIXME: act on this.
> +    Actions.ActOnFinishNamespace(Res);
> +    return Res;
>   } else {
>     unsigned D = Ident ? diag::err_expected_lbrace :
>                          diag::err_expected_ident_lbrace;
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev




More information about the cfe-dev mailing list