[clang] fcb90cb - Fix miscomputation of dependence for elaborated types that are
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 4 13:14:28 PST 2021
Author: Richard Smith
Date: 2021-02-04T13:14:15-08:00
New Revision: fcb90cbd3b4ae3934bdd05d538647d37ce899962
URL: https://github.com/llvm/llvm-project/commit/fcb90cbd3b4ae3934bdd05d538647d37ce899962
DIFF: https://github.com/llvm/llvm-project/commit/fcb90cbd3b4ae3934bdd05d538647d37ce899962.diff
LOG: 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.
Added:
Modified:
clang/include/clang/AST/DependenceFlags.h
clang/include/clang/AST/Type.h
clang/test/SemaTemplate/instantiation-dependence.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h
index ca96b65574bd..62efdb4ce6e4 100644
--- a/clang/include/clang/AST/DependenceFlags.h
+++ b/clang/include/clang/AST/DependenceFlags.h
@@ -128,6 +128,9 @@ class Dependence {
// Type depends on a runtime value (variable-length array).
VariablyModified = 32,
+ // Dependence that is propagated syntactically, regardless of semantics.
+ Syntactic = UnexpandedPack | Instantiation | Error,
+
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
};
@@ -165,6 +168,13 @@ class Dependence {
translate(D, TNDependence::Dependent, Dependent) |
translate(D, TNDependence::Error, Error)) {}
+ /// Extract only the syntactic portions of this type's dependence.
+ Dependence syntactic() {
+ Dependence Result = *this;
+ Result.V &= Syntactic;
+ return Result;
+ }
+
TypeDependence type() const {
return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
translate(V, Instantiation, TypeDependence::Instantiation) |
@@ -256,6 +266,10 @@ inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
return Dependence(D).type();
}
+inline TypeDependence toSyntacticDependence(TypeDependence D) {
+ return Dependence(D).syntactic().type();
+}
+
inline NestedNameSpecifierDependence
toNestedNameSpecifierDependendence(TypeDependence D) {
return Dependence(D).nestedNameSpecifier();
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 319d3850346b..66ed32a9e9e5 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -5412,8 +5412,13 @@ class ElaboratedType final
ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
QualType NamedType, QualType CanonType, TagDecl *OwnedTagDecl)
: TypeWithKeyword(Keyword, Elaborated, CanonType,
+ // Any semantic dependence on the qualifier will have
+ // been incorporated into NamedType. We still need to
+ // track syntactic (instantiation / error / pack)
+ // dependence on the qualifier.
NamedType->getDependence() |
- (NNS ? toTypeDependence(NNS->getDependence())
+ (NNS ? toSyntacticDependence(
+ toTypeDependence(NNS->getDependence()))
: TypeDependence::None)),
NNS(NNS), NamedType(NamedType) {
ElaboratedTypeBits.HasOwnedTagDecl = false;
diff --git a/clang/test/SemaTemplate/instantiation-dependence.cpp b/clang/test/SemaTemplate/instantiation-dependence.cpp
index 2b9a47ad25a4..ae641080bec0 100644
--- a/clang/test/SemaTemplate/instantiation-dependence.cpp
+++ b/clang/test/SemaTemplate/instantiation-dependence.cpp
@@ -80,3 +80,24 @@ namespace TypeQualifier {
template<typename T> A<sizeof(sizeof(T::error))>::type f() {} // expected-note {{'int' cannot be used prior to '::'}}
int k = f<int>(); // expected-error {{no matching}}
}
+
+namespace MemberOfInstantiationDependentBase {
+ template<typename T> struct A { template<int> void f(int); };
+ template<typename T> struct B { using X = A<T>; };
+ template<typename T> struct C1 : B<int> {
+ using X = typename C1::X;
+ void f(X *p) {
+ p->f<0>(0);
+ p->template f<0>(0);
+ }
+ };
+ template<typename T> struct C2 : B<int> {
+ using X = typename C2<T>::X;
+ void f(X *p) {
+ p->f<0>(0);
+ p->template f<0>(0);
+ }
+ };
+ void q(C1<int> *c) { c->f(0); }
+ void q(C2<int> *c) { c->f(0); }
+}
More information about the cfe-commits
mailing list