Here's a fairly non-intrusive fix for PR11216: "Can't derive from a
decltype-specifier" including a couple of test cases & some updated
naming/comments.

Let me know if this looks OK & I'll check it in.
Index: test/CXX/class.derived/p1.cpp
===================================================================
--- test/CXX/class.derived/p1.cpp	(revision 0)
+++ test/CXX/class.derived/p1.cpp	(revision 0)
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11
+
+// base-clause:
+//         : base-specifier-list
+// base-specifier-list:
+//         base-specifier ...[opt]
+//         base-specifier-list , base-specifier ...[opt]
+// base-specifier:
+//         attribute-specifier-seq[opt] base-type-specifier
+//         attribute-specifier-seq[opt] virtual access-specifier[opt] base-type-specifier
+//         attribute-specifier-seq[opt] access-specifier virtual[opt] base-type-specifier
+// class-or-decltype:
+//         nested-name-specifier[opt] class-name
+//         decltype-specifier
+// base-type-specifier:
+//         class-or-decltype
+// access-specifier:
+//         private
+//         protected
+//         public
+
+namespace PR11216 {
+  struct Base { };
+  struct Derived : decltype(Base()) { };
+  int func();
+  struct Derived2 : decltype(func()) { }; // expected-error {{base specifier must name a class}}
+}
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 142895)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -1993,7 +1993,6 @@
 
   //===--------------------------------------------------------------------===//
   // C++ 9: classes [class] and C structs/unions.
-  TypeResult ParseClassName(SourceLocation &EndLocation, CXXScopeSpec &SS);
   void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
                            DeclSpec &DS,
                 const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
@@ -2013,6 +2012,8 @@
 
   //===--------------------------------------------------------------------===//
   // C++ 10: Derived classes [class.derived]
+  TypeResult ParseBaseTypeSpecifier(SourceLocation &EndLocation, 
+                                    CXXScopeSpec &SS);
   void ParseBaseClause(Decl *ClassDecl);
   BaseResult ParseBaseSpecifier(Decl *ClassDecl);
   AccessSpecifier getAccessSpecifierIfPresent() const;
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp	(revision 142895)
+++ lib/Parse/ParseDeclCXX.cpp	(working copy)
@@ -696,18 +696,23 @@
     Diag(StartLoc, DiagID) << PrevSpec;
 }
 
-/// ParseClassName - Parse a C++ class-name, which names a class. Note
-/// that we only check that the result names a type; semantic analysis
-/// will need to verify that the type names a class. The result is
-/// either a type or NULL, depending on whether a type name was
-/// found.
+/// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a
+/// class name or decltype-specifier. Note that we only check that the result 
+/// names a type; semantic analysis will need to verify that the type names a 
+/// class. The result is either a type or null, depending on whether a type 
+/// name was found.
 ///
+///       base-type-specifier: [C++ 10.1]
+///         class-or-decltype
+///       class-or-decltype: [C++ 10.1]
+///         nested-name-specifier[opt] class-name
+///         decltype-specifier
 ///       class-name: [C++ 9.1]
 ///         identifier
 ///         simple-template-id
 ///
-Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
-                                          CXXScopeSpec &SS) {
+Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &EndLocation,
+                                                  CXXScopeSpec &SS) {
   // Check whether we have a template-id that names a type.
   if (Tok.is(tok::annot_template_id)) {
     TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
@@ -728,74 +733,76 @@
     // Fall through to produce an error below.
   }
 
-  if (Tok.isNot(tok::identifier)) {
+  // Fake up a Declarator to use with ActOnTypeName.
+  DeclSpec DS(AttrFactory);
+
+  if (Tok.is(tok::kw_decltype)) {
+    ParseDecltypeSpecifier(DS);    
+  } else if (Tok.isNot(tok::identifier)) {
     Diag(Tok, diag::err_expected_class_name);
     return true;
-  }
+  } else {
+    IdentifierInfo *Id = Tok.getIdentifierInfo();
+    SourceLocation IdLoc = ConsumeToken();
 
-  IdentifierInfo *Id = Tok.getIdentifierInfo();
-  SourceLocation IdLoc = ConsumeToken();
+    if (Tok.is(tok::less)) {
+      // It looks the user intended to write a template-id here, but the
+      // template-name was wrong. Try to fix that.
+      TemplateNameKind TNK = TNK_Type_template;
+      TemplateTy Template;
+      if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(),
+                                               &SS, Template, TNK)) {
+        Diag(IdLoc, diag::err_unknown_template_name)
+          << Id;
+      }
 
-  if (Tok.is(tok::less)) {
-    // It looks the user intended to write a template-id here, but the
-    // template-name was wrong. Try to fix that.
-    TemplateNameKind TNK = TNK_Type_template;
-    TemplateTy Template;
-    if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(),
-                                             &SS, Template, TNK)) {
-      Diag(IdLoc, diag::err_unknown_template_name)
-        << Id;
-    }
+      if (!Template)
+        return true;
 
-    if (!Template)
-      return true;
+      // Form the template name
+      UnqualifiedId TemplateName;
+      TemplateName.setIdentifier(Id, IdLoc);
 
-    // Form the template name
-    UnqualifiedId TemplateName;
-    TemplateName.setIdentifier(Id, IdLoc);
+      // Parse the full template-id, then turn it into a type.
+      if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
+                                  SourceLocation(), true))
+        return true;
+      if (TNK == TNK_Dependent_template_name)
+        AnnotateTemplateIdTokenAsType();
 
-    // Parse the full template-id, then turn it into a type.
-    if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
-                                SourceLocation(), true))
-      return true;
-    if (TNK == TNK_Dependent_template_name)
-      AnnotateTemplateIdTokenAsType();
+      // If we didn't end up with a typename token, there's nothing more we
+      // can do.
+      if (Tok.isNot(tok::annot_typename))
+        return true;
 
-    // If we didn't end up with a typename token, there's nothing more we
-    // can do.
-    if (Tok.isNot(tok::annot_typename))
+      // Retrieve the type from the annotation token, consume that token, and
+      // return.
+      EndLocation = Tok.getAnnotationEndLoc();
+      ParsedType Type = getTypeAnnotation(Tok);
+      ConsumeToken();
+      return Type;
+    }
+
+    // We have an identifier; check whether it is actually a type.
+    ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true,
+                                          false, ParsedType(),
+                                          /*NonTrivialTypeSourceInfo=*/true);
+    if (!Type) {
+      Diag(IdLoc, diag::err_expected_class_name);
       return true;
+    }
 
-    // Retrieve the type from the annotation token, consume that token, and
-    // return.
-    EndLocation = Tok.getAnnotationEndLoc();
-    ParsedType Type = getTypeAnnotation(Tok);
-    ConsumeToken();
-    return Type;
-  }
+    DS.SetRangeStart(IdLoc);
+    DS.SetRangeEnd(IdLoc);
+    DS.getTypeSpecScope() = SS;
 
-  // We have an identifier; check whether it is actually a type.
-  ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true,
-                                        false, ParsedType(),
-                                        /*NonTrivialTypeSourceInfo=*/true);
-  if (!Type) {
-    Diag(IdLoc, diag::err_expected_class_name);
-    return true;
+    const char *PrevSpec = 0;
+    unsigned DiagID;
+    DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type);
   }
 
-  // Consume the identifier.
-  EndLocation = IdLoc;
+  EndLocation = DS.getSourceRange().getEnd();
 
-  // Fake up a Declarator to use with ActOnTypeName.
-  DeclSpec DS(AttrFactory);
-  DS.SetRangeStart(IdLoc);
-  DS.SetRangeEnd(EndLocation);
-  DS.getTypeSpecScope() = SS;
-
-  const char *PrevSpec = 0;
-  unsigned DiagID;
-  DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type);
-
   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
   return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
 }
@@ -1363,9 +1370,9 @@
 ///       base-specifier: [C++ class.derived]
 ///         ::[opt] nested-name-specifier[opt] class-name
 ///         'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
-///                        class-name
+///                        base-type-specifier
 ///         access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
-///                        class-name
+///                        base-type-specifier
 Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
   bool IsVirtual = false;
   SourceLocation StartLoc = Tok.getLocation();
@@ -1403,7 +1410,7 @@
 
   // Parse the class-name.
   SourceLocation EndLocation;
-  TypeResult BaseType = ParseClassName(EndLocation, SS);
+  TypeResult BaseType = ParseBaseTypeSpecifier(EndLocation, SS);
   if (BaseType.isInvalid())
     return true;
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to