[cfe-dev] C++ PATCH: Basic inheritance syntax, semantics

Chris Lattner clattner at apple.com
Sun Apr 13 13:19:49 PDT 2008


On Apr 13, 2008, at 10:54 AM, Doug Gregor wrote:
> This patch adds very basic support for parsing and type-checking class
> inheritance in C++. It'll parse the base-specifier list, e.g.,
>
>  class D : public B1, virtual public B2 { };

Nice.  One non-technical thing I should mention: Argiris is scheduled  
to implement class-related (methods, instance vars, etc) parsing and  
sema for google summer of code, which should start in a couple(?)  
weeks.  I (as his mentor) have no problem with him working on other  
stuff if he prefers, but you guys should probably sync up so that you  
don't step on each others toes.

> and do some of the simpler semantic checks (B1 and B2 are classes;
> they aren't unions or incomplete types, etc). This patch *does not*
> introduce any representation of base classes into the AST. That (along
> with the semantic checks it enables) will be a follow-on patch.

Sounds good.

> The only interesting part of this patch is that I've completely
> removed Parser::ParseStructUnionSpecifier in favor of the new
> Parser::ParseClassSpecifier. The latter parses C++ class specifiers,
> which are a superset of the C99 struct-or-union-specifier. So there's
> no reason to keep around the C-only ParseStructOrUnionSpecifier.

Makes sense.  Please add a comment that indicates that it is used in C  
though:

+++ include/clang/Parse/Parser.h	(working copy)

+  // 
===-------------------------------------------------------------------- 
===//
+  // C++ 9: classes [class]
+  void ParseClassSpecifier(DeclSpec &DS);

Something like:

+  // C++ 9: classes [class] and C struct/union bodies.

or something.  Also, perhaps ParseStructUnionSpecifier/ 
ParseClassSpecifier should be renamed ParseStructUnionClassSpecifier,  
though that's pretty long :).  ParseSUCSpecifier?



+  AccessSpecifier IsAccessSpecifier();

should be 'const'.  Also, for better or worse, other 'is' predicates  
in Parser (e.g. isDeclarationSpecifier) use a lowercase 'i', please be  
consistent with that.  Also, it's somewhat strange for an 'is' method  
to return something other than bool.  Maybe this should be:  
"getAccessSpecifierIfPresent()" or something like that?



+void Parser::ParseBaseClause(DeclTy *ClassDecl)
+{
+  assert(Tok.is(tok::colon) && "Not a base clause");
+  SourceLocation ColonLoc = ConsumeToken();
+
+  Actions.ActOnBaseClause(ClassDecl, ColonLoc);
+  while (true) {
+    // Parse a base-specifier.
+    if (ParseBaseSpecifier(ClassDecl)) {
...

I know the code is unfinished, but what do you anticipate using  
'ActOnBaseClause' for?  Right now it provides a Loc for the colon to  
sema and does checking for unions.  If we don't currently care about  
the colon loc, would it make sense to do the union check in  
ActOnBaseSpecifier?  It's obviously not a big deal, but one fewer  
action is nice.

+/// ParseBaseSpecifier - Parse a C++ base-specifier.
+///

Please explain a bit more about what a base-specifier is to give quick  
intuition.  This is important for people who aren't fully immersed in  
the grammar but want to understand what the code is doing quickly.   
Something like:

+/// ParseBaseSpecifier - Parse a C++ base-specifier.  base-specifier is
+/// one entry in the base class list of a class specifier, for example:
+///    class foo : public bar, private baz {
+/// 'public bar' and 'private baz' are each base-specifiers.

We don't do this consistently in the parser, but it is very useful  
where we do (for me specifically, I highly value similar comments in  
the ObjC parts ;-)



+  // FIXME: Alternatively, parse a simple-template-id.
+  if (!Tok.is(tok::identifier)) {

Please use:

+  // FIXME: Alternatively, parse a simple-template-id.
+  if (Tok.isNot(tok::identifier)) {

it reads slightly better.

+  // We have an identifier; check whether it is actually a type.
+  if (DeclTy *BaseType = Actions.isTypeName(*Tok.getIdentifierInfo(),
+                                            CurScope)) {
...

To reduce nesting, how about:

+  // We have an identifier; check whether it is actually a type.
+  DeclTy *BaseType = Actions.isTypeName(*Tok.getIdentifierInfo(),  
CurScope);

if (BaseType == 0) {
   error
   return;
}
... handle good case...


+    // Find the complete source range for the base-specifier.
+    // FIXME: Is there a better way to
+    SourceRange Range(StartLoc);
+    unsigned RawSpecifierEnd
+      = Tok.getLocation().getRawEncoding() + Tok.getLength();
+    Range.setEnd(SourceLocation::getFromRawEncoding(RawSpecifierEnd));

You shouldn't need to do this.  The end location of a source range  
actually points to the first character of the last token.  You should  
be good with something like:

   SourceRange Range(StartLoc, Tok.getLocation());

Overall, looks great, please apply with these changes (and after the  
other part gets in of course),

-Chris



More information about the cfe-dev mailing list