<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Apr 29, 2015 at 1:58 PM, Aaron Ballman <span dir="ltr"><<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Wed, Apr 29, 2015 at 4:54 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>> wrote:<br>
> On Wed, Apr 29, 2015 at 1:37 PM, Aaron Ballman <<a href="mailto:aaron@aaronballman.com">aaron@aaronballman.com</a>><br>
> wrote:<br>
>><br>
>> On Wed, Apr 29, 2015 at 3:31 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>><br>
>> wrote:<br>
>> > On Wed, Apr 29, 2015 at 11:04 AM, Aaron Ballman <<a href="mailto:aaron@aaronballman.com">aaron@aaronballman.com</a>><br>
>> > wrote:<br>
>> >><br>
>> >> On Wed, Apr 29, 2015 at 1:36 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>><br>
>> >> wrote:<br>
>> >> > Is the real problem that we're entering the lambda scope too early?<br>
>> >> > The<br>
>> >> > scope shoudn't start until we get to the body -- things referenced<br>
>> >> > from<br>
>> >> > within the parameter-declaration-clause of the inner lambda should<br>
>> >> > not<br>
>> >> > be<br>
>> >> > captured by it, so the LSI->Lambda pointer for the inner lambda<br>
>> >> > should<br>
>> >> > never<br>
>> >> > be referenced until we're ready to capture.<br>
>> >><br>
>> >> We're crashing on the following code:<br>
>> >><br>
>> >> template <int dimension><br>
>> >> class A;<br>
>> >><br>
>> >> int main ()<br>
>> >> {<br>
>> >>   const int dim = 3;<br>
>> >>   {<br>
>> >>     auto contraction = []() {<br>
>> >>       auto computeStrain = [](A<dim>& strain) {  };<br>
>> >>     };<br>
>> >>   }<br>
>> >> }<br>
>> >><br>
>> >> with a (partial) call stack of:<br>
>> >><br>
>> >>   clang.exe!clang::Sema::tryCaptureVariable(clang::VarDecl * Var,<br>
>> >> clang::SourceLocation ExprLoc, clang::Sema::TryCaptureKind Kind,<br>
>> >> clang::SourceLocation EllipsisLoc, bool BuildAndDiagnose,<br>
>> >> clang::QualType & CaptureType, clang::QualType & DeclRefType, const<br>
>> >> unsigned int * const FunctionScopeIndexToStopAt) Line 12883 C++<br>
>> >>   clang.exe!clang::MarkVarDeclODRUsed(clang::VarDecl * Var,<br>
>> >> clang::SourceLocation Loc, clang::Sema & SemaRef, const unsigned int *<br>
>> >> const FunctionScopeIndexToStopAt) Line 88 C++<br>
>> >>   clang.exe!clang::Sema::CleanupVarDeclMarking() Line 13047 C++<br>
>> >>   clang.exe!clang::Sema::PopExpressionEvaluationContext() Line 12009<br>
>> >> C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::EnterExpressionEvaluationContext::~EnterExpressionEvaluationContext()<br>
>> >> Line 8711 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseTemplateArgumentList(llvm::SmallVector<clang::ParsedTemplateArgument,16><br>
>> >> & TemplateArgs) Line 1252 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseTemplateIdAfterTemplateName(clang::OpaquePtr<clang::TemplateName><br>
>> >> Template, clang::SourceLocation TemplateNameLoc, const<br>
>> >> clang::CXXScopeSpec & SS, bool ConsumeLastToken, clang::SourceLocation<br>
>> >> & LAngleLoc, llvm::SmallVector<clang::ParsedTemplateArgument,16> &<br>
>> >> TemplateArgs, clang::SourceLocation & RAngleLoc) Line 876 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::AnnotateTemplateIdToken(clang::OpaquePtr<clang::TemplateName><br>
>> >> Template, clang::TemplateNameKind TNK, clang::CXXScopeSpec & SS,<br>
>> >> clang::SourceLocation TemplateKWLoc, clang::UnqualifiedId &<br>
>> >> TemplateName, bool AllowTypeAnnotation) Line 947 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseOptionalCXXScopeSpecifier(clang::CXXScopeSpec<br>
>> >> & SS, clang::OpaquePtr<clang::QualType> ObjectType, bool<br>
>> >> EnteringContext, bool * MayBePseudoDestructor, bool IsTypename,<br>
>> >> clang::IdentifierInfo * * LastII) Line 541 C++<br>
>> >>   clang.exe!clang::Parser::TryAnnotateCXXScopeToken(bool<br>
>> >> EnteringContext) Line 1691 C++<br>
>> >>   clang.exe!clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec<br>
>> >> & DS, const clang::Parser::ParsedTemplateInfo & TemplateInfo,<br>
>> >> clang::AccessSpecifier AS, clang::Parser::DeclSpecContext DSContext,<br>
>> >> clang::Parser::LateParsedAttrList * LateAttrs) Line 2898 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseParameterDeclarationClause(clang::Declarator<br>
>> >> & D, clang::ParsedAttributes & FirstArgAttrs,<br>
>> >> llvm::SmallVectorImpl<clang::DeclaratorChunk::ParamInfo> & ParamInfo,<br>
>> >> clang::SourceLocation & EllipsisLoc) Line 5652 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseLambdaExpressionAfterIntroducer(clang::LambdaIntroducer<br>
>> >> & Intro) Line 1086 C++<br>
>> >>   clang.exe!clang::Parser::ParseLambdaExpression() Line 729 C++<br>
>> >>   clang.exe!clang::Parser::ParseCastExpression(bool isUnaryExpression,<br>
>> >> bool isAddressOfOperand, bool & NotCastExpr,<br>
>> >> clang::Parser::TypeCastState isTypeCast) Line 1283 C++<br>
>> >>   clang.exe!clang::Parser::ParseCastExpression(bool isUnaryExpression,<br>
>> >> bool isAddressOfOperand, clang::Parser::TypeCastState isTypeCast) Line<br>
>> >> 441 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState<br>
>> >> isTypeCast) Line 170 C++<br>
>> >>   clang.exe!clang::Parser::ParseInitializer() Line 1522 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator<br>
>> >> & D, const clang::Parser::ParsedTemplateInfo & TemplateInfo,<br>
>> >> clang::Parser::ForRangeInit * FRI) Line 1998 C++<br>
>> >>   clang.exe!clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec & DS,<br>
>> >> unsigned int Context, clang::SourceLocation * DeclEnd,<br>
>> >> clang::Parser::ForRangeInit * FRI) Line 1783 C++<br>
>> >>   clang.exe!clang::Parser::ParseSimpleDeclaration(unsigned int<br>
>> >> Context, clang::SourceLocation & DeclEnd,<br>
>> >> clang::Parser::ParsedAttributesWithRange & Attrs, bool RequireSemi,<br>
>> >> clang::Parser::ForRangeInit * FRI) Line 1514 C++<br>
>> >>   clang.exe!clang::Parser::ParseDeclaration(unsigned int Context,<br>
>> >> clang::SourceLocation & DeclEnd,<br>
>> >> clang::Parser::ParsedAttributesWithRange & attrs) Line 1459 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt<br>
>> >> *,32> & Stmts, bool OnlyStatement, clang::SourceLocation *<br>
>> >> TrailingElseLoc, clang::Parser::ParsedAttributesWithRange & Attrs)<br>
>> >> Line 212 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt<br>
>> >> *,32> & Stmts, bool OnlyStatement, clang::SourceLocation *<br>
>> >> TrailingElseLoc) Line 110 C++<br>
>> >>   clang.exe!clang::Parser::ParseCompoundStatementBody(bool isStmtExpr)<br>
>> >> Line 958 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseLambdaExpressionAfterIntroducer(clang::LambdaIntroducer<br>
>> >> & Intro) Line 1249 C++<br>
>> >>   clang.exe!clang::Parser::ParseLambdaExpression() Line 729 C++<br>
>> >>   clang.exe!clang::Parser::ParseCastExpression(bool isUnaryExpression,<br>
>> >> bool isAddressOfOperand, bool & NotCastExpr,<br>
>> >> clang::Parser::TypeCastState isTypeCast) Line 1283 C++<br>
>> >>   clang.exe!clang::Parser::ParseCastExpression(bool isUnaryExpression,<br>
>> >> bool isAddressOfOperand, clang::Parser::TypeCastState isTypeCast) Line<br>
>> >> 441 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState<br>
>> >> isTypeCast) Line 170 C++<br>
>> >>   clang.exe!clang::Parser::ParseInitializer() Line 1522 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator<br>
>> >> & D, const clang::Parser::ParsedTemplateInfo & TemplateInfo,<br>
>> >> clang::Parser::ForRangeInit * FRI) Line 1998 C++<br>
>> >>   clang.exe!clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec & DS,<br>
>> >> unsigned int Context, clang::SourceLocation * DeclEnd,<br>
>> >> clang::Parser::ForRangeInit * FRI) Line 1783 C++<br>
>> >>   clang.exe!clang::Parser::ParseSimpleDeclaration(unsigned int<br>
>> >> Context, clang::SourceLocation & DeclEnd,<br>
>> >> clang::Parser::ParsedAttributesWithRange & Attrs, bool RequireSemi,<br>
>> >> clang::Parser::ForRangeInit * FRI) Line 1514 C++<br>
>> >>   clang.exe!clang::Parser::ParseDeclaration(unsigned int Context,<br>
>> >> clang::SourceLocation & DeclEnd,<br>
>> >> clang::Parser::ParsedAttributesWithRange & attrs) Line 1459 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt<br>
>> >> *,32> & Stmts, bool OnlyStatement, clang::SourceLocation *<br>
>> >> TrailingElseLoc, clang::Parser::ParsedAttributesWithRange & Attrs)<br>
>> >> Line 212 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt<br>
>> >> *,32> & Stmts, bool OnlyStatement, clang::SourceLocation *<br>
>> >> TrailingElseLoc) Line 110 C++<br>
>> >>   clang.exe!clang::Parser::ParseCompoundStatementBody(bool isStmtExpr)<br>
>> >> Line 958 C++<br>
>> >>   clang.exe!clang::Parser::ParseCompoundStatement(bool isStmtExpr,<br>
>> >> unsigned int ScopeFlags) Line 844 C++<br>
>> >>   clang.exe!clang::Parser::ParseCompoundStatement(bool isStmtExpr) Line<br>
>> >> 810 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt<br>
>> >> *,32> & Stmts, bool OnlyStatement, clang::SourceLocation *<br>
>> >> TrailingElseLoc, clang::Parser::ParsedAttributesWithRange & Attrs)<br>
>> >> Line 229 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt<br>
>> >> *,32> & Stmts, bool OnlyStatement, clang::SourceLocation *<br>
>> >> TrailingElseLoc) Line 110 C++<br>
>> >>   clang.exe!clang::Parser::ParseCompoundStatementBody(bool isStmtExpr)<br>
>> >> Line 958 C++<br>
>> >>   clang.exe!clang::Parser::ParseFunctionStatementBody(clang::Decl *<br>
>> >> Decl, clang::Parser::ParseScope & BodyScope) Line 1876 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator<br>
>> >> & D, const clang::Parser::ParsedTemplateInfo & TemplateInfo,<br>
>> >> clang::Parser::LateParsedAttrList * LateParsedAttrs) Line 1104 C++<br>
>> >>   clang.exe!clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec & DS,<br>
>> >> unsigned int Context, clang::SourceLocation * DeclEnd,<br>
>> >> clang::Parser::ForRangeInit * FRI) Line 1729 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange<br>
>> >> & attrs, clang::ParsingDeclSpec & DS, clang::AccessSpecifier AS) Line<br>
>> >> 893 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange<br>
>> >> & attrs, clang::ParsingDeclSpec * DS, clang::AccessSpecifier AS) Line<br>
>> >> 909 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange<br>
>> >> & attrs, clang::ParsingDeclSpec * DS) Line 767 C++<br>
>> >><br>
>> >><br>
>> >> clang.exe!clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef><br>
>> >> & Result) Line 569 C++<br>
>> >>   clang.exe!clang::ParseAST(clang::Sema & S, bool PrintStats, bool<br>
>> >> SkipFunctionBodies) Line 144 C++<br>
>> >><br>
>> >> So it looks like we're trying to do an implicit capture of the<br>
>> >> template argument "dim" within the parameter declaration, and<br>
>> >> attempting to diagnose the location using the lambda scope information<br>
>> >> (which is null, and winds up crashing).<br>
>> ><br>
>> ><br>
>> > Right, but there should not be any lambda scope information for the<br>
>> > inner<br>
>> > lambda yet, because we have not yet entered its scope, right? Our<br>
>> > current<br>
>> > lambda should still be the outer one.<br>
>><br>
>> We have entered its scope, but we've not generated any useful scope<br>
>> information. See ParseLambaExpressionAfterIntroducer, around line<br>
>> 1062, that's where we push the lambda scope onto the stack. So we're<br>
>> definitely not pushing that scope when we hit the body. If I move it<br>
>> down to where we act on the start of the lambda definition itself (for<br>
>> parsing the body), I get a lot of llvm_unreachables from<br>
>> RecordParsingTemplateParameterDepth being called in<br>
>> ParseLambaExpressionAfterIntroducer.<br>
><br>
><br>
> I'm not surprised that there's code that relies on us getting this wrong =)<br>
<br>
</div></div>Okay, so it sounds like the correct fix is to change where the scope<br>
is pushed onto the scope stack, and then fix all of the fallout from<br>
that?</blockquote><div><br></div><div>I think so, yes, unless there's a reason that's unworkable.</div></div></div></div>