[PATCH] Don't crash on reporting lambda diagnostics

Aaron Ballman aaron at aaronballman.com
Wed Apr 29 13:37:43 PDT 2015


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.

~Aaron



More information about the cfe-commits mailing list