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