This is an archive of the discontinued LLVM Phabricator instance.

lambdas in modules: change storage for LambdaDefinitionData
Needs ReviewPublic

Authored by elsteveogrande on Aug 19 2018, 1:37 PM.

Details

Summary

Previously LambdaDefinitionData extended DefinitionData and either might have been used interchangably in a CXXRecordDecl's DefinitionData field.

However there are cases where LambdaDefinitionData ("LDD") aren't copied or moved completely, into this DefinitionData ("DD") field, as it has additional members of its own.

This patch:

  • makes LDD a separate structure, no longer using DD as the base class, but otherwise kept the same so as to encapsulate lambda stuff properly
  • stores lambda data within an Optional called LambdaData
  • replaces IsLambda bit with bool isLambda() const, true IFF lambda data are present in that optional field
  • as the formerly-subclass's LDD constructor set some members on DD, this is now done in a new method SetLambdaData; this sets those fields to values sensible for lambdas, and emplaces lambda data in the optional field

This solves one case where lambda data were not handled quite properly.

Note that this doesn't solve all lambda-handling in pcm's (clang modules) but is more of a refactoring pre-step.

Test Plan: ninja check-clang-modules

Diff Detail

Event Timeline

elsteveogrande created this revision.Aug 19 2018, 1:37 PM
elsteveogrande retitled this revision from Change how LambdaDefinitionData is stored to lambdas in modules: change storage for LambdaDefinitionData.

Rebase past dependency commit C341499, fix a conflict

rsmith added a comment.EditedSep 18 2018, 8:06 AM

We don't want to allocate storage for the lambda fields for non-lambda classes, which is why we use distinct definition data classes. Is the problem you're trying to solve here that we fake a definition in AST deserialization before we know whether the class is a lambda? If so, that seems solvable by moving the IsLambda flag out of DefinitionData into CXXRecordData (perhaps as a distinct TagTypeKind?).

elsteveogrande added inline comments.Sep 18 2018, 3:32 PM
lib/Serialization/ASTReaderDecl.cpp
1775

Hi @rsmith, thanks again for looking! This is the part that I was concerned about: that DD could be either a DefinitionData or LambdaDefinitionData reference; similar MergeDD. It didn't seem that move-assign was well-defined in the cases where they were mixed.

If their being different is completely unexpected, though, this whole thing could perhaps be an assertion that they are both lambda, or both not lambda. And an IsLambda field on the CXXRecordDecl` (or TTK_Lambda).

Alternatively, I could make the lambda data a pointer or std::unique_ptr<LambdaDefinitionData> inside DefinitionData (and maybe make the latter final), so as not to allocate much extra space in the non-lambda case.

Depends on whether a new tag type is not too much of a breaking change. Also, whether it's known at this point that this record is a lambda (and DD is already of the correct type).

Change Optional to unique_ptr instead, to at least save an allocation and keep the same semantics. Reverified with ninja check-clang.

I did try a copy of D50949 again, locally and without this diff, to see if I can avoid messing with this structure altogether. But then I get a SEGV.

The reason behind this diff is to try to make the logic a little safer, though it's probably still not bulletproof. It at least does seem to fix, or "fix" (i.e. hide) the crash below.

I admit I didn't take the time to really dig into that one, and I'm not yet experienced enough in Clang's code to do so confidently, so it's a bit scary to continue going down rabbit holes :)

But I'm happy to revise (or go fix that problem) if you think that's best. Thanks again!

Stack dump:
0.	Program arguments: /opt/llvm/build/bin/clang -cc1 -internal-isystem /opt/llvm/build/lib/clang/8.0.0/include -nostdsysteminc -fmodules -verify /opt/llvm/llvm/tools/clang/test/Modules/merge-lambdas.cpp -emit-llvm-only
1.	/opt/llvm/llvm/tools/clang/test/Modules/merge-lambdas.cpp:73:1: at annotation token
2.	/opt/llvm/build/tools/clang/test/Modules/PR38531.map:11:14: LLVM IR generation of declaration 'foo(Fun)::(anonymous class)::'
0  clang                    0x00000001032cffe8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1  clang                    0x00000001032cf165 llvm::sys::RunSignalHandlers() + 85
2  clang                    0x00000001032d05f2 SignalHandler(int) + 258
3  libsystem_platform.dylib 0x00007fff79709f5a _sigtramp + 26
4  libsystem_platform.dylib 0x00007ffeed8dbe3f _sigtramp + 1948065535
5  clang                    0x0000000104b865b1 (anonymous namespace)::CXXNameMangler::manglePrefix(clang::DeclContext const*, bool) + 545
6  clang                    0x0000000104b877d5 (anonymous namespace)::CXXNameMangler::mangleNestedName(clang::NamedDecl const*, clang::DeclContext const*, llvm::SmallVector<llvm::StringRef, 4u> const*, bool) + 453
7  clang                    0x0000000104b8733d (anonymous namespace)::CXXNameMangler::mangleLocalName(clang::Decl const*, llvm::SmallVector<llvm::StringRef, 4u> const*) + 1613
8  clang                    0x0000000104b77bf7 (anonymous namespace)::CXXNameMangler::mangleFunctionEncoding(clang::FunctionDecl const*) + 87
9  clang                    0x0000000104b760c5 (anonymous namespace)::ItaniumMangleContextImpl::mangleCXXCtor(clang::CXXConstructorDecl const*, clang::CXXCtorType, llvm::raw_ostream&) + 245
10 clang                    0x000000010368eb21 getMangledNameImpl(clang::CodeGen::CodeGenModule const&, clang::GlobalDecl, clang::NamedDecl const*, bool) + 305
11 clang                    0x000000010368a83b clang::CodeGen::CodeGenModule::getMangledName(clang::GlobalDecl) + 427
12 clang                    0x0000000103697135 clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) + 1941
13 clang                    0x00000001036f7529 (anonymous namespace)::ItaniumCXXABI::EmitCXXConstructors(clang::CXXConstructorDecl const*) + 41
14 clang                    0x000000010371401f (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) + 143
15 clang                    0x000000010367a151 clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) + 177
16 clang                    0x000000010367a244 clang::BackendConsumer::HandleInterestingDecl(clang::DeclGroupRef) + 20
17 clang                    0x000000010427c2db clang::ASTReader::PassInterestingDeclsToConsumer() + 123
18 clang                    0x0000000104243f8b clang::ASTReader::FinishedDeserializing() + 1867
19 clang                    0x000000010427be48 clang::ASTReader::ReadDeclRecord(unsigned int) + 2808
20 clang                    0x000000010422b219 non-virtual thunk to clang::ASTReader::GetExternalDecl(unsigned int) + 89
21 clang                    0x0000000104afe7a1 clang::RedeclarableTemplateDecl::loadLazySpecializationsImpl() const + 241
22 clang                    0x0000000104aff1dc clang::ClassTemplateDecl::findSpecialization(llvm::ArrayRef<clang::TemplateArgument>, void*&) + 28
23 clang                    0x00000001048096a2 clang::Sema::CheckTemplateIdType(clang::TemplateName, clang::SourceLocation, clang::TemplateArgumentListInfo&) + 1170
24 clang                    0x000000010480c900 clang::Sema::ActOnTemplateIdType(clang::CXXScopeSpec&, clang::SourceLocation, clang::OpaquePtr<clang::TemplateName>, clang::IdentifierInfo*, clang::SourceLocation, clang::SourceLocation, llvm::MutableArrayRef<clang::ParsedTemplateArgument>, clang::SourceLocation, bool, bool) + 1552
25 clang                    0x00000001041df3b1 clang::Parser::AnnotateTemplateIdTokenAsType(bool) + 129
26 clang                    0x000000010416449a clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, clang::Parser::DeclSpecContext, clang::Parser::LateParsedAttrList*) + 10410
27 clang                    0x00000001041eb69b clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec&, clang::AccessSpecifier) + 139
28 clang                    0x00000001041eb367 clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*, clang::AccessSpecifier) + 343
29 clang                    0x00000001041e9a99 clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) + 2521
30 clang                    0x00000001041e8bd0 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&) + 688
31 clang                    0x00000001041537a5 clang::ParseAST(clang::Sema&, bool, bool) + 453
32 clang                    0x00000001038a8ed3 clang::FrontendAction::Execute() + 67
33 clang                    0x00000001038650f8 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 1272
34 clang                    0x00000001038f9858 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 1688
35 clang                    0x0000000102326339 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) + 1401
36 clang                    0x00000001023243e0 main + 10320
37 libdyld.dylib            0x00007fff793fb015 start + 1
/opt/llvm/build/tools/clang/test/Modules/Output/merge-lambdas.cpp.script: line 1: 62496 Segmentation fault: 11  /opt/llvm/build/bin/clang -cc1 -internal-isystem /opt/llvm/build/lib/clang/8.0.0/include -nostdsysteminc -fmodules -verify /opt/llvm/llvm/tools/clang/test/Modules/merge-lambdas.cpp -emit-llvm-only