I have spent more time than I would like to admit diagnosing a super weird and super hard to reproduce problem with clang that turned out to be yet another instance of the old “dangling pointer” problem.
This email is really meant just to outline the problem, not offer a solution - I am hoping that the clang experts on this list will offer the best solution.
So here’s the problem…
When a Preprocessor object is created by calling CompilerInstance::createPreprocessor(), the existing shared pointer may already be pointing to an existing object. That existing object will own a HeaderSearch which will own a ModuleMap which will own a number of Module objects. Pointers to those Module objects may have been cached in the CompilerInstance::KnownModules map by CompilerInstance::loadModule(). However, creating the new Preprocessor will make the shared pointer point to that new one and since there are no further references to the old one, it will be destroyed. Of course, everything the old Preprocessor owns will be destroyed as well so we now have dangling pointers in the CompilerInstance::KnownModules map.
As it turns out, it appears to be very difficult to end up in a situation where this is actually a problem. It seems to be related to the path of whatever this function is looking for. So with a very specific path for the build tree, we come across the problem with the last RUN command in test/Modules/builtins.m. Changing the build tree path by a single character seems to make the problem go away for some reason.
Now obviously, this problem can be fixed by just clearing CompilerInstance::KnownModules if the shared pointer PP isn’t null in CompilerInstance::createPreprocessor(). However, I am not sure if that is the desired fix.
The attached patch isn’t the fix I mentioned but a patch that can show the problem I have described. Applying that patch and running that test should cause the expected assert.
I would really appreciate feedback with regard to how best to fix this problem.
ShowDanglingPtr.patch (2.91 KB)