diff options
author | Corentin Jabot <corentinjabot@gmail.com> | 2022-01-27 13:55:08 +0100 |
---|---|---|
committer | Corentin Jabot <corentinjabot@gmail.com> | 2023-10-02 14:33:02 +0200 |
commit | af4751738db89a142a8880c782d12d4201b222a8 (patch) | |
tree | b58f2c515b189904f4b598a06f0af0e642343b2c /clang/lib/Parse/ParseDecl.cpp | |
parent | bc7d88faf1a595ab59952a2054418cdd0d9eeee8 (diff) | |
download | llvm-af4751738db89a142a8880c782d12d4201b222a8.zip llvm-af4751738db89a142a8880c782d12d4201b222a8.tar.gz llvm-af4751738db89a142a8880c782d12d4201b222a8.tar.bz2 |
[C++] Implement "Deducing this" (P0847R7)
This patch implements P0847R7 (partially),
CWG2561 and CWG2653.
Reviewed By: aaron.ballman, #clang-language-wg
Differential Revision: https://reviews.llvm.org/D140828
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 9bda4ec..a149159 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5835,8 +5835,7 @@ bool Parser::isDeclarationSpecifier( bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, DeclSpec::FriendSpecified IsFriend, const ParsedTemplateInfo *TemplateInfo) { - TentativeParsingAction TPA(*this); - + RevertingTentativeParsingAction TPA(*this); // Parse the C++ scope specifier. CXXScopeSpec SS; if (TemplateInfo && TemplateInfo->TemplateParams) @@ -5845,7 +5844,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, /*ObjectHasErrors=*/false, /*EnteringContext=*/true)) { - TPA.Revert(); return false; } @@ -5857,7 +5855,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, } else if (Tok.is(tok::annot_template_id)) { ConsumeAnnotationToken(); } else { - TPA.Revert(); return false; } @@ -5867,7 +5864,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, // Current class name must be followed by a left parenthesis. if (Tok.isNot(tok::l_paren)) { - TPA.Revert(); return false; } ConsumeParen(); @@ -5876,7 +5872,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, // that we have a constructor. if (Tok.is(tok::r_paren) || (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren))) { - TPA.Revert(); return true; } @@ -5885,7 +5880,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier(/*Disambiguate*/ false, /*OuterMightBeMessageSend*/ true)) { - TPA.Revert(); return true; } @@ -5906,9 +5900,17 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, // If we parsed a scope specifier as well as friend, // we might be parsing a friend constructor. bool IsConstructor = false; - if (isDeclarationSpecifier(IsFriend && !SS.isSet() - ? ImplicitTypenameContext::No - : ImplicitTypenameContext::Yes)) + ImplicitTypenameContext ITC = IsFriend && !SS.isSet() + ? ImplicitTypenameContext::No + : ImplicitTypenameContext::Yes; + // Constructors cannot have this parameters, but we support that scenario here + // to improve diagnostic. + if (Tok.is(tok::kw_this)) { + ConsumeToken(); + return isDeclarationSpecifier(ITC); + } + + if (isDeclarationSpecifier(ITC)) IsConstructor = true; else if (Tok.is(tok::identifier) || (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) { @@ -5977,8 +5979,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, break; } } - - TPA.Revert(); return IsConstructor; } @@ -7356,6 +7356,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList( /// '=' assignment-expression /// [GNU] declaration-specifiers abstract-declarator[opt] attributes /// [C++11] attribute-specifier-seq parameter-declaration +/// [C++2b] attribute-specifier-seq 'this' parameter-declaration /// void Parser::ParseParameterDeclarationClause( DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs, @@ -7420,9 +7421,16 @@ void Parser::ParseParameterDeclarationClause( SourceLocation DSStart = Tok.getLocation(); + // Parse a C++23 Explicit Object Parameter + // We do that in all language modes to produce a better diagnostic. + SourceLocation ThisLoc; + if (getLangOpts().CPlusPlus && Tok.is(tok::kw_this)) + ThisLoc = ConsumeToken(); + ParseDeclarationSpecifiers(DS, /*TemplateInfo=*/ParsedTemplateInfo(), AS_none, DeclSpecContext::DSC_normal, /*LateAttrs=*/nullptr, AllowImplicitTypename); + DS.takeAttributesFrom(ArgDeclSpecAttrs); // Parse the declarator. This is "PrototypeContext" or @@ -7436,6 +7444,9 @@ void Parser::ParseParameterDeclarationClause( : DeclaratorContext::Prototype); ParseDeclarator(ParmDeclarator); + if (ThisLoc.isValid()) + ParmDeclarator.SetRangeBegin(ThisLoc); + // Parse GNU attributes, if present. MaybeParseGNUAttributes(ParmDeclarator); if (getLangOpts().HLSL) @@ -7505,7 +7516,8 @@ void Parser::ParseParameterDeclarationClause( } // Inform the actions module about the parameter declarator, so it gets // added to the current scope. - Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator); + Decl *Param = + Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, ThisLoc); // Parse the default argument, if any. We parse the default // arguments in all dialects; the semantic analysis in // ActOnParamDefaultArgument will reject the default argument in |