summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-08-12 00:22:39 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-08-12 00:22:39 +0000
commit3d1a94c6a63692541896a42388a4c08efbd59959 (patch)
tree4640bb1eebc86f5d6516c4a72817efc4ba0383da /clang/lib/Parse/ParseDeclCXX.cpp
parent3ae6e1528a29a0c717d2f2c6a63e9dcb67731cd7 (diff)
downloadbcm5719-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.cpp25
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 {
OpenPOWER on IntegriCloud