Support the use of decltype for specifying base types. Fixes PR11216.

llvm-svn: 142926
This commit is contained in:
David Blaikie 2011-10-25 15:01:20 +00:00
parent 9a8f13961c
commit 00ee7a081d
3 changed files with 61 additions and 11 deletions

View File

@ -1993,7 +1993,6 @@ private:
//===--------------------------------------------------------------------===//
// 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 @@ private:
//===--------------------------------------------------------------------===//
// C++ 10: Derived classes [class.derived]
TypeResult ParseBaseTypeSpecifier(SourceLocation &EndLocation,
CXXScopeSpec &SS);
void ParseBaseClause(Decl *ClassDecl);
BaseResult ParseBaseSpecifier(Decl *ClassDecl);
AccessSpecifier getAccessSpecifierIfPresent() const;

View File

@ -696,18 +696,23 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
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,6 +733,17 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
// Fall through to produce an error below.
}
if (Tok.is(tok::kw_decltype)) {
// Fake up a Declarator to use with ActOnTypeName.
DeclSpec DS(AttrFactory);
ParseDecltypeSpecifier(DS);
EndLocation = DS.getSourceRange().getEnd();
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_class_name);
return true;
@ -1363,9 +1379,9 @@ void Parser::ParseBaseClause(Decl *ClassDecl) {
/// 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 +1419,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
// Parse the class-name.
SourceLocation EndLocation;
TypeResult BaseType = ParseClassName(EndLocation, SS);
TypeResult BaseType = ParseBaseTypeSpecifier(EndLocation, SS);
if (BaseType.isInvalid())
return true;

View File

@ -0,0 +1,33 @@
// 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}}
template<typename T>
struct Derived3 : decltype(T().foo()) { };
struct Foo { Base foo(); };
Derived3<Foo> d;
}