You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[clang] Fix conflicting declaration error with using_if_exists
This fixes an issue with using_if_exists where we would hit
`conflicts with target of using declaration already in scope` with a
using_if_exists attribute referring to a declaration which did not
exist. That is, if we have `using ::bar
__attribute__((using_if_exists))` but `bar` is not in the global
namespace, then nothing should actually be declared here.
This PR contains the following changes:
1. Ensure we only diagnose this error if the target decl and [Non]Tag
decl can be substitutes for each other.
2. Prevent LookupResult from considering UnresolvedUsingIfExistsDecls in
the event of ambiguous results.
3. Update tests. This includes the minimal repo for a regression test,
and changes to existing tests which also seem to exhibit this bug.
Fixes#85335
using NS2::A UIE; //expected-note{{using declaration annotated with 'using_if_exists' here}} expected-note{{conflicting declaration}}
33
-
using NS3::A UIE; //expected-error{{target of using declaration conflicts with declaration already in scope}}
34
-
int i = A(); //expected-error{{reference to unresolved using declaration}}
31
+
using NS1::A UIE;// OK since this declaration shouldn't exist since `A` is not in `NS1`
32
+
using NS2::A UIE; //OK since this declaration shouldn't exist since `A` is not in `NS2`
33
+
using NS3::A UIE; //OK since prior UIEs of `A` shouldn't have declare anything since they don't exist
34
+
int i = A(); //OK since `A` resolved to the single UIE in the previous line
35
35
36
-
using NS1::B UIE;
37
-
using NS2::B UIE; //expected-note{{conflicting declaration}} expected-note{{using declaration annotated with 'using_if_exists' here}}
38
-
using NS3::B UIE; //expected-error{{target of using declaration conflicts with declaration already in scope}}
39
-
B myB; //expected-error{{reference to unresolved using declaration}}
36
+
using NS1::B UIE;// OK since this declaration shouldn't exist since `B` is not in `NS1`
37
+
using NS2::B UIE; //OK since this declaration shouldn't exist since `B` is not in `NS2
38
+
using NS3::B UIE; //OK since prior UIEs of `B` shouldn't have declare anything since they don't exist
39
+
B myB; //OK since `B` resolved to the single UIE in the previous lin
40
40
41
41
using NS3::C UIE;
42
-
using NS2::C UIE; //expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}}
42
+
using NS2::C UIE; //OK since NS2::C doesn't exist
43
43
int j = C();
44
44
45
45
using NS3::D UIE;
46
-
using NS2::D UIE; //expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}}
46
+
using NS2::D UIE; //OK since NS2::D doesn't exist
47
47
D myD;
48
48
} // namespace test_redecl
49
49
@@ -113,29 +113,36 @@ struct NonDep : BaseEmpty {
113
113
namespacetest_using_pack {
114
114
template <class... Ts>
115
115
structS : Ts... {
116
-
usingtypename Ts::x... UIE; // expected-error 2 {{target of using declaration conflicts with declaration already in scope}} expected-note{{conflicting declaration}} expected-note{{target of using declaration}}
116
+
// We don't expect any errors with conflicting targets for variables `a`, `b`, `c`,
117
+
// and `d` below this. For `a`, `x` will not be declared because neither E1 nor E2
118
+
// defines it. For `b`, `x` is the same type so there won't be any conflicts. For
119
+
// `c` and `d`, only one of the template parameters has a class that defines it,
typedefint x;// expected-note 2 {{target of using declaration}}
132
+
typedefint x;
128
133
};
129
134
S<F1, F2> b;
130
135
131
-
S<E1, F2> c;// expected-note{{in instantiation of template class}}
132
-
S<F1, E2> d;// expected-note{{in instantiation of template class}}
136
+
S<E1, F2> c;
137
+
S<F1, E2> d;
133
138
134
139
template <class... Ts>
135
140
structS2 : Ts... {
136
-
usingtypename Ts::x... UIE; // expected-error 2 {{target of using declaration conflicts with declaration already in scope}} expected-note 3 {{using declaration annotated with 'using_if_exists' here}} expected-note{{conflicting declaration}} expected-note{{target of using declaration}}
141
+
// OK for the same reasons listed in `struct S` above. We don't expect any conflicts w.r.t
142
+
// redefinitions of `x` but we still expect errors when using `x` for cases it's not available.
using Ts::m... UIE; // expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}}
155
+
// No errors for conflicting declarations because only one of the parent classes declares `m`.
156
+
using Ts::m... UIE;
149
157
};
150
158
structB1 {
151
-
enum { m };// expected-note{{conflicting declaration}}
159
+
enum { m };
152
160
};
153
161
structB2 {};
154
162
155
-
S3<B1, B2> i;// expected-note{{in instantiation of template}}
163
+
S3<B1, B2> i;
156
164
S<B2, B1> j;
157
165
158
166
} // namespace test_using_pack
@@ -170,23 +178,23 @@ NS2::x y; // expected-error {{reference to unresolved using declaration}}
170
178
} // namespace test_nested
171
179
172
180
namespacetest_scope {
173
-
int x;// expected-note{{conflicting declaration}}
181
+
int x;
174
182
voidf() {
175
-
int x;// expected-note{{conflicting declaration}}
183
+
int x;
176
184
{
177
185
using ::x UIE; // expected-note {{using declaration annotated with 'using_if_exists' here}}
178
186
(void)x; // expected-error {{reference to unresolved using declaration}}
179
187
}
180
188
181
189
{
182
190
using test_scope::x;
183
-
using ::x UIE; //expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}}
191
+
using ::x UIE; //OK since there's no `x` in the global namespace, so this wouldn't be any declaration
184
192
(void)x;
185
193
}
186
194
187
195
(void)x;
188
196
189
-
using ::x UIE; //expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}}
197
+
using ::x UIE; //OK since there's no `x` in the global namespace, so this wouldn't be any declaration
190
198
(void)x;
191
199
}
192
200
} // namespace test_scope
@@ -224,3 +232,20 @@ int main() {
224
232
size = fake_printf();
225
233
size = std::fake_printf();
226
234
}
235
+
236
+
// Regression test for https://github.com/llvm/llvm-project/issues/85335.
0 commit comments