Support the use of decltype for specifying base types. Fixes PR11216.
llvm-svn: 142926
This commit is contained in:
parent
9a8f13961c
commit
00ee7a081d
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue