/// \brief Late parse a C++ function template in Microsoft mode. void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { if(!LMT.D) return; // Get the FunctionDecl. FunctionDecl *FD = 0; if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D)) FD = FunTmpl->getTemplatedDecl(); else FD = cast<FunctionDecl>(LMT.D); // To restore the context after late parsing. Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext); SmallVector<ParseScope*, 4> TemplateParamScopeStack; DeclaratorDecl* Declarator = dyn_cast<DeclaratorDecl>(FD); if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { TemplateParamScopeStack.push_back(new ParseScope(this, Scope::TemplateParamScope)); Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); } else { // Get the list of DeclContext to reenter. SmallVector<DeclContext*, 4> DeclContextToReenter; DeclContext *DD = FD->getLexicalParent(); while (DD && !DD->isTranslationUnit()) { DeclContextToReenter.push_back(DD); DD = DD->getLexicalParent(); } // Reenter template scopes from outmost to innermost. SmallVector<DeclContext*, 4>::reverse_iterator II = DeclContextToReenter.rbegin(); for (; II != DeclContextToReenter.rend(); ++II) { if (ClassTemplatePartialSpecializationDecl* MD = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) { TemplateParamScopeStack.push_back(new ParseScope(this, Scope::TemplateParamScope)); Actions.ActOnReenterTemplateScope(getCurScope(), MD); } else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(*II)) { TemplateParamScopeStack.push_back(new ParseScope(this, Scope::TemplateParamScope, MD->getDescribedClassTemplate() != 0 )); Actions.ActOnReenterTemplateScope(getCurScope(), MD->getDescribedClassTemplate()); } TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); Actions.PushDeclContext(Actions.getCurScope(), *II); } TemplateParamScopeStack.push_back(new ParseScope(this, Scope::TemplateParamScope)); Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); } assert(!LMT.Toks.empty() && "Empty body!"); // Append the current token at the end of the new token stream so that it // doesn't get lost. LMT.Toks.push_back(Tok); PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false); // Consume the previously pushed token. ConsumeAnyToken(); assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && "Inline method not starting with '{', ':' or 'try'"); // Parse the method body. Function body parsing code is similar enough // to be re-used for method bodies as well. ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); // Recreate the containing function DeclContext. Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FD)); if (FunctionTemplateDecl *FunctionTemplate = dyn_cast_or_null<FunctionTemplateDecl>(LMT.D)) Actions.ActOnStartOfFunctionDef(getCurScope(), FunctionTemplate->getTemplatedDecl()); if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(LMT.D)) Actions.ActOnStartOfFunctionDef(getCurScope(), Function); if (Tok.is(tok::kw_try)) { ParseFunctionTryBlock(LMT.D, FnScope); } else { if (Tok.is(tok::colon)) ParseConstructorInitializer(LMT.D); else Actions.ActOnDefaultCtorInitializers(LMT.D); if (Tok.is(tok::l_brace)) { ParseFunctionStatementBody(LMT.D, FnScope); Actions.MarkAsLateParsedTemplate(FD, false); } else Actions.ActOnFinishFunctionBody(LMT.D, 0); } // Exit scopes. FnScope.Exit(); SmallVector<ParseScope*, 4>::reverse_iterator I = TemplateParamScopeStack.rbegin(); for (; I != TemplateParamScopeStack.rend(); ++I) delete *I; DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D); if (grp) Actions.getASTConsumer().HandleTopLevelDecl(grp.get()); }
/// \brief Late parse a C++ function template in Microsoft mode. void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { if(!LMT.D) return; // If this is a member template, introduce the template parameter scope. ParseScope TemplateScope(this, Scope::TemplateParamScope); // Get the FunctionDecl. FunctionDecl *FD = 0; if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D)) FD = FunTmpl->getTemplatedDecl(); else FD = cast<FunctionDecl>(LMT.D); // Reinject the template parameters. DeclaratorDecl* Declarator = dyn_cast<DeclaratorDecl>(FD); if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); } else { Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); DeclContext *DD = FD->getLexicalParent(); while (DD && DD->isRecord()) { if (ClassTemplatePartialSpecializationDecl* MD = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(DD)) Actions.ActOnReenterTemplateScope(getCurScope(), MD); else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(DD)) Actions.ActOnReenterTemplateScope(getCurScope(), MD->getDescribedClassTemplate()); DD = DD->getLexicalParent(); } } assert(!LMT.Toks.empty() && "Empty body!"); // Append the current token at the end of the new token stream so that it // doesn't get lost. LMT.Toks.push_back(Tok); PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false); // Consume the previously pushed token. ConsumeAnyToken(); assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && "Inline method not starting with '{', ':' or 'try'"); // Parse the method body. Function body parsing code is similar enough // to be re-used for method bodies as well. ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); // Recreate the DeclContext. Sema::ContextRAII SavedContext(Actions, Actions.getContainingDC(FD)); if (FunctionTemplateDecl *FunctionTemplate = dyn_cast_or_null<FunctionTemplateDecl>(LMT.D)) Actions.ActOnStartOfFunctionDef(getCurScope(), FunctionTemplate->getTemplatedDecl()); if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(LMT.D)) Actions.ActOnStartOfFunctionDef(getCurScope(), Function); if (Tok.is(tok::kw_try)) { ParseFunctionTryBlock(LMT.D, FnScope); return; } if (Tok.is(tok::colon)) { ParseConstructorInitializer(LMT.D); // Error recovery. if (!Tok.is(tok::l_brace)) { Actions.ActOnFinishFunctionBody(LMT.D, 0); return; } } else Actions.ActOnDefaultCtorInitializers(LMT.D); ParseFunctionStatementBody(LMT.D, FnScope); Actions.MarkAsLateParsedTemplate(FD, false); DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D); if (grp) Actions.getASTConsumer().HandleTopLevelDecl(grp.get()); }