[cfe-commits] r151140 - in /cfe/trunk: lib/Parse/ParseTemplate.cpp test/Parser/DelayedTemplateParsing.cpp
Francois Pichet
pichet2000 at gmail.com
Wed Feb 22 00:25:53 PST 2012
Author: fpichet
Date: Wed Feb 22 02:25:53 2012
New Revision: 151140
URL: http://llvm.org/viewvc/llvm-project?rev=151140&view=rev
Log:
In -fdelayed-template-parsing mode, reenter every scope when late parsing a templated function; (Not just the template parameter scope as previously). Also enter the scope stack in the correct order.
Otherwise this breaks some invariant during name lookup especially when dealing with shadowed declaration
Fix PR11931.
Modified:
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/test/Parser/DelayedTemplateParsing.cpp
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=151140&r1=151139&r2=151140&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Feb 22 02:25:53 2012
@@ -1157,109 +1157,113 @@
llvm_unreachable("Late templated function without associated lexed tokens");
}
-
-/// \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.
- SmallVector<ParseScope*, 4> TemplateParamScopeStack;
- 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);
-
- // Get the list of DeclContext to reenter.
- SmallVector<DeclContext*, 4> DeclContextToReenter;
- DeclContext *DD = FD->getLexicalParent();
- while (DD && DD->isRecord()) {
- 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());
- }
- }
- }
- 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);
- } 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.
+
+/// \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());
+ 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 Lex a delayed template function for late parsing.
Modified: cfe/trunk/test/Parser/DelayedTemplateParsing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/DelayedTemplateParsing.cpp?rev=151140&r1=151139&r2=151140&view=diff
==============================================================================
--- cfe/trunk/test/Parser/DelayedTemplateParsing.cpp (original)
+++ cfe/trunk/test/Parser/DelayedTemplateParsing.cpp Wed Feb 22 02:25:53 2012
@@ -63,3 +63,30 @@
}
+
+namespace PR11931 {
+
+template <typename RunType>
+struct BindState;
+
+ template<>
+struct BindState<void(void*)> {
+ static void Run() { }
+};
+
+class Callback {
+public:
+ typedef void RunType();
+
+ template <typename RunType>
+ Callback(BindState<RunType> bind_state) {
+ BindState<RunType>::Run();
+ }
+};
+
+
+Callback Bind() {
+ return Callback(BindState<void(void*)>());
+}
+
+}
More information about the cfe-commits
mailing list