[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