-
Notifications
You must be signed in to change notification settings - Fork 0
Contracts nightly #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: contracts-base
Are you sure you want to change the base?
Conversation
…e initial implementation
The template stuff is a bit of a hack. I'm considering simply inserting the statements into the function body and letting the existing code handle the rest. Also add some cheaky diagnostics, fix a few name lookup bugs, and delete some old code.
There are also various experiements that need cleaning up, specifically around builtins and source location.
Some work on constification, but a bunch of experiment that still needs
to be undone.
The addition of -fclang-contract-groups=foo=<semantic>, which still
needs better integrating with -fcontract-evaluation-semantic=.
The [[clang::contract_group("foo.bar")]] stuff works really well.
I'll be happy to try it in libc++.
What still needs to be done includes:
* Coming up with a proper descriptor/format for the compiler-stl
interface. It seems to me we'll want the ABI to be able to evolve
over time, and so we should pass a pointer to data + data descriptor of
some kind so that the STL can parse version of the header from different
compilers & versions.
* Everything to do with parsing pre/post in inline member functions.
* Contract redeclaration checking.
* Constifying implicit this.
* Code gen & constant evaluation for result names (and representation
too).
* Cleanup around experiments for source location & constification.
…e initial implementation
The template stuff is a bit of a hack. I'm considering simply inserting the statements into the function body and letting the existing code handle the rest. Also add some cheaky diagnostics, fix a few name lookup bugs, and delete some old code.
There are also various experiements that need cleaning up, specifically around builtins and source location.
Some work on constification, but a bunch of experiment that still needs
to be undone.
The addition of -fclang-contract-groups=foo=<semantic>, which still
needs better integrating with -fcontract-evaluation-semantic=.
The [[clang::contract_group("foo.bar")]] stuff works really well.
I'll be happy to try it in libc++.
What still needs to be done includes:
* Coming up with a proper descriptor/format for the compiler-stl
interface. It seems to me we'll want the ABI to be able to evolve
over time, and so we should pass a pointer to data + data descriptor of
some kind so that the STL can parse version of the header from different
compilers & versions.
* Everything to do with parsing pre/post in inline member functions.
* Contract redeclaration checking.
* Constifying implicit this.
* Code gen & constant evaluation for result names (and representation
too).
* Cleanup around experiments for source location & constification.
This allows better versioning, and also prevents us from clobbering every registery. (though that latter case is likely not too impactful).
Also, re-enable the exception handling tentatively.
cor3ntin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am far from having done a complete pass, but here are some comments.
Chopping this in manageable pieces will be necessary I'm afraid, Github can barely render the PR and reviewers will be discouraged by the sheer size of it all.
Changes to source location could be a PR and then maybe we want to start with just contract_assert, even if i understand it would be annoying for you.
Non essentials (ast matchers for examples) can be separate PRs.
Everything lamba related can also be separated out.
I will keep reviewing today or tomorrow
|
|
||
| // Decl used to define the datastructure for the contract violation object | ||
| // used for C++ contracts | ||
| mutable Decl *BuiltinContractViolationRecordDecl = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to make that a RecordDecl directly?
| if (isa<DeclStmt, GenericSelectionExpr, RequiresExpr, | ||
| OpenACCWaitConstruct, SYCLKernelCallStmt>(S)) | ||
| OpenACCWaitConstruct, SYCLKernelCallStmt, ContractStmt>(S)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should just make expressions children. It's not yet clear to me why they should not be, as I do a linear read through
| /// int foo() post(r : r > 0); | ||
| /// | ||
| /// Where `r` refers to the value returned by the function | ||
| class ResultNameDecl : public ValueDecl { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be called ContractXXXX. Maybe ContractNamedReturnDecl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The result name decl is what's used in the spec, but I'm happy to add Contract to it.
clang/include/clang/AST/Decl.h
Outdated
| // qualifier, to be used for the (uncommon) case of out-of-line declarations | ||
| // and constrained function decls. | ||
| // qualifier, to be used for the (uncommon) case of out-of-line declarations, | ||
| // constrained function decls or functions with contracts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // constrained function decls or functions with contracts. | |
| // constrained function decls or functions with pre/post conditions. |
| // which are heavily based on AltiVec | ||
| // KEYBORLAND - This is a keyword if Borland extensions are enabled | ||
| // KEYCOROUTINES - This is a keyword if support for C++ coroutines is enabled | ||
| // KEYCONTRACTS - This is a keyword if support for C++ contracts is enabled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the upstream version I think
- we want to put contracts behind the C++26 flags
- allow them in all c++ versions (without flag) once they are a bit baked
| // C++ Contracts | ||
| defm contracts : BoolFOption<"contracts", | ||
| LangOpts<"Contracts">, DefaultFalse, | ||
| PosFlag<SetTrue, [], [ClangOption, CC1Option, CLOption], | ||
| "Enable support for C++ Contracts">, | ||
| NegFlag<SetFalse, [], [ClangOption, CC1Option]>>; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cf above, lets forgo that for now
| def fcontract_group_evaluation_semantic_EQ : CommaJoined<["-"], "fcontract-group-evaluation-semantic=">, | ||
| Visibility<[ClangOption, CC1Option]>, | ||
| HelpText<"Clang extension. Enable or disable contracts by group. The argument is a comma-separated " | ||
| "sequence of one or more group names, each prefixed by '+' or '-'.">; | ||
|
|
||
| defm contract_exceptions : BoolFOption<"contract-exceptions", | ||
| LangOpts<"ContractExceptions">, DefaultTrue, | ||
| PosFlag<SetTrue, [], [ClangOption], | ||
| "Enable contract violation on exception">, | ||
| NegFlag<SetFalse, [], [ClangOption, CC1Option], | ||
| "Disable contract violations on exception">>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do that in a subsequent PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we can certainly do that. It was useful for testing.
| std::optional<ContractKind> getContractKeyword(const Token &Token) const; | ||
| std::optional<ContractKind> getContractKeyword() const { | ||
| return getContractKeyword(Tok); | ||
| } | ||
| bool isFunctionContractKeyword() const { | ||
| return isFunctionContractKeyword(Tok); | ||
| } | ||
| bool isFunctionContractKeyword(const Token &Token) const { | ||
| return getContractKeyword(Token).value_or(ContractKind::Assert) != | ||
| ContractKind::Assert; | ||
| } | ||
|
|
||
| bool isAnyContractKeyword(const Token &Token) const { | ||
| return getContractKeyword(Token).has_value(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cf above, lets keep assert separate from pre/post
| /// ScopeFlags - These are bitfields that are or'd together when creating a | ||
| /// scope, which defines the sorts of things the scope contains. | ||
| enum ScopeFlags { | ||
| enum ScopeFlags : unsigned long { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we want to introduce an alias for the underlying type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
| enum class ContractEmissionStyle { | ||
| /// Emit the contract at every call site, in the caller. | ||
| InCaller, | ||
|
|
||
| /// Emit the contract with the function definition. | ||
| InDefinition, | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we focus on callee side initially?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I should remove the emission style stuff since it's not implemented.
| enum ContractScopeOffset { | ||
| CSO_ParentContext, | ||
| CSO_FunctionContext | ||
| }; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets use a scoped enum here
| "woops... FIXME(EricWF): %0" | ||
| >, InGroup<EricWFFixme>; | ||
|
|
||
| def err_result_name_shadows_param : Error< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we be more consistent about using _contract_ in these diags?
| def err_result_name_shadows_param : Error< | ||
| "declaration of result name %0 shadows parameter">; | ||
| def err_void_result_name : Error< | ||
| "result name %0 cannot be used with a void return type">; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
used? declared? introduced?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"result name in the post condition of a function with a void return type" maybe
| def err_contract_violation : Error<"contract %select{precondition|postcondition|assertion}0 failed%select{: %2|}1">; | ||
| def warn_contract_violation : Warning<"contract %select{precondition|postcondition|assertion}0 failed%select{: %2|}1">, | ||
| InGroup<ContractViolation>; | ||
|
|
||
| def err_contract_requirement_failed : Error< | ||
| "%select{precondition|postcondition|contract assertion}0 failed due to requirement '%1'%select{: %3|}2">; | ||
| def warn_contract_requirement_failed : Warning< | ||
| "%select{precondition|postcondition|contract assertion}0 failed due to requirement '%1'%select{: %3|}2">, | ||
| InGroup<ContractViolation>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None of these are (nor can) ever be used, right?
| ContractSpecifierDecl * | ||
| Parser::ParseLexedFunctionContractsInScope(CachedTokens &ContractToks, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not anymore I think. It was left over. Removing.
| ContractSpecifierDecl *Seq = Actions.ActOnFinishContractSpecifierSequence( | ||
| Contracts, StartLoc, IsInvalid); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should check we are parsing a function (and not a type or a function pointer)
see err_requires_clause_on_declarator_not_declaring_a_function
| // FIXME(EricWF): We allow parsing the result name declarator in `pre` so we | ||
| // can diagnose it but we don't do the same for contract assert... Should we? | ||
| if ((CK != ContractKind::Assert) && Tok.is(tok::identifier) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably should not!
| if (Cond.isInvalid()) { | ||
| Cond = | ||
| Actions.CreateRecoveryExpr(ExprLoc, EndLoc, {}, Actions.Context.BoolTy); | ||
| } else { | ||
| SetInvalidOnExit.release(); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here for the braces
…erver (llvm#148774) Summary: There was a deadlock was introduced by [PR llvm#146441](llvm#146441) which changed `CurrentThreadIsPrivateStateThread()` to `CurrentThreadPosesAsPrivateStateThread()`. This change caused the execution path in [`ExecutionContextRef::SetTargetPtr()`](https://github.com/llvm/llvm-project/blob/10b5558b61baab59c7d3dff37ffdf0861c0cc67a/lldb/source/Target/ExecutionContext.cpp#L513) to now enter a code block that was previously skipped, triggering [`GetSelectedFrame()`](https://github.com/llvm/llvm-project/blob/10b5558b61baab59c7d3dff37ffdf0861c0cc67a/lldb/source/Target/ExecutionContext.cpp#L522) which leads to a deadlock. Thread 1 gets m_modules_mutex in [`ModuleList::AppendImpl`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Core/ModuleList.cpp#L218), Thread 3 gets m_language_runtimes_mutex in [`GetLanguageRuntime`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Target/Process.cpp#L1501), but then Thread 1 waits for m_language_runtimes_mutex in [`GetLanguageRuntime`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Target/Process.cpp#L1501) while Thread 3 waits for m_modules_mutex in [`ScanForGNUstepObjCLibraryCandidate`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.cpp#L57). This fixes the deadlock by adding a scoped block around the mutex lock before the call to the notifier, and moved the notifier call outside of the mutex-guarded section. The notifier call [`NotifyModuleAdded`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Target/Target.cpp#L1810) should be thread-safe, since the module should be added to the `ModuleList` before the mutex is released, and the notifier doesn't modify the module list further, and the call is operates on local state and the `Target` instance. ### Deadlocked Thread backtraces: ``` * thread #3, name = 'dbg.evt-handler', stop reason = signal SIGSTOP * frame #0: 0x00007f2f1e2973dc libc.so.6`futex_wait(private=0, expected=2, futex_word=0x0000563786bd5f40) at futex-internal.h:146:13 /*... a bunch of mutex related bt ... */ liblldb.so.21.0git`std::lock_guard<std::recursive_mutex>::lock_guard(this=0x00007f2f0f1927b0, __m=0x0000563786bd5f40) at std_mutex.h:229:19 frame #8: 0x00007f2f27946eb7 liblldb.so.21.0git`ScanForGNUstepObjCLibraryCandidate(modules=0x0000563786bd5f28, TT=0x0000563786bd5eb8) at GNUstepObjCRuntime.cpp:60:41 frame #9: 0x00007f2f27946c80 liblldb.so.21.0git`lldb_private::GNUstepObjCRuntime::CreateInstance(process=0x0000563785e1d360, language=eLanguageTypeObjC) at GNUstepObjCRuntime.cpp:87:8 frame #10: 0x00007f2f2746fca5 liblldb.so.21.0git`lldb_private::LanguageRuntime::FindPlugin(process=0x0000563785e1d360, language=eLanguageTypeObjC) at LanguageRuntime.cpp:210:36 frame #11: 0x00007f2f2742c9e3 liblldb.so.21.0git`lldb_private::Process::GetLanguageRuntime(this=0x0000563785e1d360, language=eLanguageTypeObjC) at Process.cpp:1516:9 ... frame llvm#21: 0x00007f2f2750b5cc liblldb.so.21.0git`lldb_private::Thread::GetSelectedFrame(this=0x0000563785e064d0, select_most_relevant=DoNoSelectMostRelevantFrame) at Thread.cpp:274:48 frame llvm#22: 0x00007f2f273f9957 liblldb.so.21.0git`lldb_private::ExecutionContextRef::SetTargetPtr(this=0x00007f2f0f193778, target=0x0000563786bd5be0, adopt_selected=true) at ExecutionContext.cpp:525:32 frame llvm#23: 0x00007f2f273f9714 liblldb.so.21.0git`lldb_private::ExecutionContextRef::ExecutionContextRef(this=0x00007f2f0f193778, target=0x0000563786bd5be0, adopt_selected=true) at ExecutionContext.cpp:413:3 frame llvm#24: 0x00007f2f270e80af liblldb.so.21.0git`lldb_private::Debugger::GetSelectedExecutionContext(this=0x0000563785d83bc0) at Debugger.cpp:1225:23 frame llvm#25: 0x00007f2f271bb7fd liblldb.so.21.0git`lldb_private::Statusline::Redraw(this=0x0000563785d83f30, update=true) at Statusline.cpp:136:41 ... * thread #1, name = 'lldb', stop reason = signal SIGSTOP * frame #0: 0x00007f2f1e2973dc libc.so.6`futex_wait(private=0, expected=2, futex_word=0x0000563785e1dd98) at futex-internal.h:146:13 /*... a bunch of mutex related bt ... */ liblldb.so.21.0git`std::lock_guard<std::recursive_mutex>::lock_guard(this=0x00007ffe62be0488, __m=0x0000563785e1dd98) at std_mutex.h:229:19 frame #8: 0x00007f2f2742c8d1 liblldb.so.21.0git`lldb_private::Process::GetLanguageRuntime(this=0x0000563785e1d360, language=eLanguageTypeC_plus_plus) at Process.cpp:1510:41 frame #9: 0x00007f2f2743c46f liblldb.so.21.0git`lldb_private::Process::ModulesDidLoad(this=0x0000563785e1d360, module_list=0x00007ffe62be06a0) at Process.cpp:6082:36 ... frame llvm#13: 0x00007f2f2715cf03 liblldb.so.21.0git`lldb_private::ModuleList::AppendImpl(this=0x0000563786bd5f28, module_sp=ptr = 0x563785cec560, use_notifier=true) at ModuleList.cpp:246:19 frame llvm#14: 0x00007f2f2715cf4c liblldb.so.21.0git`lldb_private::ModuleList::Append(this=0x0000563786bd5f28, module_sp=ptr = 0x563785cec560, notify=true) at ModuleList.cpp:251:3 ... frame llvm#19: 0x00007f2f274349b3 liblldb.so.21.0git`lldb_private::Process::ConnectRemote(this=0x0000563785e1d360, remote_url=(Data = "connect://localhost:1234", Length = 24)) at Process.cpp:3250:9 frame llvm#20: 0x00007f2f27411e0e liblldb.so.21.0git`lldb_private::Platform::DoConnectProcess(this=0x0000563785c59990, connect_url=(Data = "connect://localhost:1234", Length = 24), plugin_name=(Data = "gdb-remote", Length = 10), debugger=0x0000563785d83bc0, stream=0x00007ffe62be3128, target=0x0000563786bd5be0, error=0x00007ffe62be1ca0) at Platform.cpp:1926:23 ``` ## Test Plan: Built a hello world a.out Run server in one terminal: ``` ~/llvm/build/Debug/bin/lldb-server g :1234 a.out ``` Run client in another terminal ``` ~/llvm/build/Debug/bin/lldb -o "gdb-remote 1234" -o "b hello.cc:3" ``` Before: Client hangs indefinitely ``` ~/llvm/build/Debug/bin/lldb -o "gdb-remote 1234" -o "b main" (lldb) gdb-remote 1234 ^C^C ``` After: ``` ~/llvm/build/Debug/bin/lldb -o "gdb-remote 1234" -o "b hello.cc:3" (lldb) gdb-remote 1234 Process 837068 stopped * thread #1, name = 'a.out', stop reason = signal SIGSTOP frame #0: 0x00007ffff7fe4a60 ld-linux-x86-64.so.2`_start: -> 0x7ffff7fe4a60 <+0>: movq %rsp, %rdi 0x7ffff7fe4a63 <+3>: callq 0x7ffff7fe5780 ; _dl_start at rtld.c:522:1 ld-linux-x86-64.so.2`_dl_start_user: 0x7ffff7fe4a68 <+0>: movq %rax, %r12 0x7ffff7fe4a6b <+3>: movl 0x18067(%rip), %eax ; _dl_skip_args (lldb) b hello.cc:3 Breakpoint 1: where = a.out`main + 15 at hello.cc:4:13, address = 0x00005555555551bf (lldb) c Process 837068 resuming Process 837068 stopped * thread #1, name = 'a.out', stop reason = breakpoint 1.1 frame #0: 0x00005555555551bf a.out`main at hello.cc:4:13 1 #include <iostream> 2 3 int main() { -> 4 std::cout << "Hello World" << std::endl; 5 return 0; 6 } ```
… contracts-nightly
Resolved merge conflicts by keeping both sides of changes: - clang/include/clang/AST/Decl.h: Added both ContractKind enum and UsualDeleteParams struct - clang/lib/AST/DeclPrinter.cpp: Added both VisitResultNameDecl and VisitTemplateTemplateParmDecl functions - clang/lib/Frontend/CompilerInvocation.cpp: Added both contract group serialization and AllocToken code
…am (llvm#167724) This got exposed by `09262656f32ab3f2e1d82e5342ba37eecac52522`. The underlying stream of `m_os` is referenced by the `TextDiagnostic` member of `TextDiagnosticPrinter`. It got turned into a `llvm::formatted_raw_ostream` in the commit above. When `~TextDiagnosticPrinter` (and thus `~TextDiagnostic`) is invoked, we now call `~formatted_raw_ostream`, which tries to access the underlying stream. But `m_os` was already deleted because it is earlier in the order of destruction in `TextDiagnosticPrinter`. Move the `m_os` member before the `TextDiagnosticPrinter` to avoid a use-after-free. Drive-by: * Also move the `m_output` member which the `m_os` holds a reference to. The fact it's a reference indicates the expectation is most likely that the string outlives the stream. The ASAN macOS bot is currently failing with this: ``` 08:15:39 ================================================================= 08:15:39 ==61103==ERROR: AddressSanitizer: heap-use-after-free on address 0x60600012cf40 at pc 0x00012140d304 bp 0x00016eecc850 sp 0x00016eecc848 08:15:39 READ of size 8 at 0x60600012cf40 thread T0 08:15:39 #0 0x00012140d300 in llvm::formatted_raw_ostream::releaseStream() FormattedStream.h:205 08:15:39 #1 0x00012140d3a4 in llvm::formatted_raw_ostream::~formatted_raw_ostream() FormattedStream.h:145 08:15:39 #2 0x00012604abf8 in clang::TextDiagnostic::~TextDiagnostic() TextDiagnostic.cpp:721 08:15:39 #3 0x00012605dc80 in clang::TextDiagnosticPrinter::~TextDiagnosticPrinter() TextDiagnosticPrinter.cpp:30 08:15:39 #4 0x00012605dd5c in clang::TextDiagnosticPrinter::~TextDiagnosticPrinter() TextDiagnosticPrinter.cpp:27 08:15:39 #5 0x0001231fb210 in (anonymous namespace)::StoringDiagnosticConsumer::~StoringDiagnosticConsumer() ClangModulesDeclVendor.cpp:47 08:15:39 #6 0x0001231fb3bc in (anonymous namespace)::StoringDiagnosticConsumer::~StoringDiagnosticConsumer() ClangModulesDeclVendor.cpp:47 08:15:39 #7 0x000129aa9d70 in clang::DiagnosticsEngine::~DiagnosticsEngine() Diagnostic.cpp:91 08:15:39 #8 0x0001230436b8 in llvm::RefCountedBase<clang::DiagnosticsEngine>::Release() const IntrusiveRefCntPtr.h:103 08:15:39 #9 0x0001231fe6c8 in (anonymous namespace)::ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl() ClangModulesDeclVendor.cpp:93 08:15:39 #10 0x0001231fe858 in (anonymous namespace)::ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl() ClangModulesDeclVendor.cpp:93 ... 08:15:39 08:15:39 0x60600012cf40 is located 32 bytes inside of 56-byte region [0x60600012cf20,0x60600012cf58) 08:15:39 freed by thread T0 here: 08:15:39 #0 0x0001018abb88 in _ZdlPv+0x74 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x4bb88) 08:15:39 #1 0x0001231fb1c0 in (anonymous namespace)::StoringDiagnosticConsumer::~StoringDiagnosticConsumer() ClangModulesDeclVendor.cpp:47 08:15:39 #2 0x0001231fb3bc in (anonymous namespace)::StoringDiagnosticConsumer::~StoringDiagnosticConsumer() ClangModulesDeclVendor.cpp:47 08:15:39 #3 0x000129aa9d70 in clang::DiagnosticsEngine::~DiagnosticsEngine() Diagnostic.cpp:91 08:15:39 #4 0x0001230436b8 in llvm::RefCountedBase<clang::DiagnosticsEngine>::Release() const IntrusiveRefCntPtr.h:103 08:15:39 #5 0x0001231fe6c8 in (anonymous namespace)::ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl() ClangModulesDeclVendor.cpp:93 08:15:39 #6 0x0001231fe858 in (anonymous namespace)::ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl() ClangModulesDeclVendor.cpp:93 ... 08:15:39 08:15:39 previously allocated by thread T0 here: 08:15:39 #0 0x0001018ab760 in _Znwm+0x74 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x4b760) 08:15:39 #1 0x0001231f8dec in lldb_private::ClangModulesDeclVendor::Create(lldb_private::Target&) ClangModulesDeclVendor.cpp:732 08:15:39 #2 0x00012320af58 in lldb_private::ClangPersistentVariables::GetClangModulesDeclVendor() ClangPersistentVariables.cpp:124 08:15:39 #3 0x0001232111f0 in lldb_private::ClangUserExpression::PrepareForParsing(lldb_private::DiagnosticManager&, lldb_private::ExecutionContext&, bool) ClangUserExpression.cpp:536 08:15:39 #4 0x000123213790 in lldb_private::ClangUserExpression::Parse(lldb_private::DiagnosticManager&, lldb_private::ExecutionContext&, lldb_private::ExecutionPolicy, bool, bool) ClangUserExpression.cpp:647 08:15:39 #5 0x00012032b258 in lldb_private::UserExpression::Evaluate(lldb_private::ExecutionContext&, lldb_private::EvaluateExpressionOptions const&, llvm::StringRef, llvm::StringRef, std::__1::shared_ptr<lldb_private::ValueObject>&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*, lldb_private::ValueObject*) UserExpression.cpp:280 08:15:39 #6 0x000120724010 in lldb_private::Target::EvaluateExpression(llvm::StringRef, lldb_private::ExecutionContextScope*, std::__1::shared_ptr<lldb_private::ValueObject>&, lldb_private::EvaluateExpressionOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*, lldb_private::ValueObject*) Target.cpp:2905 08:15:39 #7 0x00011fc7bde0 in lldb::SBTarget::EvaluateExpression(char const*, lldb::SBExpressionOptions const&) SBTarget.cpp:2305 08:15:39 ==61103==ABORTING ... ```
Resolved merge conflicts: - clang/lib/Basic/IdentifierTable.cpp: Kept enum definitions with KEYCONTRACTS support - libcxx/utils/libcxx/test/features.py: Kept modified version (modify-delete conflict)
After merging contracts-base into contracts-nightly, several build errors
needed to be addressed:
1. TokenKey and KeywordStatus enums were moved to IdentifierTable.h in
contracts-base, but contracts-nightly had added KEYCONTRACTS to the
.cpp file version. Added KEYCONTRACTS to the header and removed the
duplicate enum definitions from the .cpp file.
2. ArrayRef no longer accepts std::nullopt for construction in newer LLVM.
Updated return statements to use {} instead of std::nullopt in:
- FunctionDecl::contracts() in Decl.cpp
- Sema::getInterveningContractScopes() in SemaContract.cpp
Co-authored-by: Corentin Jabot <corentinjabot@gmail.com>
Co-authored-by: Corentin Jabot <corentinjabot@gmail.com>
Co-authored-by: Corentin Jabot <corentinjabot@gmail.com>
…lvm#159480) When building rustc std for arm64e, core fails to compile successfully with the error: ``` Constant ValueID not recognized. UNREACHABLE executed at rust/src/llvm-project/llvm/lib/Transforms/Utils/FunctionComparator.cpp:523! ``` This is a result of function merging so I modified FunctionComparator.cpp as the ConstantPtrAuth value would go unchecked in the switch statement. The test case is a reduction from the failure in core and fails on main with: ``` ******************** FAIL: LLVM :: Transforms/MergeFunc/ptrauth-const-compare.ll (59809 of 59995) ******************** TEST 'LLVM :: Transforms/MergeFunc/ptrauth-const-compare.ll' FAILED ******************** Exit Code: 2 Command Output (stdout): -- # RUN: at line 3 /Users/oskarwirga/llvm-project/build/bin/opt -S -passes=mergefunc < /Users/oskarwirga/llvm-project/llvm/test/Transforms/MergeFunc/ptrauth-const-compare.ll | /Users/oskarwirga/llvm-project/build/bin/FileCheck /Users/oskarwirga/llvm-project/llvm/test/Transforms/MergeFunc/ptrauth-const-compare.ll # executed command: /Users/oskarwirga/llvm-project/build/bin/opt -S -passes=mergefunc # .---command stderr------------ # | Constant ValueID not recognized. # | UNREACHABLE executed at /Users/oskarwirga/llvm-project/llvm/lib/Transforms/Utils/FunctionComparator.cpp:523! # | PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug. # | Stack dump: # | 0. Program arguments: /Users/oskarwirga/llvm-project/build/bin/opt -S -passes=mergefunc # | 1. Running pass "mergefunc" on module "<stdin>" # | #0 0x0000000103335770 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/Users/oskarwirga/llvm-project/build/bin/opt+0x102651770) # | #1 0x00000001033336bc llvm::sys::RunSignalHandlers() (/Users/oskarwirga/llvm-project/build/bin/opt+0x10264f6bc) # | #2 0x0000000103336218 SignalHandler(int, __siginfo*, void*) (/Users/oskarwirga/llvm-project/build/bin/opt+0x102652218) # | #3 0x000000018e6c16a4 (/usr/lib/system/libsystem_platform.dylib+0x1804ad6a4) # | #4 0x000000018e68788c (/usr/lib/system/libsystem_pthread.dylib+0x18047388c) # | #5 0x000000018e590a3c (/usr/lib/system/libsystem_c.dylib+0x18037ca3c) # | #6 0x00000001032a84bc llvm::install_out_of_memory_new_handler() (/Users/oskarwirga/llvm-project/build/bin/opt+0x1025c44bc) # | #7 0x00000001033b37c0 llvm::FunctionComparator::cmpMDNode(llvm::MDNode const*, llvm::MDNode const*) const (/Users/oskarwirga/llvm-project/build/bin/opt+0x1026cf7c0) # | #8 0x00000001033b4d90 llvm::FunctionComparator::cmpBasicBlocks(llvm::BasicBlock const*, llvm::BasicBlock const*) const (/Users/oskarwirga/llvm-project/build/bin/opt+0x1026d0d90) # | #9 0x00000001033b5234 llvm::FunctionComparator::compare() (/Users/oskarwirga/llvm-project/build/bin/opt+0x1026d1234) # | #10 0x0000000102d6d868 (anonymous namespace)::MergeFunctions::insert(llvm::Function*) (/Users/oskarwirga/llvm-project/build/bin/opt+0x102089868) # | #11 0x0000000102d6bc0c llvm::MergeFunctionsPass::runOnModule(llvm::Module&) (/Users/oskarwirga/llvm-project/build/bin/opt+0x102087c0c) # | llvm#12 0x0000000102d6b430 llvm::MergeFunctionsPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/Users/oskarwirga/llvm-project/build/bin/opt+0x102087430) # | llvm#13 0x0000000102b90558 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/Users/oskarwirga/llvm-project/build/bin/opt+0x101eac558) # | llvm#14 0x0000000103734bc4 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::__1::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (/Users/oskarwirga/llvm-project/build/bin/opt+0x102a50bc4) # | llvm#15 0x000000010373cc28 optMain (/Users/oskarwirga/llvm-project/build/bin/opt+0x102a58c28) # | llvm#16 0x000000018e2e6b98 # `----------------------------- # error: command failed with exit status: -6 # executed command: /Users/oskarwirga/llvm-project/build/bin/FileCheck /Users/oskarwirga/llvm-project/llvm/test/Transforms/MergeFunc/ptrauth-const-compare.ll # .---command stderr------------ # | FileCheck error: '<stdin>' is empty. # | FileCheck command line: /Users/oskarwirga/llvm-project/build/bin/FileCheck /Users/oskarwirga/llvm-project/llvm/test/Transforms/MergeFunc/ptrauth-const-compare.ll # `----------------------------- # error: command failed with exit status: 2 ```
No description provided.