[PATCH] Don't crash on reporting lambda diagnostics

Richard Smith richard at metafoo.co.uk
Wed Apr 29 14:06:22 PDT 2015


On Wed, Apr 29, 2015 at 1:58 PM, Aaron Ballman <aaron at aaronballman.com>
wrote:

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


I think so, yes, unless there's a reason that's unworkable.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150429/526c1232/attachment.html>


More information about the cfe-commits mailing list