[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