xref: /openbsd-src/gnu/llvm/clang/lib/Parse/ParseCXXInlineMethods.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
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