Skip to content

Commit fcb90cb

Browse files
committed
Fix miscomputation of dependence for elaborated types that are
explicitly qualified as members of the current instantiation. Despite the nested name specifier being fully-dependent in this case, the elaborated type might only be instantiation-dependent, because the type is a member of the current instantiation.
1 parent aecdf15 commit fcb90cb

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

clang/include/clang/AST/DependenceFlags.h

+14
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ class Dependence {
128128
// Type depends on a runtime value (variable-length array).
129129
VariablyModified = 32,
130130

131+
// Dependence that is propagated syntactically, regardless of semantics.
132+
Syntactic = UnexpandedPack | Instantiation | Error,
133+
131134
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
132135
};
133136

@@ -165,6 +168,13 @@ class Dependence {
165168
translate(D, TNDependence::Dependent, Dependent) |
166169
translate(D, TNDependence::Error, Error)) {}
167170

171+
/// Extract only the syntactic portions of this type's dependence.
172+
Dependence syntactic() {
173+
Dependence Result = *this;
174+
Result.V &= Syntactic;
175+
return Result;
176+
}
177+
168178
TypeDependence type() const {
169179
return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
170180
translate(V, Instantiation, TypeDependence::Instantiation) |
@@ -256,6 +266,10 @@ inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
256266
return Dependence(D).type();
257267
}
258268

269+
inline TypeDependence toSyntacticDependence(TypeDependence D) {
270+
return Dependence(D).syntactic().type();
271+
}
272+
259273
inline NestedNameSpecifierDependence
260274
toNestedNameSpecifierDependendence(TypeDependence D) {
261275
return Dependence(D).nestedNameSpecifier();

clang/include/clang/AST/Type.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -5412,8 +5412,13 @@ class ElaboratedType final
54125412
ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
54135413
QualType NamedType, QualType CanonType, TagDecl *OwnedTagDecl)
54145414
: TypeWithKeyword(Keyword, Elaborated, CanonType,
5415+
// Any semantic dependence on the qualifier will have
5416+
// been incorporated into NamedType. We still need to
5417+
// track syntactic (instantiation / error / pack)
5418+
// dependence on the qualifier.
54155419
NamedType->getDependence() |
5416-
(NNS ? toTypeDependence(NNS->getDependence())
5420+
(NNS ? toSyntacticDependence(
5421+
toTypeDependence(NNS->getDependence()))
54175422
: TypeDependence::None)),
54185423
NNS(NNS), NamedType(NamedType) {
54195424
ElaboratedTypeBits.HasOwnedTagDecl = false;

clang/test/SemaTemplate/instantiation-dependence.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,24 @@ namespace TypeQualifier {
8080
template<typename T> A<sizeof(sizeof(T::error))>::type f() {} // expected-note {{'int' cannot be used prior to '::'}}
8181
int k = f<int>(); // expected-error {{no matching}}
8282
}
83+
84+
namespace MemberOfInstantiationDependentBase {
85+
template<typename T> struct A { template<int> void f(int); };
86+
template<typename T> struct B { using X = A<T>; };
87+
template<typename T> struct C1 : B<int> {
88+
using X = typename C1::X;
89+
void f(X *p) {
90+
p->f<0>(0);
91+
p->template f<0>(0);
92+
}
93+
};
94+
template<typename T> struct C2 : B<int> {
95+
using X = typename C2<T>::X;
96+
void f(X *p) {
97+
p->f<0>(0);
98+
p->template f<0>(0);
99+
}
100+
};
101+
void q(C1<int> *c) { c->f(0); }
102+
void q(C2<int> *c) { c->f(0); }
103+
}

0 commit comments

Comments
 (0)