mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 07:31:28 +00:00
Don't consider 'LinkageSpec' when calculating DeclContext 'Encloses'
We don't properly handle lookup through using directives when there is a linkage spec in the common chain. This is because `CppLookupName` and `CppNamespaceLookup` end up skipping `LinkageSpec`'s (correctly, as they are not lookup scopes), but the `UnqualUsingDirectiveSet` does not. I discovered that when we are calculating the `CommonAncestor` for a using-directive, we were coming up with the `LinkageSpec`, instead of the `LinkageSpec`'s parent. Then, when we use `UnqualUsingDirectiveSet::getNamespacesFor` a scope, we don't end up finding any that were in the `LinkageSpec` (again, since `CppLookupName` skips linkage specs), so those don't end up participating in the lookup. The function `UnqualUsingDirectiveSet::addUsingDirective` calculates this common ancestor via a loop through the the `DeclSpec::Encloses` function. Changing this Encloses function to believe that a `LinkageSpec` `Encloses` nothing ends up fixing the problem without breaking any other tests, so I opted to do that. A less aggressive patch could perhaps change only the `addUsingDirective`, but my examination of all uses of `Encloses` showed that it seems to be used exclusively in lookup, which makes me think this is correct everywhere. Differential Revision: https://reviews.llvm.org/D113709
This commit is contained in:
parent
5e96553608
commit
90010c2e1d
@ -1212,7 +1212,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const {
|
||||
return getPrimaryContext()->Encloses(DC);
|
||||
|
||||
for (; DC; DC = DC->getParent())
|
||||
if (DC->getPrimaryContext() == this)
|
||||
if (!isa<LinkageSpecDecl>(DC) && DC->getPrimaryContext() == this)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
33
clang/test/SemaCXX/lookup-through-linkage.cpp
Normal file
33
clang/test/SemaCXX/lookup-through-linkage.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
// RUN: %clang_cc1 %s -verify
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
extern "C++" {
|
||||
namespace A {
|
||||
namespace B {
|
||||
int bar;
|
||||
}
|
||||
} // namespace A
|
||||
namespace C {
|
||||
void foo() {
|
||||
using namespace A;
|
||||
(void)B::bar;
|
||||
}
|
||||
} // namespace C
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
extern "C++" {
|
||||
namespace D {
|
||||
namespace E {
|
||||
int bar;
|
||||
}
|
||||
} // namespace A
|
||||
namespace F {
|
||||
void foo() {
|
||||
using namespace D;
|
||||
(void)E::bar;
|
||||
}
|
||||
} // namespace C
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user