[cfe-dev] [PATCH]: Sema support for C++ classes

Chris Lattner clattner at apple.com
Fri Jun 27 16:45:22 PDT 2008


On Jun 25, 2008, at 9:49 AM, Argiris Kirtzidis wrote:

> Hi,
>
> The attached patch adds the missing Sema support for parsing C++  
> classes.
>
> About references to instance fields:
>
> +      // FIXME: Use DeclRefExpr or a new Expr for a direct CXXField  
> reference.
> +      ExprResult ThisExpr = ActOnCXXThis(Loc);
> +      return new MemberExpr(static_cast<Expr*>(ThisExpr.Val),
> +                            true, FD, Loc, FD->getType());
>
> I'll fix this once Sema support is in place.

Ok!  One meta question: the PushDeclContext/pop context logic has to  
keep the CurMethodDecl members up to date, and are somewhat complex.   
Would it be better to change direct accesses to CurMethodDecl to call  
getCurMethodDecl(), which would just look at the current context?



+DIAG(err_member_initialization, ERROR,
+    "'%0' can be initialized only if it is a static const integral  
data member")

How about "can only be initialized if..."


+DIAG(err_invalid_this_at_top_level, ERROR,
+     "invalid use of 'this' at top level")

How about "outside of a member function"?  It would also subsume  
err_invalid_this_in_non_member_func

Are methods in C++ officially known as "member functions" or "methods"?


+++ lib/Sema/Sema.h	(working copy)

+  /// CXXFieldCollector - Used to keep track of CXXFieldDecls during  
parsing of
+  /// C++ classes.
+  class {

Instead of nesting this inside the sema class, please pull this out to  
its own header (or put in SemaUtil.h).  The sema class is already very  
large, which means it is hard to understand "at a glance".  Also, it  
is probably best for Sema to have a pointer (e.g. an OwningPtr) to the  
instance instead of having it inline.  This allows it to be lazily  
created and helps keep sizeof(Sema) reasonable.


+    llvm::SmallVector<CXXFieldDecl*, 32> Fields;
+    llvm::SmallVector<size_t, 4> FieldCount;

Please comment what these are and what invariants hold.

+    /// getNumField - The number of fields added to the currently  
parsed class.
+    size_t getNumField() const { return FieldCount.back(); }

"getNumFields"?


+    /// StartClass - Called by Sema::ActOnFinishCXXClassDef.
+    void FinishClass() {

plz update comment.


+    assert(isa<CXXMethodDecl>(FD) || CurFunctionDecl == 0
+           && "Confused parsing.");

You need parens here.


+    if (getLangOptions().CPlusPlus)
+      New = CXXRecordDecl::Create(Context, Kind, CurContext, Loc,  
Name, 0);
+    else
+      New = RecordDecl::Create(Context, Kind, CurContext, Loc, Name,  
0);


Is it hopeless to use the "light weight recorddecl" for "simple enough  
structs" even in C++?

+  if (getLangOptions().CPlusPlus) {
+    NewFD = CXXFieldDecl::Create(Context,  
cast<CXXRecordDecl>(CurContext),
+                                 Loc, II, T, BitWidth);
+    PushOnScopeChains(NewFD, S);
+  }
+  else
+    NewFD = FieldDecl::Create(Context, Loc, II, T, BitWidth);

likewise.



+++ lib/Sema/SemaExprCXX.cpp	(working copy)
@@ -49,3 +49,21 @@
+
+Action::ExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) {
+  /// C++ 9.3.2: In the body of a non-static member function, the  
keyword this is

80 col violation


+++ lib/Sema/SemaExpr.cpp	(working copy)

+      if (MD->isStatic())
+        // "invalid use of member 'x' in static member function"
+        return Diag(Loc,  
diag::err_invalid_member_use_in_static_method, FD->getName());
+      if (cast<CXXRecordDecl>(MD->getParent()) != FD->getParent())

likewise.

===================================================================
--- lib/Sema/SemaDeclCXX.cpp	(revision 52718)
+++ lib/Sema/SemaDeclCXX.cpp	(working copy)

in Sema::ActOnStartCXXClassDef and:

+void Sema::ActOnFinishCXXClassDef(DeclTy *D,SourceLocation RBrace) {
+  Decl *Dcl = static_cast<Decl *>(D);
+  CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(Dcl);
+  assert(RD && "Invalid parameter, expected CXXRecordDecl");
+  CXXFieldCollector.FinishClass();
+  PopDeclContext();
+}

Instead of using dyn_cast_or_null + assert(not null), just use cast<>


+Sema::DeclTy *
+Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,  
Declarator &D,


+  assert(II && "No identifier ?");

does this abort on unnamed bitfields like "int : 4;" ?



+  CXXClassMemberWrapper MW(Member);
+  MW.setAccess(AS);
+

What does this do?  I had to look this up, it is somewhat strange.  At  
the least, how about:

// What this does and why we can't just call Member->setAccess(..)
CXXClassMemberWrapper(Member).setAccess(AS);


Otherwise, this looks great Argiris!

-Chris




More information about the cfe-dev mailing list