[PATCH] Don't crash on reporting lambda diagnostics

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


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?

~Aaron



More information about the cfe-commits mailing list