diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-08-12 00:22:39 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-08-12 00:22:39 +0000 |
commit | 3d1a94c6a63692541896a42388a4c08efbd59959 (patch) | |
tree | 4640bb1eebc86f5d6516c4a72817efc4ba0383da /clang/lib/Parse/ParseDeclCXX.cpp | |
parent | 3ae6e1528a29a0c717d2f2c6a63e9dcb67731cd7 (diff) | |
download | bcm5719-llvm-3d1a94c6a63692541896a42388a4c08efbd59959.tar.gz bcm5719-llvm-3d1a94c6a63692541896a42388a4c08efbd59959.zip |
Reject virt-specifiers on friend declarations. Give anonymous bitfields a
location so their diagnostics have somewhere to point.
llvm-svn: 215416
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index f5ce708a97a..d7ed2fa54b4 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1879,12 +1879,22 @@ VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const { /// virt-specifier /// virt-specifier-seq virt-specifier void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, - bool IsInterface) { + bool IsInterface, + SourceLocation FriendLoc) { while (true) { VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(); if (Specifier == VirtSpecifiers::VS_None) return; + if (FriendLoc.isValid()) { + Diag(Tok.getLocation(), diag::err_friend_decl_spec) + << VirtSpecifiers::getSpecifierName(Specifier) + << FixItHint::CreateRemoval(Tok.getLocation()) + << SourceRange(FriendLoc, FriendLoc); + ConsumeToken(); + continue; + } + // C++ [class.mem]p8: // A virt-specifier-seq shall contain at most one of each virt-specifier. const char *PrevSpec = nullptr; @@ -1929,13 +1939,19 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer( // identifier[opt] ':' constant-expression if (Tok.isNot(tok::colon)) ParseDeclarator(DeclaratorInfo); + else + DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation()); if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) { + assert(DeclaratorInfo.isPastIdentifier() && + "don't know where identifier would go yet?"); BitfieldSize = ParseConstantExpression(); if (BitfieldSize.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); } else - ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); + ParseOptionalCXX11VirtSpecifierSeq( + VS, getCurrentClass().IsInterface, + DeclaratorInfo.getDeclSpec().getFriendSpecLoc()); // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { @@ -1954,7 +1970,9 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer( // For compatibility with code written to older Clang, also accept a // virt-specifier *after* the GNU attributes. if (BitfieldSize.isUnset() && VS.isUnset()) { - ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); + ParseOptionalCXX11VirtSpecifierSeq( + VS, getCurrentClass().IsInterface, + DeclaratorInfo.getDeclSpec().getFriendSpecLoc()); if (!VS.isUnset()) { // If we saw any GNU-style attributes that are known to GCC followed by a // virt-specifier, issue a GCC-compat warning. @@ -2319,7 +2337,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, E = Ranges.end(); I != E; ++I) Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I; - // TODO: handle initializers, VS, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, TemplateParams); } else { |