From: David Blaikie Date: Tue, 25 Oct 2011 17:10:12 +0000 (+0000) Subject: Fix cases where the optional nested-name-specifier erroneously preceeded a decltype... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=22216eb4fb0936d2488fc03abd285d135c36ff01;p=clang Fix cases where the optional nested-name-specifier erroneously preceeded a decltype-specification when specifying a base type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142928 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 449d83f7c1..c863e76b9d 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -2012,8 +2012,8 @@ private: //===--------------------------------------------------------------------===// // C++ 10: Derived classes [class.derived] - TypeResult ParseBaseTypeSpecifier(SourceLocation &EndLocation, - CXXScopeSpec &SS); + TypeResult ParseBaseTypeSpecifier(SourceLocation &BaseLoc, + SourceLocation &EndLocation); void ParseBaseClause(Decl *ClassDecl); BaseResult ParseBaseSpecifier(Decl *ClassDecl); AccessSpecifier getAccessSpecifierIfPresent() const; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 9d2db2ae1c..10234ab892 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -711,8 +711,26 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { /// identifier /// simple-template-id /// -Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &EndLocation, - CXXScopeSpec &SS) { +Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, + SourceLocation &EndLocation) { + // Parse decltype-specifier + 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); + } + + // Parse optional nested-name-specifier + CXXScopeSpec SS; + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + + BaseLoc = Tok.getLocation(); + // Check whether we have a template-id that names a type. if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); @@ -733,17 +751,6 @@ Parser::TypeResult Parser::ParseBaseTypeSpecifier(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; @@ -1410,16 +1417,10 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { IsVirtual = true; } - // Parse optional '::' and optional nested-name-specifier. - CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); - - // The location of the base class itself. - SourceLocation BaseLoc = Tok.getLocation(); - // Parse the class-name. SourceLocation EndLocation; - TypeResult BaseType = ParseBaseTypeSpecifier(EndLocation, SS); + SourceLocation BaseLoc; + TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation); if (BaseType.isInvalid()) return true; diff --git a/test/CXX/class.derived/p1.cpp b/test/CXX/class.derived/p1.cpp index 98c1d354fa..dcbe63fd09 100644 --- a/test/CXX/class.derived/p1.cpp +++ b/test/CXX/class.derived/p1.cpp @@ -30,4 +30,8 @@ namespace PR11216 { struct Derived3 : decltype(T().foo()) { }; struct Foo { Base foo(); }; Derived3 d; + + struct Derived4 : :: decltype(Base()) { }; // expected-error {{expected class name}} + + struct Derived5 : PR11216:: decltype(Base()) { }; // expected-error {{expected class name}} }