[cfe-commits] r142926 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDeclCXX.cpp test/CXX/class.derived/p1.cpp
David Blaikie
dblaikie at gmail.com
Tue Oct 25 08:01:20 PDT 2011
Author: dblaikie
Date: Tue Oct 25 10:01:20 2011
New Revision: 142926
URL: http://llvm.org/viewvc/llvm-project?rev=142926&view=rev
Log:
Support the use of decltype for specifying base types. Fixes PR11216.
Added:
cfe/trunk/test/CXX/class.derived/p1.cpp
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=142926&r1=142925&r2=142926&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Oct 25 10:01:20 2011
@@ -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;
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=142926&r1=142925&r2=142926&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Oct 25 10:01:20 2011
@@ -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,6 +733,17 @@
// 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 @@
/// 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 @@
// Parse the class-name.
SourceLocation EndLocation;
- TypeResult BaseType = ParseClassName(EndLocation, SS);
+ TypeResult BaseType = ParseBaseTypeSpecifier(EndLocation, SS);
if (BaseType.isInvalid())
return true;
Added: cfe/trunk/test/CXX/class.derived/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.derived/p1.cpp?rev=142926&view=auto
==============================================================================
--- cfe/trunk/test/CXX/class.derived/p1.cpp (added)
+++ cfe/trunk/test/CXX/class.derived/p1.cpp Tue Oct 25 10:01:20 2011
@@ -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;
+}
More information about the cfe-commits
mailing list