diff options
author | Sean Hunt <scshunt@csclub.uwaterloo.ca> | 2011-05-12 06:15:49 +0000 |
---|---|---|
committer | Sean Hunt <scshunt@csclub.uwaterloo.ca> | 2011-05-12 06:15:49 +0000 |
commit | e4246a633b13197634225971b25df0cbdcec0c5d (patch) | |
tree | f917d93ad86bce728cf83fb00b6b29937d3c24ed /lib/Parse/ParseDeclCXX.cpp | |
parent | 1e23865d0e148a3951a9b418e57b7e0762dc3098 (diff) |
Properly parse the 'default' and 'delete' keywords.
They are actually grammatically considered definitions and parsed
accordingly.
This fixes the outstanding bugs regarding defaulting functions after
their declarations.
We now really nicely diagnose the following construct (try it!)
int foo() = delete, bar;
Still todo: Defaulted functions other than default constructors
Test cases (including for the above construct)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131228 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index ecf66a79db..91b55d5b58 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1614,10 +1614,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SkipUntil(tok::comma, true, true); } + bool IsDefinition = false; // function-definition: - if (Tok.is(tok::l_brace) - || (DeclaratorInfo.isFunctionDeclarator() && - (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) { + if (Tok.is(tok::l_brace)) { + IsDefinition = true; + } else if (DeclaratorInfo.isFunctionDeclarator()) { + if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) { + IsDefinition = true; + } else if (Tok.is(tok::equal)) { + const Token &KW = NextToken(); + if (KW.is(tok::kw_default) || KW.is(tok::kw_delete)) + IsDefinition = true; + } + } + + if (IsDefinition) { if (!DeclaratorInfo.isFunctionDeclarator()) { Diag(Tok, diag::err_func_def_no_params); ConsumeBrace(); @@ -1644,9 +1655,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS, Init); - // Consume the optional ';' - if (Tok.is(tok::semi)) + + // Consume the ';' - it's optional unless we have a delete or default + if (Tok.is(tok::semi)) { ConsumeToken(); + } return; } @@ -1658,8 +1671,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, llvm::SmallVector<Decl *, 8> DeclsInGroup; ExprResult BitfieldSize; - bool Deleted = false; - SourceLocation DefaultLoc; while (1) { // member-declarator: @@ -1687,14 +1698,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::equal)) { ConsumeToken(); if (Tok.is(tok::kw_delete)) { - if (!getLang().CPlusPlus0x) - Diag(Tok, diag::warn_deleted_function_accepted_as_extension); - ConsumeToken(); - Deleted = true; + if (DeclaratorInfo.isFunctionDeclarator()) + Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) + << 1 /* delete */; + else + Diag(ConsumeToken(), diag::err_deleted_non_function); } else if (Tok.is(tok::kw_default)) { - if (!getLang().CPlusPlus0x) - Diag(Tok, diag::warn_defaulted_function_accepted_as_extension); - DefaultLoc = ConsumeToken(); + if (DeclaratorInfo.isFunctionDeclarator()) + Diag(Tok, diag::err_default_delete_in_multiple_declaration) + << 1 /* delete */; + else + Diag(ConsumeToken(), diag::err_default_special_members); } else { Init = ParseInitializer(); if (Init.isInvalid()) @@ -1722,9 +1736,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Decl *ThisDecl = 0; if (DS.isFriendSpecified()) { - if (DefaultLoc.isValid()) - Diag(DefaultLoc, diag::err_default_special_members); - // TODO: handle initializers, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, /*IsDefinition*/ false, @@ -1734,9 +1745,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DeclaratorInfo, move(TemplateParams), BitfieldSize.release(), - VS, Init.release(), - /*IsDefinition*/Deleted, - Deleted, DefaultLoc); + VS, Init.release(), false); } if (ThisDecl) DeclsInGroup.push_back(ThisDecl); @@ -1762,8 +1771,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, VS.clear(); BitfieldSize = 0; Init = 0; - Deleted = false; - DefaultLoc = SourceLocation(); // Attributes are only allowed on the second declarator. MaybeParseGNUAttributes(DeclaratorInfo); |