[PATCH] Don't crash on reporting lambda diagnostics

Aaron Ballman aaron at aaronballman.com
Wed Apr 29 11:04:09 PDT 2015


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).

~Aaron

>
> On Wed, Apr 29, 2015 at 10:09 AM, Aaron Ballman <aaron at aaronballman.com>
> wrote:
>>
>> Ping
>>
>> On Thu, Apr 23, 2015 at 11:31 AM, Aaron Ballman <aaron at aaronballman.com>
>> wrote:
>> > Ping
>> >
>> > On Fri, Apr 10, 2015 at 10:08 AM, Aaron Ballman <aaron at aaronballman.com>
>> > wrote:
>> >> PR23021 demonstrates a case where diagnostic reporting on an inner
>> >> lambda would crash due to a null pointer dereference. Since captures
>> >> happen from calling ParseParameterDeclarationClause, which is before
>> >> the semantic lambda object is created, another mechanism is required
>> >> to get the lambda introducer location.
>> >>
>> >> This patch addresses it by storing the introducer location into the
>> >> scope object directly, and using that location when reporting the
>> >> diagnostics. The result is the same, but no longer relies on a lambda
>> >> object being created first.
>> >>
>> >> ~Aaron
>
>



More information about the cfe-commits mailing list