1e5dd7070Spatrick //===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements parsing for C++ class inline methods.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick
13e5dd7070Spatrick #include "clang/Parse/Parser.h"
14e5dd7070Spatrick #include "clang/AST/DeclTemplate.h"
15e5dd7070Spatrick #include "clang/Parse/ParseDiagnostic.h"
16e5dd7070Spatrick #include "clang/Parse/RAIIObjectsForParser.h"
17e5dd7070Spatrick #include "clang/Sema/DeclSpec.h"
18e5dd7070Spatrick #include "clang/Sema/Scope.h"
19e5dd7070Spatrick using namespace clang;
20e5dd7070Spatrick
21e5dd7070Spatrick /// ParseCXXInlineMethodDef - We parsed and verified that the specified
22e5dd7070Spatrick /// Declarator is a well formed C++ inline method definition. Now lex its body
23e5dd7070Spatrick /// and store its tokens for parsing after the C++ class is complete.
ParseCXXInlineMethodDef(AccessSpecifier AS,const ParsedAttributesView & AccessAttrs,ParsingDeclarator & D,const ParsedTemplateInfo & TemplateInfo,const VirtSpecifiers & VS,SourceLocation PureSpecLoc)24e5dd7070Spatrick NamedDecl *Parser::ParseCXXInlineMethodDef(
25*12c85518Srobert AccessSpecifier AS, const ParsedAttributesView &AccessAttrs,
26*12c85518Srobert ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo,
27*12c85518Srobert const VirtSpecifiers &VS, SourceLocation PureSpecLoc) {
28e5dd7070Spatrick assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
29e5dd7070Spatrick assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) &&
30e5dd7070Spatrick "Current token not a '{', ':', '=', or 'try'!");
31e5dd7070Spatrick
32e5dd7070Spatrick MultiTemplateParamsArg TemplateParams(
33e5dd7070Spatrick TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data()
34e5dd7070Spatrick : nullptr,
35e5dd7070Spatrick TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
36e5dd7070Spatrick
37e5dd7070Spatrick NamedDecl *FnD;
38e5dd7070Spatrick if (D.getDeclSpec().isFriendSpecified())
39e5dd7070Spatrick FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D,
40e5dd7070Spatrick TemplateParams);
41e5dd7070Spatrick else {
42e5dd7070Spatrick FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,
43e5dd7070Spatrick TemplateParams, nullptr,
44e5dd7070Spatrick VS, ICIS_NoInit);
45e5dd7070Spatrick if (FnD) {
46e5dd7070Spatrick Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs);
47e5dd7070Spatrick if (PureSpecLoc.isValid())
48e5dd7070Spatrick Actions.ActOnPureSpecifier(FnD, PureSpecLoc);
49e5dd7070Spatrick }
50e5dd7070Spatrick }
51e5dd7070Spatrick
52e5dd7070Spatrick if (FnD)
53e5dd7070Spatrick HandleMemberFunctionDeclDelays(D, FnD);
54e5dd7070Spatrick
55e5dd7070Spatrick D.complete(FnD);
56e5dd7070Spatrick
57e5dd7070Spatrick if (TryConsumeToken(tok::equal)) {
58e5dd7070Spatrick if (!FnD) {
59e5dd7070Spatrick SkipUntil(tok::semi);
60e5dd7070Spatrick return nullptr;
61e5dd7070Spatrick }
62e5dd7070Spatrick
63e5dd7070Spatrick bool Delete = false;
64e5dd7070Spatrick SourceLocation KWLoc;
65e5dd7070Spatrick SourceLocation KWEndLoc = Tok.getEndLoc().getLocWithOffset(-1);
66e5dd7070Spatrick if (TryConsumeToken(tok::kw_delete, KWLoc)) {
67e5dd7070Spatrick Diag(KWLoc, getLangOpts().CPlusPlus11
68e5dd7070Spatrick ? diag::warn_cxx98_compat_defaulted_deleted_function
69e5dd7070Spatrick : diag::ext_defaulted_deleted_function)
70e5dd7070Spatrick << 1 /* deleted */;
71e5dd7070Spatrick Actions.SetDeclDeleted(FnD, KWLoc);
72e5dd7070Spatrick Delete = true;
73e5dd7070Spatrick if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
74e5dd7070Spatrick DeclAsFunction->setRangeEnd(KWEndLoc);
75e5dd7070Spatrick }
76e5dd7070Spatrick } else if (TryConsumeToken(tok::kw_default, KWLoc)) {
77e5dd7070Spatrick Diag(KWLoc, getLangOpts().CPlusPlus11
78e5dd7070Spatrick ? diag::warn_cxx98_compat_defaulted_deleted_function
79e5dd7070Spatrick : diag::ext_defaulted_deleted_function)
80e5dd7070Spatrick << 0 /* defaulted */;
81e5dd7070Spatrick Actions.SetDeclDefaulted(FnD, KWLoc);
82e5dd7070Spatrick if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
83e5dd7070Spatrick DeclAsFunction->setRangeEnd(KWEndLoc);
84e5dd7070Spatrick }
85e5dd7070Spatrick } else {
86e5dd7070Spatrick llvm_unreachable("function definition after = not 'delete' or 'default'");
87e5dd7070Spatrick }
88e5dd7070Spatrick
89e5dd7070Spatrick if (Tok.is(tok::comma)) {
90e5dd7070Spatrick Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
91e5dd7070Spatrick << Delete;
92e5dd7070Spatrick SkipUntil(tok::semi);
93e5dd7070Spatrick } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,
94e5dd7070Spatrick Delete ? "delete" : "default")) {
95e5dd7070Spatrick SkipUntil(tok::semi);
96e5dd7070Spatrick }
97e5dd7070Spatrick
98e5dd7070Spatrick return FnD;
99e5dd7070Spatrick }
100e5dd7070Spatrick
101e5dd7070Spatrick if (SkipFunctionBodies && (!FnD || Actions.canSkipFunctionBody(FnD)) &&
102e5dd7070Spatrick trySkippingFunctionBody()) {
103e5dd7070Spatrick Actions.ActOnSkippedFunctionBody(FnD);
104e5dd7070Spatrick return FnD;
105e5dd7070Spatrick }
106e5dd7070Spatrick
107e5dd7070Spatrick // In delayed template parsing mode, if we are within a class template
108e5dd7070Spatrick // or if we are about to parse function member template then consume
109e5dd7070Spatrick // the tokens and store them for parsing at the end of the translation unit.
110e5dd7070Spatrick if (getLangOpts().DelayedTemplateParsing &&
111a9ac8606Spatrick D.getFunctionDefinitionKind() == FunctionDefinitionKind::Definition &&
112e5dd7070Spatrick !D.getDeclSpec().hasConstexprSpecifier() &&
113e5dd7070Spatrick !(FnD && FnD->getAsFunction() &&
114e5dd7070Spatrick FnD->getAsFunction()->getReturnType()->getContainedAutoType()) &&
115e5dd7070Spatrick ((Actions.CurContext->isDependentContext() ||
116e5dd7070Spatrick (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
117e5dd7070Spatrick TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) &&
118e5dd7070Spatrick !Actions.IsInsideALocalClassWithinATemplateFunction())) {
119e5dd7070Spatrick
120e5dd7070Spatrick CachedTokens Toks;
121e5dd7070Spatrick LexTemplateFunctionForLateParsing(Toks);
122e5dd7070Spatrick
123e5dd7070Spatrick if (FnD) {
124e5dd7070Spatrick FunctionDecl *FD = FnD->getAsFunction();
125e5dd7070Spatrick Actions.CheckForFunctionRedefinition(FD);
126e5dd7070Spatrick Actions.MarkAsLateParsedTemplate(FD, FnD, Toks);
127e5dd7070Spatrick }
128e5dd7070Spatrick
129e5dd7070Spatrick return FnD;
130e5dd7070Spatrick }
131e5dd7070Spatrick
132e5dd7070Spatrick // Consume the tokens and store them for later parsing.
133e5dd7070Spatrick
134e5dd7070Spatrick LexedMethod* LM = new LexedMethod(this, FnD);
135e5dd7070Spatrick getCurrentClass().LateParsedDeclarations.push_back(LM);
136e5dd7070Spatrick CachedTokens &Toks = LM->Toks;
137e5dd7070Spatrick
138e5dd7070Spatrick tok::TokenKind kind = Tok.getKind();
139e5dd7070Spatrick // Consume everything up to (and including) the left brace of the
140e5dd7070Spatrick // function body.
141e5dd7070Spatrick if (ConsumeAndStoreFunctionPrologue(Toks)) {
142e5dd7070Spatrick // We didn't find the left-brace we expected after the
143*12c85518Srobert // constructor initializer.
144*12c85518Srobert
145*12c85518Srobert // If we're code-completing and the completion point was in the broken
146*12c85518Srobert // initializer, we want to parse it even though that will fail.
147*12c85518Srobert if (PP.isCodeCompletionEnabled() &&
148*12c85518Srobert llvm::any_of(Toks, [](const Token &Tok) {
149*12c85518Srobert return Tok.is(tok::code_completion);
150*12c85518Srobert })) {
151*12c85518Srobert // If we gave up at the completion point, the initializer list was
152*12c85518Srobert // likely truncated, so don't eat more tokens. We'll hit some extra
153*12c85518Srobert // errors, but they should be ignored in code completion.
154*12c85518Srobert return FnD;
155*12c85518Srobert }
156*12c85518Srobert
157*12c85518Srobert // We already printed an error, and it's likely impossible to recover,
158*12c85518Srobert // so don't try to parse this method later.
159e5dd7070Spatrick // Skip over the rest of the decl and back to somewhere that looks
160e5dd7070Spatrick // reasonable.
161e5dd7070Spatrick SkipMalformedDecl();
162e5dd7070Spatrick delete getCurrentClass().LateParsedDeclarations.back();
163e5dd7070Spatrick getCurrentClass().LateParsedDeclarations.pop_back();
164e5dd7070Spatrick return FnD;
165e5dd7070Spatrick } else {
166e5dd7070Spatrick // Consume everything up to (and including) the matching right brace.
167e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
168e5dd7070Spatrick }
169e5dd7070Spatrick
170e5dd7070Spatrick // If we're in a function-try-block, we need to store all the catch blocks.
171e5dd7070Spatrick if (kind == tok::kw_try) {
172e5dd7070Spatrick while (Tok.is(tok::kw_catch)) {
173e5dd7070Spatrick ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);
174e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
175e5dd7070Spatrick }
176e5dd7070Spatrick }
177e5dd7070Spatrick
178e5dd7070Spatrick if (FnD) {
179e5dd7070Spatrick FunctionDecl *FD = FnD->getAsFunction();
180e5dd7070Spatrick // Track that this function will eventually have a body; Sema needs
181e5dd7070Spatrick // to know this.
182e5dd7070Spatrick Actions.CheckForFunctionRedefinition(FD);
183e5dd7070Spatrick FD->setWillHaveBody(true);
184e5dd7070Spatrick } else {
185e5dd7070Spatrick // If semantic analysis could not build a function declaration,
186e5dd7070Spatrick // just throw away the late-parsed declaration.
187e5dd7070Spatrick delete getCurrentClass().LateParsedDeclarations.back();
188e5dd7070Spatrick getCurrentClass().LateParsedDeclarations.pop_back();
189e5dd7070Spatrick }
190e5dd7070Spatrick
191e5dd7070Spatrick return FnD;
192e5dd7070Spatrick }
193e5dd7070Spatrick
194e5dd7070Spatrick /// ParseCXXNonStaticMemberInitializer - We parsed and verified that the
195e5dd7070Spatrick /// specified Declarator is a well formed C++ non-static data member
196e5dd7070Spatrick /// declaration. Now lex its initializer and store its tokens for parsing
197e5dd7070Spatrick /// after the class is complete.
ParseCXXNonStaticMemberInitializer(Decl * VarD)198e5dd7070Spatrick void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) {
199e5dd7070Spatrick assert(Tok.isOneOf(tok::l_brace, tok::equal) &&
200e5dd7070Spatrick "Current token not a '{' or '='!");
201e5dd7070Spatrick
202e5dd7070Spatrick LateParsedMemberInitializer *MI =
203e5dd7070Spatrick new LateParsedMemberInitializer(this, VarD);
204e5dd7070Spatrick getCurrentClass().LateParsedDeclarations.push_back(MI);
205e5dd7070Spatrick CachedTokens &Toks = MI->Toks;
206e5dd7070Spatrick
207e5dd7070Spatrick tok::TokenKind kind = Tok.getKind();
208e5dd7070Spatrick if (kind == tok::equal) {
209e5dd7070Spatrick Toks.push_back(Tok);
210e5dd7070Spatrick ConsumeToken();
211e5dd7070Spatrick }
212e5dd7070Spatrick
213e5dd7070Spatrick if (kind == tok::l_brace) {
214e5dd7070Spatrick // Begin by storing the '{' token.
215e5dd7070Spatrick Toks.push_back(Tok);
216e5dd7070Spatrick ConsumeBrace();
217e5dd7070Spatrick
218e5dd7070Spatrick // Consume everything up to (and including) the matching right brace.
219e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/true);
220e5dd7070Spatrick } else {
221e5dd7070Spatrick // Consume everything up to (but excluding) the comma or semicolon.
222e5dd7070Spatrick ConsumeAndStoreInitializer(Toks, CIK_DefaultInitializer);
223e5dd7070Spatrick }
224e5dd7070Spatrick
225e5dd7070Spatrick // Store an artificial EOF token to ensure that we don't run off the end of
226e5dd7070Spatrick // the initializer when we come to parse it.
227e5dd7070Spatrick Token Eof;
228e5dd7070Spatrick Eof.startToken();
229e5dd7070Spatrick Eof.setKind(tok::eof);
230e5dd7070Spatrick Eof.setLocation(Tok.getLocation());
231e5dd7070Spatrick Eof.setEofData(VarD);
232e5dd7070Spatrick Toks.push_back(Eof);
233e5dd7070Spatrick }
234e5dd7070Spatrick
~LateParsedDeclaration()235e5dd7070Spatrick Parser::LateParsedDeclaration::~LateParsedDeclaration() {}
ParseLexedMethodDeclarations()236e5dd7070Spatrick void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {}
ParseLexedMemberInitializers()237e5dd7070Spatrick void Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {}
ParseLexedMethodDefs()238e5dd7070Spatrick void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {}
ParseLexedAttributes()239ec727ea7Spatrick void Parser::LateParsedDeclaration::ParseLexedAttributes() {}
ParseLexedPragmas()240e5dd7070Spatrick void Parser::LateParsedDeclaration::ParseLexedPragmas() {}
241e5dd7070Spatrick
LateParsedClass(Parser * P,ParsingClass * C)242e5dd7070Spatrick Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C)
243e5dd7070Spatrick : Self(P), Class(C) {}
244e5dd7070Spatrick
~LateParsedClass()245e5dd7070Spatrick Parser::LateParsedClass::~LateParsedClass() {
246e5dd7070Spatrick Self->DeallocateParsedClasses(Class);
247e5dd7070Spatrick }
248e5dd7070Spatrick
ParseLexedMethodDeclarations()249e5dd7070Spatrick void Parser::LateParsedClass::ParseLexedMethodDeclarations() {
250e5dd7070Spatrick Self->ParseLexedMethodDeclarations(*Class);
251e5dd7070Spatrick }
252e5dd7070Spatrick
ParseLexedMemberInitializers()253e5dd7070Spatrick void Parser::LateParsedClass::ParseLexedMemberInitializers() {
254e5dd7070Spatrick Self->ParseLexedMemberInitializers(*Class);
255e5dd7070Spatrick }
256e5dd7070Spatrick
ParseLexedMethodDefs()257e5dd7070Spatrick void Parser::LateParsedClass::ParseLexedMethodDefs() {
258e5dd7070Spatrick Self->ParseLexedMethodDefs(*Class);
259e5dd7070Spatrick }
260e5dd7070Spatrick
ParseLexedAttributes()261ec727ea7Spatrick void Parser::LateParsedClass::ParseLexedAttributes() {
262ec727ea7Spatrick Self->ParseLexedAttributes(*Class);
263ec727ea7Spatrick }
264ec727ea7Spatrick
ParseLexedPragmas()265e5dd7070Spatrick void Parser::LateParsedClass::ParseLexedPragmas() {
266e5dd7070Spatrick Self->ParseLexedPragmas(*Class);
267e5dd7070Spatrick }
268e5dd7070Spatrick
ParseLexedMethodDeclarations()269e5dd7070Spatrick void Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() {
270e5dd7070Spatrick Self->ParseLexedMethodDeclaration(*this);
271e5dd7070Spatrick }
272e5dd7070Spatrick
ParseLexedMethodDefs()273e5dd7070Spatrick void Parser::LexedMethod::ParseLexedMethodDefs() {
274e5dd7070Spatrick Self->ParseLexedMethodDef(*this);
275e5dd7070Spatrick }
276e5dd7070Spatrick
ParseLexedMemberInitializers()277e5dd7070Spatrick void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() {
278e5dd7070Spatrick Self->ParseLexedMemberInitializer(*this);
279e5dd7070Spatrick }
280e5dd7070Spatrick
ParseLexedAttributes()281ec727ea7Spatrick void Parser::LateParsedAttribute::ParseLexedAttributes() {
282ec727ea7Spatrick Self->ParseLexedAttribute(*this, true, false);
283ec727ea7Spatrick }
284ec727ea7Spatrick
ParseLexedPragmas()285e5dd7070Spatrick void Parser::LateParsedPragma::ParseLexedPragmas() {
286e5dd7070Spatrick Self->ParseLexedPragma(*this);
287e5dd7070Spatrick }
288e5dd7070Spatrick
289ec727ea7Spatrick /// Utility to re-enter a possibly-templated scope while parsing its
290ec727ea7Spatrick /// late-parsed components.
291ec727ea7Spatrick struct Parser::ReenterTemplateScopeRAII {
292ec727ea7Spatrick Parser &P;
293ec727ea7Spatrick MultiParseScope Scopes;
294ec727ea7Spatrick TemplateParameterDepthRAII CurTemplateDepthTracker;
295ec727ea7Spatrick
ReenterTemplateScopeRAIIParser::ReenterTemplateScopeRAII296ec727ea7Spatrick ReenterTemplateScopeRAII(Parser &P, Decl *MaybeTemplated, bool Enter = true)
297ec727ea7Spatrick : P(P), Scopes(P), CurTemplateDepthTracker(P.TemplateParameterDepth) {
298ec727ea7Spatrick if (Enter) {
299ec727ea7Spatrick CurTemplateDepthTracker.addDepth(
300ec727ea7Spatrick P.ReenterTemplateScopes(Scopes, MaybeTemplated));
301ec727ea7Spatrick }
302ec727ea7Spatrick }
303ec727ea7Spatrick };
304ec727ea7Spatrick
305ec727ea7Spatrick /// Utility to re-enter a class scope while parsing its late-parsed components.
306ec727ea7Spatrick struct Parser::ReenterClassScopeRAII : ReenterTemplateScopeRAII {
307ec727ea7Spatrick ParsingClass &Class;
308ec727ea7Spatrick
ReenterClassScopeRAIIParser::ReenterClassScopeRAII309ec727ea7Spatrick ReenterClassScopeRAII(Parser &P, ParsingClass &Class)
310ec727ea7Spatrick : ReenterTemplateScopeRAII(P, Class.TagOrTemplate,
311ec727ea7Spatrick /*Enter=*/!Class.TopLevelClass),
312ec727ea7Spatrick Class(Class) {
313ec727ea7Spatrick // If this is the top-level class, we're still within its scope.
314ec727ea7Spatrick if (Class.TopLevelClass)
315ec727ea7Spatrick return;
316ec727ea7Spatrick
317ec727ea7Spatrick // Re-enter the class scope itself.
318ec727ea7Spatrick Scopes.Enter(Scope::ClassScope|Scope::DeclScope);
319ec727ea7Spatrick P.Actions.ActOnStartDelayedMemberDeclarations(P.getCurScope(),
320ec727ea7Spatrick Class.TagOrTemplate);
321ec727ea7Spatrick }
~ReenterClassScopeRAIIParser::ReenterClassScopeRAII322ec727ea7Spatrick ~ReenterClassScopeRAII() {
323ec727ea7Spatrick if (Class.TopLevelClass)
324ec727ea7Spatrick return;
325ec727ea7Spatrick
326ec727ea7Spatrick P.Actions.ActOnFinishDelayedMemberDeclarations(P.getCurScope(),
327ec727ea7Spatrick Class.TagOrTemplate);
328ec727ea7Spatrick }
329ec727ea7Spatrick };
330ec727ea7Spatrick
331e5dd7070Spatrick /// ParseLexedMethodDeclarations - We finished parsing the member
332e5dd7070Spatrick /// specification of a top (non-nested) C++ class. Now go over the
333e5dd7070Spatrick /// stack of method declarations with some parts for which parsing was
334e5dd7070Spatrick /// delayed (such as default arguments) and parse them.
ParseLexedMethodDeclarations(ParsingClass & Class)335e5dd7070Spatrick void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
336ec727ea7Spatrick ReenterClassScopeRAII InClassScope(*this, Class);
337e5dd7070Spatrick
338ec727ea7Spatrick for (LateParsedDeclaration *LateD : Class.LateParsedDeclarations)
339ec727ea7Spatrick LateD->ParseLexedMethodDeclarations();
340e5dd7070Spatrick }
341e5dd7070Spatrick
ParseLexedMethodDeclaration(LateParsedMethodDeclaration & LM)342e5dd7070Spatrick void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
343e5dd7070Spatrick // If this is a member template, introduce the template parameter scope.
344ec727ea7Spatrick ReenterTemplateScopeRAII InFunctionTemplateScope(*this, LM.Method);
345ec727ea7Spatrick
346e5dd7070Spatrick // Start the delayed C++ method declaration
347e5dd7070Spatrick Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
348e5dd7070Spatrick
349e5dd7070Spatrick // Introduce the parameters into scope and parse their default
350e5dd7070Spatrick // arguments.
351ec727ea7Spatrick InFunctionTemplateScope.Scopes.Enter(Scope::FunctionPrototypeScope |
352ec727ea7Spatrick Scope::FunctionDeclarationScope |
353ec727ea7Spatrick Scope::DeclScope);
354e5dd7070Spatrick for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
355e5dd7070Spatrick auto Param = cast<ParmVarDecl>(LM.DefaultArgs[I].Param);
356e5dd7070Spatrick // Introduce the parameter into scope.
357e5dd7070Spatrick bool HasUnparsed = Param->hasUnparsedDefaultArg();
358e5dd7070Spatrick Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param);
359e5dd7070Spatrick std::unique_ptr<CachedTokens> Toks = std::move(LM.DefaultArgs[I].Toks);
360e5dd7070Spatrick if (Toks) {
361e5dd7070Spatrick ParenBraceBracketBalancer BalancerRAIIObj(*this);
362e5dd7070Spatrick
363e5dd7070Spatrick // Mark the end of the default argument so that we know when to stop when
364e5dd7070Spatrick // we parse it later on.
365e5dd7070Spatrick Token LastDefaultArgToken = Toks->back();
366e5dd7070Spatrick Token DefArgEnd;
367e5dd7070Spatrick DefArgEnd.startToken();
368e5dd7070Spatrick DefArgEnd.setKind(tok::eof);
369e5dd7070Spatrick DefArgEnd.setLocation(LastDefaultArgToken.getEndLoc());
370e5dd7070Spatrick DefArgEnd.setEofData(Param);
371e5dd7070Spatrick Toks->push_back(DefArgEnd);
372e5dd7070Spatrick
373e5dd7070Spatrick // Parse the default argument from its saved token stream.
374e5dd7070Spatrick Toks->push_back(Tok); // So that the current token doesn't get lost
375e5dd7070Spatrick PP.EnterTokenStream(*Toks, true, /*IsReinject*/ true);
376e5dd7070Spatrick
377e5dd7070Spatrick // Consume the previously-pushed token.
378e5dd7070Spatrick ConsumeAnyToken();
379e5dd7070Spatrick
380e5dd7070Spatrick // Consume the '='.
381e5dd7070Spatrick assert(Tok.is(tok::equal) && "Default argument not starting with '='");
382e5dd7070Spatrick SourceLocation EqualLoc = ConsumeToken();
383e5dd7070Spatrick
384e5dd7070Spatrick // The argument isn't actually potentially evaluated unless it is
385e5dd7070Spatrick // used.
386e5dd7070Spatrick EnterExpressionEvaluationContext Eval(
387e5dd7070Spatrick Actions,
388e5dd7070Spatrick Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, Param);
389e5dd7070Spatrick
390e5dd7070Spatrick ExprResult DefArgResult;
391e5dd7070Spatrick if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
392e5dd7070Spatrick Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
393e5dd7070Spatrick DefArgResult = ParseBraceInitializer();
394e5dd7070Spatrick } else
395e5dd7070Spatrick DefArgResult = ParseAssignmentExpression();
396e5dd7070Spatrick DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
397e5dd7070Spatrick if (DefArgResult.isInvalid()) {
398e5dd7070Spatrick Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
399e5dd7070Spatrick } else {
400e5dd7070Spatrick if (Tok.isNot(tok::eof) || Tok.getEofData() != Param) {
401e5dd7070Spatrick // The last two tokens are the terminator and the saved value of
402e5dd7070Spatrick // Tok; the last token in the default argument is the one before
403e5dd7070Spatrick // those.
404e5dd7070Spatrick assert(Toks->size() >= 3 && "expected a token in default arg");
405e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_default_arg_unparsed)
406e5dd7070Spatrick << SourceRange(Tok.getLocation(),
407e5dd7070Spatrick (*Toks)[Toks->size() - 3].getLocation());
408e5dd7070Spatrick }
409e5dd7070Spatrick Actions.ActOnParamDefaultArgument(Param, EqualLoc,
410e5dd7070Spatrick DefArgResult.get());
411e5dd7070Spatrick }
412e5dd7070Spatrick
413e5dd7070Spatrick // There could be leftover tokens (e.g. because of an error).
414e5dd7070Spatrick // Skip through until we reach the 'end of default argument' token.
415e5dd7070Spatrick while (Tok.isNot(tok::eof))
416e5dd7070Spatrick ConsumeAnyToken();
417e5dd7070Spatrick
418e5dd7070Spatrick if (Tok.is(tok::eof) && Tok.getEofData() == Param)
419e5dd7070Spatrick ConsumeAnyToken();
420e5dd7070Spatrick } else if (HasUnparsed) {
421e5dd7070Spatrick assert(Param->hasInheritedDefaultArg());
422a9ac8606Spatrick const FunctionDecl *Old;
423a9ac8606Spatrick if (const auto *FunTmpl = dyn_cast<FunctionTemplateDecl>(LM.Method))
424a9ac8606Spatrick Old =
425a9ac8606Spatrick cast<FunctionDecl>(FunTmpl->getTemplatedDecl())->getPreviousDecl();
426a9ac8606Spatrick else
427a9ac8606Spatrick Old = cast<FunctionDecl>(LM.Method)->getPreviousDecl();
428a9ac8606Spatrick if (Old) {
429a9ac8606Spatrick ParmVarDecl *OldParam = const_cast<ParmVarDecl*>(Old->getParamDecl(I));
430e5dd7070Spatrick assert(!OldParam->hasUnparsedDefaultArg());
431e5dd7070Spatrick if (OldParam->hasUninstantiatedDefaultArg())
432e5dd7070Spatrick Param->setUninstantiatedDefaultArg(
433e5dd7070Spatrick OldParam->getUninstantiatedDefaultArg());
434e5dd7070Spatrick else
435e5dd7070Spatrick Param->setDefaultArg(OldParam->getInit());
436e5dd7070Spatrick }
437e5dd7070Spatrick }
438a9ac8606Spatrick }
439e5dd7070Spatrick
440e5dd7070Spatrick // Parse a delayed exception-specification, if there is one.
441e5dd7070Spatrick if (CachedTokens *Toks = LM.ExceptionSpecTokens) {
442e5dd7070Spatrick ParenBraceBracketBalancer BalancerRAIIObj(*this);
443e5dd7070Spatrick
444e5dd7070Spatrick // Add the 'stop' token.
445e5dd7070Spatrick Token LastExceptionSpecToken = Toks->back();
446e5dd7070Spatrick Token ExceptionSpecEnd;
447e5dd7070Spatrick ExceptionSpecEnd.startToken();
448e5dd7070Spatrick ExceptionSpecEnd.setKind(tok::eof);
449e5dd7070Spatrick ExceptionSpecEnd.setLocation(LastExceptionSpecToken.getEndLoc());
450e5dd7070Spatrick ExceptionSpecEnd.setEofData(LM.Method);
451e5dd7070Spatrick Toks->push_back(ExceptionSpecEnd);
452e5dd7070Spatrick
453e5dd7070Spatrick // Parse the default argument from its saved token stream.
454e5dd7070Spatrick Toks->push_back(Tok); // So that the current token doesn't get lost
455e5dd7070Spatrick PP.EnterTokenStream(*Toks, true, /*IsReinject*/true);
456e5dd7070Spatrick
457e5dd7070Spatrick // Consume the previously-pushed token.
458e5dd7070Spatrick ConsumeAnyToken();
459e5dd7070Spatrick
460e5dd7070Spatrick // C++11 [expr.prim.general]p3:
461e5dd7070Spatrick // If a declaration declares a member function or member function
462e5dd7070Spatrick // template of a class X, the expression this is a prvalue of type
463e5dd7070Spatrick // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
464e5dd7070Spatrick // and the end of the function-definition, member-declarator, or
465e5dd7070Spatrick // declarator.
466e5dd7070Spatrick CXXMethodDecl *Method;
467e5dd7070Spatrick if (FunctionTemplateDecl *FunTmpl
468e5dd7070Spatrick = dyn_cast<FunctionTemplateDecl>(LM.Method))
469*12c85518Srobert Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
470e5dd7070Spatrick else
471*12c85518Srobert Method = dyn_cast<CXXMethodDecl>(LM.Method);
472e5dd7070Spatrick
473*12c85518Srobert Sema::CXXThisScopeRAII ThisScope(
474*12c85518Srobert Actions, Method ? Method->getParent() : nullptr,
475*12c85518Srobert Method ? Method->getMethodQualifiers() : Qualifiers{},
476*12c85518Srobert Method && getLangOpts().CPlusPlus11);
477e5dd7070Spatrick
478e5dd7070Spatrick // Parse the exception-specification.
479e5dd7070Spatrick SourceRange SpecificationRange;
480e5dd7070Spatrick SmallVector<ParsedType, 4> DynamicExceptions;
481e5dd7070Spatrick SmallVector<SourceRange, 4> DynamicExceptionRanges;
482e5dd7070Spatrick ExprResult NoexceptExpr;
483e5dd7070Spatrick CachedTokens *ExceptionSpecTokens;
484e5dd7070Spatrick
485e5dd7070Spatrick ExceptionSpecificationType EST
486e5dd7070Spatrick = tryParseExceptionSpecification(/*Delayed=*/false, SpecificationRange,
487e5dd7070Spatrick DynamicExceptions,
488e5dd7070Spatrick DynamicExceptionRanges, NoexceptExpr,
489e5dd7070Spatrick ExceptionSpecTokens);
490e5dd7070Spatrick
491e5dd7070Spatrick if (Tok.isNot(tok::eof) || Tok.getEofData() != LM.Method)
492e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_except_spec_unparsed);
493e5dd7070Spatrick
494e5dd7070Spatrick // Attach the exception-specification to the method.
495e5dd7070Spatrick Actions.actOnDelayedExceptionSpecification(LM.Method, EST,
496e5dd7070Spatrick SpecificationRange,
497e5dd7070Spatrick DynamicExceptions,
498e5dd7070Spatrick DynamicExceptionRanges,
499e5dd7070Spatrick NoexceptExpr.isUsable()?
500e5dd7070Spatrick NoexceptExpr.get() : nullptr);
501e5dd7070Spatrick
502e5dd7070Spatrick // There could be leftover tokens (e.g. because of an error).
503e5dd7070Spatrick // Skip through until we reach the original token position.
504e5dd7070Spatrick while (Tok.isNot(tok::eof))
505e5dd7070Spatrick ConsumeAnyToken();
506e5dd7070Spatrick
507e5dd7070Spatrick // Clean up the remaining EOF token.
508e5dd7070Spatrick if (Tok.is(tok::eof) && Tok.getEofData() == LM.Method)
509e5dd7070Spatrick ConsumeAnyToken();
510e5dd7070Spatrick
511e5dd7070Spatrick delete Toks;
512e5dd7070Spatrick LM.ExceptionSpecTokens = nullptr;
513e5dd7070Spatrick }
514e5dd7070Spatrick
515ec727ea7Spatrick InFunctionTemplateScope.Scopes.Exit();
516e5dd7070Spatrick
517e5dd7070Spatrick // Finish the delayed C++ method declaration.
518e5dd7070Spatrick Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
519e5dd7070Spatrick }
520e5dd7070Spatrick
521e5dd7070Spatrick /// ParseLexedMethodDefs - We finished parsing the member specification of a top
522e5dd7070Spatrick /// (non-nested) C++ class. Now go over the stack of lexed methods that were
523e5dd7070Spatrick /// collected during its parsing and parse them all.
ParseLexedMethodDefs(ParsingClass & Class)524e5dd7070Spatrick void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
525ec727ea7Spatrick ReenterClassScopeRAII InClassScope(*this, Class);
526e5dd7070Spatrick
527ec727ea7Spatrick for (LateParsedDeclaration *D : Class.LateParsedDeclarations)
528ec727ea7Spatrick D->ParseLexedMethodDefs();
529e5dd7070Spatrick }
530e5dd7070Spatrick
ParseLexedMethodDef(LexedMethod & LM)531e5dd7070Spatrick void Parser::ParseLexedMethodDef(LexedMethod &LM) {
532e5dd7070Spatrick // If this is a member template, introduce the template parameter scope.
533ec727ea7Spatrick ReenterTemplateScopeRAII InFunctionTemplateScope(*this, LM.D);
534e5dd7070Spatrick
535e5dd7070Spatrick ParenBraceBracketBalancer BalancerRAIIObj(*this);
536e5dd7070Spatrick
537e5dd7070Spatrick assert(!LM.Toks.empty() && "Empty body!");
538e5dd7070Spatrick Token LastBodyToken = LM.Toks.back();
539e5dd7070Spatrick Token BodyEnd;
540e5dd7070Spatrick BodyEnd.startToken();
541e5dd7070Spatrick BodyEnd.setKind(tok::eof);
542e5dd7070Spatrick BodyEnd.setLocation(LastBodyToken.getEndLoc());
543e5dd7070Spatrick BodyEnd.setEofData(LM.D);
544e5dd7070Spatrick LM.Toks.push_back(BodyEnd);
545e5dd7070Spatrick // Append the current token at the end of the new token stream so that it
546e5dd7070Spatrick // doesn't get lost.
547e5dd7070Spatrick LM.Toks.push_back(Tok);
548e5dd7070Spatrick PP.EnterTokenStream(LM.Toks, true, /*IsReinject*/true);
549e5dd7070Spatrick
550e5dd7070Spatrick // Consume the previously pushed token.
551e5dd7070Spatrick ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
552e5dd7070Spatrick assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)
553e5dd7070Spatrick && "Inline method not starting with '{', ':' or 'try'");
554e5dd7070Spatrick
555e5dd7070Spatrick // Parse the method body. Function body parsing code is similar enough
556e5dd7070Spatrick // to be re-used for method bodies as well.
557e5dd7070Spatrick ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
558e5dd7070Spatrick Scope::CompoundStmtScope);
559e5dd7070Spatrick Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
560e5dd7070Spatrick
561e5dd7070Spatrick if (Tok.is(tok::kw_try)) {
562e5dd7070Spatrick ParseFunctionTryBlock(LM.D, FnScope);
563e5dd7070Spatrick
564e5dd7070Spatrick while (Tok.isNot(tok::eof))
565e5dd7070Spatrick ConsumeAnyToken();
566e5dd7070Spatrick
567e5dd7070Spatrick if (Tok.is(tok::eof) && Tok.getEofData() == LM.D)
568e5dd7070Spatrick ConsumeAnyToken();
569e5dd7070Spatrick return;
570e5dd7070Spatrick }
571e5dd7070Spatrick if (Tok.is(tok::colon)) {
572e5dd7070Spatrick ParseConstructorInitializer(LM.D);
573e5dd7070Spatrick
574e5dd7070Spatrick // Error recovery.
575e5dd7070Spatrick if (!Tok.is(tok::l_brace)) {
576e5dd7070Spatrick FnScope.Exit();
577e5dd7070Spatrick Actions.ActOnFinishFunctionBody(LM.D, nullptr);
578e5dd7070Spatrick
579e5dd7070Spatrick while (Tok.isNot(tok::eof))
580e5dd7070Spatrick ConsumeAnyToken();
581e5dd7070Spatrick
582e5dd7070Spatrick if (Tok.is(tok::eof) && Tok.getEofData() == LM.D)
583e5dd7070Spatrick ConsumeAnyToken();
584e5dd7070Spatrick return;
585e5dd7070Spatrick }
586e5dd7070Spatrick } else
587e5dd7070Spatrick Actions.ActOnDefaultCtorInitializers(LM.D);
588e5dd7070Spatrick
589e5dd7070Spatrick assert((Actions.getDiagnostics().hasErrorOccurred() ||
590e5dd7070Spatrick !isa<FunctionTemplateDecl>(LM.D) ||
591e5dd7070Spatrick cast<FunctionTemplateDecl>(LM.D)->getTemplateParameters()->getDepth()
592e5dd7070Spatrick < TemplateParameterDepth) &&
593e5dd7070Spatrick "TemplateParameterDepth should be greater than the depth of "
594e5dd7070Spatrick "current template being instantiated!");
595e5dd7070Spatrick
596e5dd7070Spatrick ParseFunctionStatementBody(LM.D, FnScope);
597e5dd7070Spatrick
598e5dd7070Spatrick while (Tok.isNot(tok::eof))
599e5dd7070Spatrick ConsumeAnyToken();
600e5dd7070Spatrick
601e5dd7070Spatrick if (Tok.is(tok::eof) && Tok.getEofData() == LM.D)
602e5dd7070Spatrick ConsumeAnyToken();
603e5dd7070Spatrick
604e5dd7070Spatrick if (auto *FD = dyn_cast_or_null<FunctionDecl>(LM.D))
605e5dd7070Spatrick if (isa<CXXMethodDecl>(FD) ||
606e5dd7070Spatrick FD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend))
607e5dd7070Spatrick Actions.ActOnFinishInlineFunctionDef(FD);
608e5dd7070Spatrick }
609e5dd7070Spatrick
610e5dd7070Spatrick /// ParseLexedMemberInitializers - We finished parsing the member specification
611e5dd7070Spatrick /// of a top (non-nested) C++ class. Now go over the stack of lexed data member
612e5dd7070Spatrick /// initializers that were collected during its parsing and parse them all.
ParseLexedMemberInitializers(ParsingClass & Class)613e5dd7070Spatrick void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
614ec727ea7Spatrick ReenterClassScopeRAII InClassScope(*this, Class);
615e5dd7070Spatrick
616e5dd7070Spatrick if (!Class.LateParsedDeclarations.empty()) {
617e5dd7070Spatrick // C++11 [expr.prim.general]p4:
618e5dd7070Spatrick // Otherwise, if a member-declarator declares a non-static data member
619e5dd7070Spatrick // (9.2) of a class X, the expression this is a prvalue of type "pointer
620e5dd7070Spatrick // to X" within the optional brace-or-equal-initializer. It shall not
621e5dd7070Spatrick // appear elsewhere in the member-declarator.
622ec727ea7Spatrick // FIXME: This should be done in ParseLexedMemberInitializer, not here.
623e5dd7070Spatrick Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
624e5dd7070Spatrick Qualifiers());
625e5dd7070Spatrick
626ec727ea7Spatrick for (LateParsedDeclaration *D : Class.LateParsedDeclarations)
627ec727ea7Spatrick D->ParseLexedMemberInitializers();
628e5dd7070Spatrick }
629e5dd7070Spatrick
630e5dd7070Spatrick Actions.ActOnFinishDelayedMemberInitializers(Class.TagOrTemplate);
631e5dd7070Spatrick }
632e5dd7070Spatrick
ParseLexedMemberInitializer(LateParsedMemberInitializer & MI)633e5dd7070Spatrick void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
634e5dd7070Spatrick if (!MI.Field || MI.Field->isInvalidDecl())
635e5dd7070Spatrick return;
636e5dd7070Spatrick
637e5dd7070Spatrick ParenBraceBracketBalancer BalancerRAIIObj(*this);
638e5dd7070Spatrick
639e5dd7070Spatrick // Append the current token at the end of the new token stream so that it
640e5dd7070Spatrick // doesn't get lost.
641e5dd7070Spatrick MI.Toks.push_back(Tok);
642e5dd7070Spatrick PP.EnterTokenStream(MI.Toks, true, /*IsReinject*/true);
643e5dd7070Spatrick
644e5dd7070Spatrick // Consume the previously pushed token.
645e5dd7070Spatrick ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
646e5dd7070Spatrick
647e5dd7070Spatrick SourceLocation EqualLoc;
648e5dd7070Spatrick
649e5dd7070Spatrick Actions.ActOnStartCXXInClassMemberInitializer();
650e5dd7070Spatrick
651*12c85518Srobert // The initializer isn't actually potentially evaluated unless it is
652*12c85518Srobert // used.
653*12c85518Srobert EnterExpressionEvaluationContext Eval(
654*12c85518Srobert Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed);
655*12c85518Srobert
656e5dd7070Spatrick ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
657e5dd7070Spatrick EqualLoc);
658e5dd7070Spatrick
659e5dd7070Spatrick Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc,
660e5dd7070Spatrick Init.get());
661e5dd7070Spatrick
662e5dd7070Spatrick // The next token should be our artificial terminating EOF token.
663e5dd7070Spatrick if (Tok.isNot(tok::eof)) {
664e5dd7070Spatrick if (!Init.isInvalid()) {
665e5dd7070Spatrick SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
666e5dd7070Spatrick if (!EndLoc.isValid())
667e5dd7070Spatrick EndLoc = Tok.getLocation();
668e5dd7070Spatrick // No fixit; we can't recover as if there were a semicolon here.
669e5dd7070Spatrick Diag(EndLoc, diag::err_expected_semi_decl_list);
670e5dd7070Spatrick }
671e5dd7070Spatrick
672e5dd7070Spatrick // Consume tokens until we hit the artificial EOF.
673e5dd7070Spatrick while (Tok.isNot(tok::eof))
674e5dd7070Spatrick ConsumeAnyToken();
675e5dd7070Spatrick }
676e5dd7070Spatrick // Make sure this is *our* artificial EOF token.
677e5dd7070Spatrick if (Tok.getEofData() == MI.Field)
678e5dd7070Spatrick ConsumeAnyToken();
679e5dd7070Spatrick }
680e5dd7070Spatrick
681ec727ea7Spatrick /// Wrapper class which calls ParseLexedAttribute, after setting up the
682ec727ea7Spatrick /// scope appropriately.
ParseLexedAttributes(ParsingClass & Class)683ec727ea7Spatrick void Parser::ParseLexedAttributes(ParsingClass &Class) {
684ec727ea7Spatrick ReenterClassScopeRAII InClassScope(*this, Class);
685e5dd7070Spatrick
686ec727ea7Spatrick for (LateParsedDeclaration *LateD : Class.LateParsedDeclarations)
687ec727ea7Spatrick LateD->ParseLexedAttributes();
688ec727ea7Spatrick }
689ec727ea7Spatrick
690ec727ea7Spatrick /// Parse all attributes in LAs, and attach them to Decl D.
ParseLexedAttributeList(LateParsedAttrList & LAs,Decl * D,bool EnterScope,bool OnDefinition)691ec727ea7Spatrick void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
692ec727ea7Spatrick bool EnterScope, bool OnDefinition) {
693ec727ea7Spatrick assert(LAs.parseSoon() &&
694ec727ea7Spatrick "Attribute list should be marked for immediate parsing.");
695ec727ea7Spatrick for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) {
696ec727ea7Spatrick if (D)
697ec727ea7Spatrick LAs[i]->addDecl(D);
698ec727ea7Spatrick ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition);
699ec727ea7Spatrick delete LAs[i];
700ec727ea7Spatrick }
701ec727ea7Spatrick LAs.clear();
702ec727ea7Spatrick }
703ec727ea7Spatrick
704ec727ea7Spatrick /// Finish parsing an attribute for which parsing was delayed.
705ec727ea7Spatrick /// This will be called at the end of parsing a class declaration
706ec727ea7Spatrick /// for each LateParsedAttribute. We consume the saved tokens and
707ec727ea7Spatrick /// create an attribute with the arguments filled in. We add this
708ec727ea7Spatrick /// to the Attribute list for the decl.
ParseLexedAttribute(LateParsedAttribute & LA,bool EnterScope,bool OnDefinition)709ec727ea7Spatrick void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
710ec727ea7Spatrick bool EnterScope, bool OnDefinition) {
711ec727ea7Spatrick // Create a fake EOF so that attribute parsing won't go off the end of the
712ec727ea7Spatrick // attribute.
713ec727ea7Spatrick Token AttrEnd;
714ec727ea7Spatrick AttrEnd.startToken();
715ec727ea7Spatrick AttrEnd.setKind(tok::eof);
716ec727ea7Spatrick AttrEnd.setLocation(Tok.getLocation());
717ec727ea7Spatrick AttrEnd.setEofData(LA.Toks.data());
718ec727ea7Spatrick LA.Toks.push_back(AttrEnd);
719ec727ea7Spatrick
720ec727ea7Spatrick // Append the current token at the end of the new token stream so that it
721ec727ea7Spatrick // doesn't get lost.
722ec727ea7Spatrick LA.Toks.push_back(Tok);
723ec727ea7Spatrick PP.EnterTokenStream(LA.Toks, true, /*IsReinject=*/true);
724ec727ea7Spatrick // Consume the previously pushed token.
725ec727ea7Spatrick ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
726ec727ea7Spatrick
727ec727ea7Spatrick ParsedAttributes Attrs(AttrFactory);
728ec727ea7Spatrick
729ec727ea7Spatrick if (LA.Decls.size() > 0) {
730ec727ea7Spatrick Decl *D = LA.Decls[0];
731ec727ea7Spatrick NamedDecl *ND = dyn_cast<NamedDecl>(D);
732ec727ea7Spatrick RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
733ec727ea7Spatrick
734ec727ea7Spatrick // Allow 'this' within late-parsed attributes.
735ec727ea7Spatrick Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(),
736ec727ea7Spatrick ND && ND->isCXXInstanceMember());
737ec727ea7Spatrick
738ec727ea7Spatrick if (LA.Decls.size() == 1) {
739ec727ea7Spatrick // If the Decl is templatized, add template parameters to scope.
740ec727ea7Spatrick ReenterTemplateScopeRAII InDeclScope(*this, D, EnterScope);
741ec727ea7Spatrick
742ec727ea7Spatrick // If the Decl is on a function, add function parameters to the scope.
743ec727ea7Spatrick bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate();
744ec727ea7Spatrick if (HasFunScope) {
745ec727ea7Spatrick InDeclScope.Scopes.Enter(Scope::FnScope | Scope::DeclScope |
746ec727ea7Spatrick Scope::CompoundStmtScope);
747ec727ea7Spatrick Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
748ec727ea7Spatrick }
749ec727ea7Spatrick
750*12c85518Srobert ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, nullptr,
751ec727ea7Spatrick nullptr, SourceLocation(), ParsedAttr::AS_GNU,
752ec727ea7Spatrick nullptr);
753ec727ea7Spatrick
754ec727ea7Spatrick if (HasFunScope)
755ec727ea7Spatrick Actions.ActOnExitFunctionContext();
756ec727ea7Spatrick } else {
757ec727ea7Spatrick // If there are multiple decls, then the decl cannot be within the
758ec727ea7Spatrick // function scope.
759*12c85518Srobert ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, nullptr,
760ec727ea7Spatrick nullptr, SourceLocation(), ParsedAttr::AS_GNU,
761ec727ea7Spatrick nullptr);
762ec727ea7Spatrick }
763ec727ea7Spatrick } else {
764ec727ea7Spatrick Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
765ec727ea7Spatrick }
766ec727ea7Spatrick
767ec727ea7Spatrick if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() &&
768ec727ea7Spatrick Attrs.begin()->isKnownToGCC())
769ec727ea7Spatrick Diag(Tok, diag::warn_attribute_on_function_definition)
770ec727ea7Spatrick << &LA.AttrName;
771ec727ea7Spatrick
772ec727ea7Spatrick for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i)
773ec727ea7Spatrick Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs);
774ec727ea7Spatrick
775ec727ea7Spatrick // Due to a parsing error, we either went over the cached tokens or
776ec727ea7Spatrick // there are still cached tokens left, so we skip the leftover tokens.
777ec727ea7Spatrick while (Tok.isNot(tok::eof))
778ec727ea7Spatrick ConsumeAnyToken();
779ec727ea7Spatrick
780ec727ea7Spatrick if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData())
781ec727ea7Spatrick ConsumeAnyToken();
782ec727ea7Spatrick }
783ec727ea7Spatrick
ParseLexedPragmas(ParsingClass & Class)784ec727ea7Spatrick void Parser::ParseLexedPragmas(ParsingClass &Class) {
785ec727ea7Spatrick ReenterClassScopeRAII InClassScope(*this, Class);
786ec727ea7Spatrick
787ec727ea7Spatrick for (LateParsedDeclaration *D : Class.LateParsedDeclarations)
788ec727ea7Spatrick D->ParseLexedPragmas();
789e5dd7070Spatrick }
790e5dd7070Spatrick
ParseLexedPragma(LateParsedPragma & LP)791e5dd7070Spatrick void Parser::ParseLexedPragma(LateParsedPragma &LP) {
792e5dd7070Spatrick PP.EnterToken(Tok, /*IsReinject=*/true);
793e5dd7070Spatrick PP.EnterTokenStream(LP.toks(), /*DisableMacroExpansion=*/true,
794e5dd7070Spatrick /*IsReinject=*/true);
795e5dd7070Spatrick
796e5dd7070Spatrick // Consume the previously pushed token.
797e5dd7070Spatrick ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
798e5dd7070Spatrick assert(Tok.isAnnotation() && "Expected annotation token.");
799e5dd7070Spatrick switch (Tok.getKind()) {
800a9ac8606Spatrick case tok::annot_attr_openmp:
801e5dd7070Spatrick case tok::annot_pragma_openmp: {
802e5dd7070Spatrick AccessSpecifier AS = LP.getAccessSpecifier();
803*12c85518Srobert ParsedAttributes Attrs(AttrFactory);
804e5dd7070Spatrick (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs);
805e5dd7070Spatrick break;
806e5dd7070Spatrick }
807e5dd7070Spatrick default:
808e5dd7070Spatrick llvm_unreachable("Unexpected token.");
809e5dd7070Spatrick }
810e5dd7070Spatrick }
811e5dd7070Spatrick
812e5dd7070Spatrick /// ConsumeAndStoreUntil - Consume and store the token at the passed token
813e5dd7070Spatrick /// container until the token 'T' is reached (which gets
814e5dd7070Spatrick /// consumed/stored too, if ConsumeFinalToken).
815e5dd7070Spatrick /// If StopAtSemi is true, then we will stop early at a ';' character.
816e5dd7070Spatrick /// Returns true if token 'T1' or 'T2' was found.
817e5dd7070Spatrick /// NOTE: This is a specialized version of Parser::SkipUntil.
ConsumeAndStoreUntil(tok::TokenKind T1,tok::TokenKind T2,CachedTokens & Toks,bool StopAtSemi,bool ConsumeFinalToken)818e5dd7070Spatrick bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
819e5dd7070Spatrick CachedTokens &Toks,
820e5dd7070Spatrick bool StopAtSemi, bool ConsumeFinalToken) {
821e5dd7070Spatrick // We always want this function to consume at least one token if the first
822e5dd7070Spatrick // token isn't T and if not at EOF.
823e5dd7070Spatrick bool isFirstTokenConsumed = true;
824*12c85518Srobert while (true) {
825e5dd7070Spatrick // If we found one of the tokens, stop and return true.
826e5dd7070Spatrick if (Tok.is(T1) || Tok.is(T2)) {
827e5dd7070Spatrick if (ConsumeFinalToken) {
828e5dd7070Spatrick Toks.push_back(Tok);
829e5dd7070Spatrick ConsumeAnyToken();
830e5dd7070Spatrick }
831e5dd7070Spatrick return true;
832e5dd7070Spatrick }
833e5dd7070Spatrick
834e5dd7070Spatrick switch (Tok.getKind()) {
835e5dd7070Spatrick case tok::eof:
836e5dd7070Spatrick case tok::annot_module_begin:
837e5dd7070Spatrick case tok::annot_module_end:
838e5dd7070Spatrick case tok::annot_module_include:
839e5dd7070Spatrick // Ran out of tokens.
840e5dd7070Spatrick return false;
841e5dd7070Spatrick
842e5dd7070Spatrick case tok::l_paren:
843e5dd7070Spatrick // Recursively consume properly-nested parens.
844e5dd7070Spatrick Toks.push_back(Tok);
845e5dd7070Spatrick ConsumeParen();
846e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
847e5dd7070Spatrick break;
848e5dd7070Spatrick case tok::l_square:
849e5dd7070Spatrick // Recursively consume properly-nested square brackets.
850e5dd7070Spatrick Toks.push_back(Tok);
851e5dd7070Spatrick ConsumeBracket();
852e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false);
853e5dd7070Spatrick break;
854e5dd7070Spatrick case tok::l_brace:
855e5dd7070Spatrick // Recursively consume properly-nested braces.
856e5dd7070Spatrick Toks.push_back(Tok);
857e5dd7070Spatrick ConsumeBrace();
858e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
859e5dd7070Spatrick break;
860e5dd7070Spatrick
861e5dd7070Spatrick // Okay, we found a ']' or '}' or ')', which we think should be balanced.
862e5dd7070Spatrick // Since the user wasn't looking for this token (if they were, it would
863e5dd7070Spatrick // already be handled), this isn't balanced. If there is a LHS token at a
864e5dd7070Spatrick // higher level, we will assume that this matches the unbalanced token
865e5dd7070Spatrick // and return it. Otherwise, this is a spurious RHS token, which we skip.
866e5dd7070Spatrick case tok::r_paren:
867e5dd7070Spatrick if (ParenCount && !isFirstTokenConsumed)
868e5dd7070Spatrick return false; // Matches something.
869e5dd7070Spatrick Toks.push_back(Tok);
870e5dd7070Spatrick ConsumeParen();
871e5dd7070Spatrick break;
872e5dd7070Spatrick case tok::r_square:
873e5dd7070Spatrick if (BracketCount && !isFirstTokenConsumed)
874e5dd7070Spatrick return false; // Matches something.
875e5dd7070Spatrick Toks.push_back(Tok);
876e5dd7070Spatrick ConsumeBracket();
877e5dd7070Spatrick break;
878e5dd7070Spatrick case tok::r_brace:
879e5dd7070Spatrick if (BraceCount && !isFirstTokenConsumed)
880e5dd7070Spatrick return false; // Matches something.
881e5dd7070Spatrick Toks.push_back(Tok);
882e5dd7070Spatrick ConsumeBrace();
883e5dd7070Spatrick break;
884e5dd7070Spatrick
885e5dd7070Spatrick case tok::semi:
886e5dd7070Spatrick if (StopAtSemi)
887e5dd7070Spatrick return false;
888*12c85518Srobert [[fallthrough]];
889e5dd7070Spatrick default:
890e5dd7070Spatrick // consume this token.
891e5dd7070Spatrick Toks.push_back(Tok);
892e5dd7070Spatrick ConsumeAnyToken(/*ConsumeCodeCompletionTok*/true);
893e5dd7070Spatrick break;
894e5dd7070Spatrick }
895e5dd7070Spatrick isFirstTokenConsumed = false;
896e5dd7070Spatrick }
897e5dd7070Spatrick }
898e5dd7070Spatrick
899e5dd7070Spatrick /// Consume tokens and store them in the passed token container until
900e5dd7070Spatrick /// we've passed the try keyword and constructor initializers and have consumed
901e5dd7070Spatrick /// the opening brace of the function body. The opening brace will be consumed
902e5dd7070Spatrick /// if and only if there was no error.
903e5dd7070Spatrick ///
904e5dd7070Spatrick /// \return True on error.
ConsumeAndStoreFunctionPrologue(CachedTokens & Toks)905e5dd7070Spatrick bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
906e5dd7070Spatrick if (Tok.is(tok::kw_try)) {
907e5dd7070Spatrick Toks.push_back(Tok);
908e5dd7070Spatrick ConsumeToken();
909e5dd7070Spatrick }
910e5dd7070Spatrick
911e5dd7070Spatrick if (Tok.isNot(tok::colon)) {
912e5dd7070Spatrick // Easy case, just a function body.
913e5dd7070Spatrick
914e5dd7070Spatrick // Grab any remaining garbage to be diagnosed later. We stop when we reach a
915e5dd7070Spatrick // brace: an opening one is the function body, while a closing one probably
916e5dd7070Spatrick // means we've reached the end of the class.
917e5dd7070Spatrick ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks,
918e5dd7070Spatrick /*StopAtSemi=*/true,
919e5dd7070Spatrick /*ConsumeFinalToken=*/false);
920e5dd7070Spatrick if (Tok.isNot(tok::l_brace))
921e5dd7070Spatrick return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;
922e5dd7070Spatrick
923e5dd7070Spatrick Toks.push_back(Tok);
924e5dd7070Spatrick ConsumeBrace();
925e5dd7070Spatrick return false;
926e5dd7070Spatrick }
927e5dd7070Spatrick
928e5dd7070Spatrick Toks.push_back(Tok);
929e5dd7070Spatrick ConsumeToken();
930e5dd7070Spatrick
931e5dd7070Spatrick // We can't reliably skip over a mem-initializer-id, because it could be
932e5dd7070Spatrick // a template-id involving not-yet-declared names. Given:
933e5dd7070Spatrick //
934e5dd7070Spatrick // S ( ) : a < b < c > ( e )
935e5dd7070Spatrick //
936e5dd7070Spatrick // 'e' might be an initializer or part of a template argument, depending
937e5dd7070Spatrick // on whether 'b' is a template.
938e5dd7070Spatrick
939e5dd7070Spatrick // Track whether we might be inside a template argument. We can give
940e5dd7070Spatrick // significantly better diagnostics if we know that we're not.
941e5dd7070Spatrick bool MightBeTemplateArgument = false;
942e5dd7070Spatrick
943e5dd7070Spatrick while (true) {
944e5dd7070Spatrick // Skip over the mem-initializer-id, if possible.
945e5dd7070Spatrick if (Tok.is(tok::kw_decltype)) {
946e5dd7070Spatrick Toks.push_back(Tok);
947e5dd7070Spatrick SourceLocation OpenLoc = ConsumeToken();
948e5dd7070Spatrick if (Tok.isNot(tok::l_paren))
949e5dd7070Spatrick return Diag(Tok.getLocation(), diag::err_expected_lparen_after)
950e5dd7070Spatrick << "decltype";
951e5dd7070Spatrick Toks.push_back(Tok);
952e5dd7070Spatrick ConsumeParen();
953e5dd7070Spatrick if (!ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/true)) {
954e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
955e5dd7070Spatrick Diag(OpenLoc, diag::note_matching) << tok::l_paren;
956e5dd7070Spatrick return true;
957e5dd7070Spatrick }
958e5dd7070Spatrick }
959e5dd7070Spatrick do {
960e5dd7070Spatrick // Walk over a component of a nested-name-specifier.
961e5dd7070Spatrick if (Tok.is(tok::coloncolon)) {
962e5dd7070Spatrick Toks.push_back(Tok);
963e5dd7070Spatrick ConsumeToken();
964e5dd7070Spatrick
965e5dd7070Spatrick if (Tok.is(tok::kw_template)) {
966e5dd7070Spatrick Toks.push_back(Tok);
967e5dd7070Spatrick ConsumeToken();
968e5dd7070Spatrick }
969e5dd7070Spatrick }
970e5dd7070Spatrick
971e5dd7070Spatrick if (Tok.is(tok::identifier)) {
972e5dd7070Spatrick Toks.push_back(Tok);
973e5dd7070Spatrick ConsumeToken();
974e5dd7070Spatrick } else {
975e5dd7070Spatrick break;
976e5dd7070Spatrick }
977e5dd7070Spatrick } while (Tok.is(tok::coloncolon));
978e5dd7070Spatrick
979e5dd7070Spatrick if (Tok.is(tok::code_completion)) {
980e5dd7070Spatrick Toks.push_back(Tok);
981e5dd7070Spatrick ConsumeCodeCompletionToken();
982e5dd7070Spatrick if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype)) {
983e5dd7070Spatrick // Could be the start of another member initializer (the ',' has not
984e5dd7070Spatrick // been written yet)
985e5dd7070Spatrick continue;
986e5dd7070Spatrick }
987e5dd7070Spatrick }
988e5dd7070Spatrick
989e5dd7070Spatrick if (Tok.is(tok::comma)) {
990e5dd7070Spatrick // The initialization is missing, we'll diagnose it later.
991e5dd7070Spatrick Toks.push_back(Tok);
992e5dd7070Spatrick ConsumeToken();
993e5dd7070Spatrick continue;
994e5dd7070Spatrick }
995e5dd7070Spatrick if (Tok.is(tok::less))
996e5dd7070Spatrick MightBeTemplateArgument = true;
997e5dd7070Spatrick
998e5dd7070Spatrick if (MightBeTemplateArgument) {
999e5dd7070Spatrick // We may be inside a template argument list. Grab up to the start of the
1000e5dd7070Spatrick // next parenthesized initializer or braced-init-list. This *might* be the
1001e5dd7070Spatrick // initializer, or it might be a subexpression in the template argument
1002e5dd7070Spatrick // list.
1003e5dd7070Spatrick // FIXME: Count angle brackets, and clear MightBeTemplateArgument
1004e5dd7070Spatrick // if all angles are closed.
1005e5dd7070Spatrick if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks,
1006e5dd7070Spatrick /*StopAtSemi=*/true,
1007e5dd7070Spatrick /*ConsumeFinalToken=*/false)) {
1008e5dd7070Spatrick // We're not just missing the initializer, we're also missing the
1009e5dd7070Spatrick // function body!
1010e5dd7070Spatrick return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;
1011e5dd7070Spatrick }
1012e5dd7070Spatrick } else if (Tok.isNot(tok::l_paren) && Tok.isNot(tok::l_brace)) {
1013e5dd7070Spatrick // We found something weird in a mem-initializer-id.
1014e5dd7070Spatrick if (getLangOpts().CPlusPlus11)
1015e5dd7070Spatrick return Diag(Tok.getLocation(), diag::err_expected_either)
1016e5dd7070Spatrick << tok::l_paren << tok::l_brace;
1017e5dd7070Spatrick else
1018e5dd7070Spatrick return Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
1019e5dd7070Spatrick }
1020e5dd7070Spatrick
1021e5dd7070Spatrick tok::TokenKind kind = Tok.getKind();
1022e5dd7070Spatrick Toks.push_back(Tok);
1023e5dd7070Spatrick bool IsLParen = (kind == tok::l_paren);
1024e5dd7070Spatrick SourceLocation OpenLoc = Tok.getLocation();
1025e5dd7070Spatrick
1026e5dd7070Spatrick if (IsLParen) {
1027e5dd7070Spatrick ConsumeParen();
1028e5dd7070Spatrick } else {
1029e5dd7070Spatrick assert(kind == tok::l_brace && "Must be left paren or brace here.");
1030e5dd7070Spatrick ConsumeBrace();
1031e5dd7070Spatrick // In C++03, this has to be the start of the function body, which
1032e5dd7070Spatrick // means the initializer is malformed; we'll diagnose it later.
1033e5dd7070Spatrick if (!getLangOpts().CPlusPlus11)
1034e5dd7070Spatrick return false;
1035e5dd7070Spatrick
1036e5dd7070Spatrick const Token &PreviousToken = Toks[Toks.size() - 2];
1037e5dd7070Spatrick if (!MightBeTemplateArgument &&
1038e5dd7070Spatrick !PreviousToken.isOneOf(tok::identifier, tok::greater,
1039e5dd7070Spatrick tok::greatergreater)) {
1040e5dd7070Spatrick // If the opening brace is not preceded by one of these tokens, we are
1041e5dd7070Spatrick // missing the mem-initializer-id. In order to recover better, we need
1042e5dd7070Spatrick // to use heuristics to determine if this '{' is most likely the
1043e5dd7070Spatrick // beginning of a brace-init-list or the function body.
1044e5dd7070Spatrick // Check the token after the corresponding '}'.
1045e5dd7070Spatrick TentativeParsingAction PA(*this);
1046e5dd7070Spatrick if (SkipUntil(tok::r_brace) &&
1047e5dd7070Spatrick !Tok.isOneOf(tok::comma, tok::ellipsis, tok::l_brace)) {
1048e5dd7070Spatrick // Consider there was a malformed initializer and this is the start
1049e5dd7070Spatrick // of the function body. We'll diagnose it later.
1050e5dd7070Spatrick PA.Revert();
1051e5dd7070Spatrick return false;
1052e5dd7070Spatrick }
1053e5dd7070Spatrick PA.Revert();
1054e5dd7070Spatrick }
1055e5dd7070Spatrick }
1056e5dd7070Spatrick
1057e5dd7070Spatrick // Grab the initializer (or the subexpression of the template argument).
1058e5dd7070Spatrick // FIXME: If we support lambdas here, we'll need to set StopAtSemi to false
1059e5dd7070Spatrick // if we might be inside the braces of a lambda-expression.
1060e5dd7070Spatrick tok::TokenKind CloseKind = IsLParen ? tok::r_paren : tok::r_brace;
1061e5dd7070Spatrick if (!ConsumeAndStoreUntil(CloseKind, Toks, /*StopAtSemi=*/true)) {
1062e5dd7070Spatrick Diag(Tok, diag::err_expected) << CloseKind;
1063e5dd7070Spatrick Diag(OpenLoc, diag::note_matching) << kind;
1064e5dd7070Spatrick return true;
1065e5dd7070Spatrick }
1066e5dd7070Spatrick
1067e5dd7070Spatrick // Grab pack ellipsis, if present.
1068e5dd7070Spatrick if (Tok.is(tok::ellipsis)) {
1069e5dd7070Spatrick Toks.push_back(Tok);
1070e5dd7070Spatrick ConsumeToken();
1071e5dd7070Spatrick }
1072e5dd7070Spatrick
1073e5dd7070Spatrick // If we know we just consumed a mem-initializer, we must have ',' or '{'
1074e5dd7070Spatrick // next.
1075e5dd7070Spatrick if (Tok.is(tok::comma)) {
1076e5dd7070Spatrick Toks.push_back(Tok);
1077e5dd7070Spatrick ConsumeToken();
1078e5dd7070Spatrick } else if (Tok.is(tok::l_brace)) {
1079e5dd7070Spatrick // This is the function body if the ')' or '}' is immediately followed by
1080e5dd7070Spatrick // a '{'. That cannot happen within a template argument, apart from the
1081e5dd7070Spatrick // case where a template argument contains a compound literal:
1082e5dd7070Spatrick //
1083e5dd7070Spatrick // S ( ) : a < b < c > ( d ) { }
1084e5dd7070Spatrick // // End of declaration, or still inside the template argument?
1085e5dd7070Spatrick //
1086e5dd7070Spatrick // ... and the case where the template argument contains a lambda:
1087e5dd7070Spatrick //
1088e5dd7070Spatrick // S ( ) : a < 0 && b < c > ( d ) + [ ] ( ) { return 0; }
1089e5dd7070Spatrick // ( ) > ( ) { }
1090e5dd7070Spatrick //
1091e5dd7070Spatrick // FIXME: Disambiguate these cases. Note that the latter case is probably
1092e5dd7070Spatrick // going to be made ill-formed by core issue 1607.
1093e5dd7070Spatrick Toks.push_back(Tok);
1094e5dd7070Spatrick ConsumeBrace();
1095e5dd7070Spatrick return false;
1096e5dd7070Spatrick } else if (!MightBeTemplateArgument) {
1097e5dd7070Spatrick return Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
1098e5dd7070Spatrick << tok::comma;
1099e5dd7070Spatrick }
1100e5dd7070Spatrick }
1101e5dd7070Spatrick }
1102e5dd7070Spatrick
1103e5dd7070Spatrick /// Consume and store tokens from the '?' to the ':' in a conditional
1104e5dd7070Spatrick /// expression.
ConsumeAndStoreConditional(CachedTokens & Toks)1105e5dd7070Spatrick bool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) {
1106e5dd7070Spatrick // Consume '?'.
1107e5dd7070Spatrick assert(Tok.is(tok::question));
1108e5dd7070Spatrick Toks.push_back(Tok);
1109e5dd7070Spatrick ConsumeToken();
1110e5dd7070Spatrick
1111e5dd7070Spatrick while (Tok.isNot(tok::colon)) {
1112e5dd7070Spatrick if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks,
1113e5dd7070Spatrick /*StopAtSemi=*/true,
1114e5dd7070Spatrick /*ConsumeFinalToken=*/false))
1115e5dd7070Spatrick return false;
1116e5dd7070Spatrick
1117e5dd7070Spatrick // If we found a nested conditional, consume it.
1118e5dd7070Spatrick if (Tok.is(tok::question) && !ConsumeAndStoreConditional(Toks))
1119e5dd7070Spatrick return false;
1120e5dd7070Spatrick }
1121e5dd7070Spatrick
1122e5dd7070Spatrick // Consume ':'.
1123e5dd7070Spatrick Toks.push_back(Tok);
1124e5dd7070Spatrick ConsumeToken();
1125e5dd7070Spatrick return true;
1126e5dd7070Spatrick }
1127e5dd7070Spatrick
1128e5dd7070Spatrick /// A tentative parsing action that can also revert token annotations.
1129e5dd7070Spatrick class Parser::UnannotatedTentativeParsingAction : public TentativeParsingAction {
1130e5dd7070Spatrick public:
UnannotatedTentativeParsingAction(Parser & Self,tok::TokenKind EndKind)1131e5dd7070Spatrick explicit UnannotatedTentativeParsingAction(Parser &Self,
1132e5dd7070Spatrick tok::TokenKind EndKind)
1133e5dd7070Spatrick : TentativeParsingAction(Self), Self(Self), EndKind(EndKind) {
1134e5dd7070Spatrick // Stash away the old token stream, so we can restore it once the
1135e5dd7070Spatrick // tentative parse is complete.
1136e5dd7070Spatrick TentativeParsingAction Inner(Self);
1137e5dd7070Spatrick Self.ConsumeAndStoreUntil(EndKind, Toks, true, /*ConsumeFinalToken*/false);
1138e5dd7070Spatrick Inner.Revert();
1139e5dd7070Spatrick }
1140e5dd7070Spatrick
RevertAnnotations()1141e5dd7070Spatrick void RevertAnnotations() {
1142e5dd7070Spatrick Revert();
1143e5dd7070Spatrick
1144e5dd7070Spatrick // Put back the original tokens.
1145e5dd7070Spatrick Self.SkipUntil(EndKind, StopAtSemi | StopBeforeMatch);
1146e5dd7070Spatrick if (Toks.size()) {
1147e5dd7070Spatrick auto Buffer = std::make_unique<Token[]>(Toks.size());
1148e5dd7070Spatrick std::copy(Toks.begin() + 1, Toks.end(), Buffer.get());
1149e5dd7070Spatrick Buffer[Toks.size() - 1] = Self.Tok;
1150e5dd7070Spatrick Self.PP.EnterTokenStream(std::move(Buffer), Toks.size(), true,
1151e5dd7070Spatrick /*IsReinject*/ true);
1152e5dd7070Spatrick
1153e5dd7070Spatrick Self.Tok = Toks.front();
1154e5dd7070Spatrick }
1155e5dd7070Spatrick }
1156e5dd7070Spatrick
1157e5dd7070Spatrick private:
1158e5dd7070Spatrick Parser &Self;
1159e5dd7070Spatrick CachedTokens Toks;
1160e5dd7070Spatrick tok::TokenKind EndKind;
1161e5dd7070Spatrick };
1162e5dd7070Spatrick
1163e5dd7070Spatrick /// ConsumeAndStoreInitializer - Consume and store the token at the passed token
1164e5dd7070Spatrick /// container until the end of the current initializer expression (either a
1165e5dd7070Spatrick /// default argument or an in-class initializer for a non-static data member).
1166e5dd7070Spatrick ///
1167e5dd7070Spatrick /// Returns \c true if we reached the end of something initializer-shaped,
1168e5dd7070Spatrick /// \c false if we bailed out.
ConsumeAndStoreInitializer(CachedTokens & Toks,CachedInitKind CIK)1169e5dd7070Spatrick bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
1170e5dd7070Spatrick CachedInitKind CIK) {
1171e5dd7070Spatrick // We always want this function to consume at least one token if not at EOF.
1172e5dd7070Spatrick bool IsFirstToken = true;
1173e5dd7070Spatrick
1174e5dd7070Spatrick // Number of possible unclosed <s we've seen so far. These might be templates,
1175e5dd7070Spatrick // and might not, but if there were none of them (or we know for sure that
1176e5dd7070Spatrick // we're within a template), we can avoid a tentative parse.
1177e5dd7070Spatrick unsigned AngleCount = 0;
1178e5dd7070Spatrick unsigned KnownTemplateCount = 0;
1179e5dd7070Spatrick
1180*12c85518Srobert while (true) {
1181e5dd7070Spatrick switch (Tok.getKind()) {
1182e5dd7070Spatrick case tok::comma:
1183e5dd7070Spatrick // If we might be in a template, perform a tentative parse to check.
1184e5dd7070Spatrick if (!AngleCount)
1185e5dd7070Spatrick // Not a template argument: this is the end of the initializer.
1186e5dd7070Spatrick return true;
1187e5dd7070Spatrick if (KnownTemplateCount)
1188e5dd7070Spatrick goto consume_token;
1189e5dd7070Spatrick
1190e5dd7070Spatrick // We hit a comma inside angle brackets. This is the hard case. The
1191e5dd7070Spatrick // rule we follow is:
1192e5dd7070Spatrick // * For a default argument, if the tokens after the comma form a
1193e5dd7070Spatrick // syntactically-valid parameter-declaration-clause, in which each
1194e5dd7070Spatrick // parameter has an initializer, then this comma ends the default
1195e5dd7070Spatrick // argument.
1196e5dd7070Spatrick // * For a default initializer, if the tokens after the comma form a
1197e5dd7070Spatrick // syntactically-valid init-declarator-list, then this comma ends
1198e5dd7070Spatrick // the default initializer.
1199e5dd7070Spatrick {
1200e5dd7070Spatrick UnannotatedTentativeParsingAction PA(*this,
1201e5dd7070Spatrick CIK == CIK_DefaultInitializer
1202e5dd7070Spatrick ? tok::semi : tok::r_paren);
1203e5dd7070Spatrick Sema::TentativeAnalysisScope Scope(Actions);
1204e5dd7070Spatrick
1205e5dd7070Spatrick TPResult Result = TPResult::Error;
1206e5dd7070Spatrick ConsumeToken();
1207e5dd7070Spatrick switch (CIK) {
1208e5dd7070Spatrick case CIK_DefaultInitializer:
1209e5dd7070Spatrick Result = TryParseInitDeclaratorList();
1210e5dd7070Spatrick // If we parsed a complete, ambiguous init-declarator-list, this
1211e5dd7070Spatrick // is only syntactically-valid if it's followed by a semicolon.
1212e5dd7070Spatrick if (Result == TPResult::Ambiguous && Tok.isNot(tok::semi))
1213e5dd7070Spatrick Result = TPResult::False;
1214e5dd7070Spatrick break;
1215e5dd7070Spatrick
1216e5dd7070Spatrick case CIK_DefaultArgument:
1217e5dd7070Spatrick bool InvalidAsDeclaration = false;
1218e5dd7070Spatrick Result = TryParseParameterDeclarationClause(
1219e5dd7070Spatrick &InvalidAsDeclaration, /*VersusTemplateArg=*/true);
1220e5dd7070Spatrick // If this is an expression or a declaration with a missing
1221e5dd7070Spatrick // 'typename', assume it's not a declaration.
1222e5dd7070Spatrick if (Result == TPResult::Ambiguous && InvalidAsDeclaration)
1223e5dd7070Spatrick Result = TPResult::False;
1224e5dd7070Spatrick break;
1225e5dd7070Spatrick }
1226e5dd7070Spatrick
1227ec727ea7Spatrick // Put the token stream back and undo any annotations we performed
1228ec727ea7Spatrick // after the comma. They may reflect a different parse than the one
1229ec727ea7Spatrick // we will actually perform at the end of the class.
1230e5dd7070Spatrick PA.RevertAnnotations();
1231ec727ea7Spatrick
1232ec727ea7Spatrick // If what follows could be a declaration, it is a declaration.
1233ec727ea7Spatrick if (Result != TPResult::False && Result != TPResult::Error)
1234ec727ea7Spatrick return true;
1235e5dd7070Spatrick }
1236e5dd7070Spatrick
1237e5dd7070Spatrick // Keep going. We know we're inside a template argument list now.
1238e5dd7070Spatrick ++KnownTemplateCount;
1239e5dd7070Spatrick goto consume_token;
1240e5dd7070Spatrick
1241e5dd7070Spatrick case tok::eof:
1242e5dd7070Spatrick case tok::annot_module_begin:
1243e5dd7070Spatrick case tok::annot_module_end:
1244e5dd7070Spatrick case tok::annot_module_include:
1245e5dd7070Spatrick // Ran out of tokens.
1246e5dd7070Spatrick return false;
1247e5dd7070Spatrick
1248e5dd7070Spatrick case tok::less:
1249e5dd7070Spatrick // FIXME: A '<' can only start a template-id if it's preceded by an
1250e5dd7070Spatrick // identifier, an operator-function-id, or a literal-operator-id.
1251e5dd7070Spatrick ++AngleCount;
1252e5dd7070Spatrick goto consume_token;
1253e5dd7070Spatrick
1254e5dd7070Spatrick case tok::question:
1255e5dd7070Spatrick // In 'a ? b : c', 'b' can contain an unparenthesized comma. If it does,
1256e5dd7070Spatrick // that is *never* the end of the initializer. Skip to the ':'.
1257e5dd7070Spatrick if (!ConsumeAndStoreConditional(Toks))
1258e5dd7070Spatrick return false;
1259e5dd7070Spatrick break;
1260e5dd7070Spatrick
1261e5dd7070Spatrick case tok::greatergreatergreater:
1262e5dd7070Spatrick if (!getLangOpts().CPlusPlus11)
1263e5dd7070Spatrick goto consume_token;
1264e5dd7070Spatrick if (AngleCount) --AngleCount;
1265e5dd7070Spatrick if (KnownTemplateCount) --KnownTemplateCount;
1266*12c85518Srobert [[fallthrough]];
1267e5dd7070Spatrick case tok::greatergreater:
1268e5dd7070Spatrick if (!getLangOpts().CPlusPlus11)
1269e5dd7070Spatrick goto consume_token;
1270e5dd7070Spatrick if (AngleCount) --AngleCount;
1271e5dd7070Spatrick if (KnownTemplateCount) --KnownTemplateCount;
1272*12c85518Srobert [[fallthrough]];
1273e5dd7070Spatrick case tok::greater:
1274e5dd7070Spatrick if (AngleCount) --AngleCount;
1275e5dd7070Spatrick if (KnownTemplateCount) --KnownTemplateCount;
1276e5dd7070Spatrick goto consume_token;
1277e5dd7070Spatrick
1278e5dd7070Spatrick case tok::kw_template:
1279e5dd7070Spatrick // 'template' identifier '<' is known to start a template argument list,
1280e5dd7070Spatrick // and can be used to disambiguate the parse.
1281e5dd7070Spatrick // FIXME: Support all forms of 'template' unqualified-id '<'.
1282e5dd7070Spatrick Toks.push_back(Tok);
1283e5dd7070Spatrick ConsumeToken();
1284e5dd7070Spatrick if (Tok.is(tok::identifier)) {
1285e5dd7070Spatrick Toks.push_back(Tok);
1286e5dd7070Spatrick ConsumeToken();
1287e5dd7070Spatrick if (Tok.is(tok::less)) {
1288e5dd7070Spatrick ++AngleCount;
1289e5dd7070Spatrick ++KnownTemplateCount;
1290e5dd7070Spatrick Toks.push_back(Tok);
1291e5dd7070Spatrick ConsumeToken();
1292e5dd7070Spatrick }
1293e5dd7070Spatrick }
1294e5dd7070Spatrick break;
1295e5dd7070Spatrick
1296e5dd7070Spatrick case tok::kw_operator:
1297e5dd7070Spatrick // If 'operator' precedes other punctuation, that punctuation loses
1298e5dd7070Spatrick // its special behavior.
1299e5dd7070Spatrick Toks.push_back(Tok);
1300e5dd7070Spatrick ConsumeToken();
1301e5dd7070Spatrick switch (Tok.getKind()) {
1302e5dd7070Spatrick case tok::comma:
1303e5dd7070Spatrick case tok::greatergreatergreater:
1304e5dd7070Spatrick case tok::greatergreater:
1305e5dd7070Spatrick case tok::greater:
1306e5dd7070Spatrick case tok::less:
1307e5dd7070Spatrick Toks.push_back(Tok);
1308e5dd7070Spatrick ConsumeToken();
1309e5dd7070Spatrick break;
1310e5dd7070Spatrick default:
1311e5dd7070Spatrick break;
1312e5dd7070Spatrick }
1313e5dd7070Spatrick break;
1314e5dd7070Spatrick
1315e5dd7070Spatrick case tok::l_paren:
1316e5dd7070Spatrick // Recursively consume properly-nested parens.
1317e5dd7070Spatrick Toks.push_back(Tok);
1318e5dd7070Spatrick ConsumeParen();
1319e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
1320e5dd7070Spatrick break;
1321e5dd7070Spatrick case tok::l_square:
1322e5dd7070Spatrick // Recursively consume properly-nested square brackets.
1323e5dd7070Spatrick Toks.push_back(Tok);
1324e5dd7070Spatrick ConsumeBracket();
1325e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false);
1326e5dd7070Spatrick break;
1327e5dd7070Spatrick case tok::l_brace:
1328e5dd7070Spatrick // Recursively consume properly-nested braces.
1329e5dd7070Spatrick Toks.push_back(Tok);
1330e5dd7070Spatrick ConsumeBrace();
1331e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
1332e5dd7070Spatrick break;
1333e5dd7070Spatrick
1334e5dd7070Spatrick // Okay, we found a ']' or '}' or ')', which we think should be balanced.
1335e5dd7070Spatrick // Since the user wasn't looking for this token (if they were, it would
1336e5dd7070Spatrick // already be handled), this isn't balanced. If there is a LHS token at a
1337e5dd7070Spatrick // higher level, we will assume that this matches the unbalanced token
1338e5dd7070Spatrick // and return it. Otherwise, this is a spurious RHS token, which we
1339e5dd7070Spatrick // consume and pass on to downstream code to diagnose.
1340e5dd7070Spatrick case tok::r_paren:
1341e5dd7070Spatrick if (CIK == CIK_DefaultArgument)
1342e5dd7070Spatrick return true; // End of the default argument.
1343e5dd7070Spatrick if (ParenCount && !IsFirstToken)
1344e5dd7070Spatrick return false;
1345e5dd7070Spatrick Toks.push_back(Tok);
1346e5dd7070Spatrick ConsumeParen();
1347e5dd7070Spatrick continue;
1348e5dd7070Spatrick case tok::r_square:
1349e5dd7070Spatrick if (BracketCount && !IsFirstToken)
1350e5dd7070Spatrick return false;
1351e5dd7070Spatrick Toks.push_back(Tok);
1352e5dd7070Spatrick ConsumeBracket();
1353e5dd7070Spatrick continue;
1354e5dd7070Spatrick case tok::r_brace:
1355e5dd7070Spatrick if (BraceCount && !IsFirstToken)
1356e5dd7070Spatrick return false;
1357e5dd7070Spatrick Toks.push_back(Tok);
1358e5dd7070Spatrick ConsumeBrace();
1359e5dd7070Spatrick continue;
1360e5dd7070Spatrick
1361e5dd7070Spatrick case tok::code_completion:
1362e5dd7070Spatrick Toks.push_back(Tok);
1363e5dd7070Spatrick ConsumeCodeCompletionToken();
1364e5dd7070Spatrick break;
1365e5dd7070Spatrick
1366e5dd7070Spatrick case tok::string_literal:
1367e5dd7070Spatrick case tok::wide_string_literal:
1368e5dd7070Spatrick case tok::utf8_string_literal:
1369e5dd7070Spatrick case tok::utf16_string_literal:
1370e5dd7070Spatrick case tok::utf32_string_literal:
1371e5dd7070Spatrick Toks.push_back(Tok);
1372e5dd7070Spatrick ConsumeStringToken();
1373e5dd7070Spatrick break;
1374e5dd7070Spatrick case tok::semi:
1375e5dd7070Spatrick if (CIK == CIK_DefaultInitializer)
1376e5dd7070Spatrick return true; // End of the default initializer.
1377*12c85518Srobert [[fallthrough]];
1378e5dd7070Spatrick default:
1379e5dd7070Spatrick consume_token:
1380e5dd7070Spatrick Toks.push_back(Tok);
1381e5dd7070Spatrick ConsumeToken();
1382e5dd7070Spatrick break;
1383e5dd7070Spatrick }
1384e5dd7070Spatrick IsFirstToken = false;
1385e5dd7070Spatrick }
1386e5dd7070Spatrick }
1387