[PATCH] Don't crash on reporting lambda diagnostics

Richard Smith richard at metafoo.co.uk
Wed Apr 29 13:54:06 PDT 2015


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 =)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150429/8eb0ba59/attachment.html>


More information about the cfe-commits mailing list