[clang] [clang] Substitute alias templates from correct context (PR #74335)

Mariya Podchishchaeva via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 4 08:52:21 PST 2023


https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/74335

>From 6d7fe6fe8c62373fdaab597c3c31c7132e475e32 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Mon, 4 Dec 2023 07:47:04 -0800
Subject: [PATCH 1/2] [clang] Substitute alias templates from correct context

Current context set to where alias was met, not where it
is declared caused incorrect access check in case alias referenced
private members of the parent class.

Fixes https://github.com/llvm/llvm-project/issues/41693
---
 clang/docs/ReleaseNotes.rst                   |  3 ++
 clang/lib/Sema/SemaCXXScopeSpec.cpp           | 23 +++++++--
 clang/lib/Sema/SemaTemplate.cpp               | 11 ++--
 .../CXX/temp/temp.decls/temp.alias/p3.cpp     |  5 +-
 clang/test/SemaCXX/alias-template.cpp         | 50 +++++++++++++++++++
 5 files changed, 84 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 683d0026bb345..18a7afda3c8b0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -653,6 +653,9 @@ Bug Fixes in This Version
   Fixes (`#13826 <https://github.com/llvm/llvm-project/issues/13826>`_)
 - Clang's ``-Wchar-subscripts`` no longer warns on chars whose values are known non-negative constants.
   Fixes (`#18763 <https://github.com/llvm/llvm-project/issues/18763>`_)
+- Fixed false positive error emitted when templated alias inside a class
+  used private members of the same class.
+  Fixes (`#41693 <https://github.com/llvm/llvm-project/issues/41693>`_)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 44a40215b90df..56f83be78266f 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -30,6 +30,21 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
     return nullptr;
 
   const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
+  if (isa<TemplateSpecializationType>(Ty)) {
+    if (auto *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
+      if (isa<ClassTemplatePartialSpecializationDecl>(Record) ||
+          Record->getDescribedClassTemplate()) {
+        const Type *ICNT = Record->getTypeForDecl();
+        QualType Injected =
+            cast<InjectedClassNameType>(ICNT)->getInjectedSpecializationType();
+
+        if (Ty == Injected->getCanonicalTypeInternal().getTypePtr()) {
+          return Record;
+        }
+      }
+    }
+  }
+
   if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
     CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
     if (!Record->isDependentContext() ||
@@ -37,10 +52,12 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
       return Record;
 
     return nullptr;
-  } else if (isa<InjectedClassNameType>(Ty))
+  }
+
+  if (isa<InjectedClassNameType>(Ty))
     return cast<InjectedClassNameType>(Ty)->getDecl();
-  else
-    return nullptr;
+
+  return nullptr;
 }
 
 /// Compute the DeclContext that is associated with the given type.
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 09bbf14d39af5..23a175da6bc4d 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3990,9 +3990,14 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
     if (Inst.isInvalid())
       return QualType();
 
-    CanonType = SubstType(Pattern->getUnderlyingType(),
-                          TemplateArgLists, AliasTemplate->getLocation(),
-                          AliasTemplate->getDeclName());
+    bool ForLambdaCallOperator = false;
+    if (const auto *Rec = dyn_cast<CXXRecordDecl>(Pattern->getDeclContext()))
+      ForLambdaCallOperator = Rec->isLambda();
+    Sema::ContextRAII SavedContext(*this, Pattern->getDeclContext(),
+                                   !ForLambdaCallOperator);
+    CanonType =
+        SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
+                  AliasTemplate->getLocation(), AliasTemplate->getDeclName());
     if (CanonType.isNull()) {
       // If this was enable_if and we failed to find the nested type
       // within enable_if in a SFINAE context, dig out the specific
diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp
index 2d46502e1d9b3..2b33a4ef566da 100644
--- a/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp
@@ -2,11 +2,12 @@
 
 // The example given in the standard (this is rejected for other reasons anyway).
 template<class T> struct A;
-template<class T> using B = typename A<T>::U; // expected-error {{no type named 'U' in 'A<T>'}}
+template<class T> using B = typename A<T>::U; // expected-error {{no type named 'U' in 'A<short>'}}
+                                              // expected-note at -1 {{in instantiation of template class 'A<short>' requested here}}
 template<class T> struct A {
   typedef B<T> U; // expected-note {{in instantiation of template type alias 'B' requested here}}
 };
-B<short> b;
+B<short> b; // expected-note {{in instantiation of template type alias 'B' requested here}}
 
 template<typename T> using U = int;
 
diff --git a/clang/test/SemaCXX/alias-template.cpp b/clang/test/SemaCXX/alias-template.cpp
index 5189405e23db5..cd415c6cd4e9b 100644
--- a/clang/test/SemaCXX/alias-template.cpp
+++ b/clang/test/SemaCXX/alias-template.cpp
@@ -192,3 +192,53 @@ int g = sfinae_me<int>(); // expected-error{{no matching function for call to 's
 namespace NullExceptionDecl {
 template<int... I> auto get = []() { try { } catch(...) {}; return I; }; // expected-error{{initializer contains unexpanded parameter pack 'I'}}
 }
+
+namespace GH41693 {
+struct S {
+private:
+  template <typename> static constexpr void Impl() {}
+
+public:
+  template <typename X> using U = decltype(Impl<X>());
+};
+
+using X = S::U<void>;
+struct Y {
+private:
+    static constexpr int x=0;
+
+    template <typename>
+    static constexpr int y=0;
+
+    template <typename>
+    static constexpr int foo();
+
+public:
+    template <typename U>
+    using bar1 = decltype(foo<U>());
+    using bar2 = decltype(x);
+    template <typename U>
+    using bar3 = decltype(y<U>);
+};
+
+
+using type1 = Y::bar1<float>;
+using type2 = Y::bar2;
+using type3 = Y::bar3<float>;
+
+struct theFriend{
+    template<class T>
+    using theAlias = decltype(&T::i);
+};
+
+class theC{
+  int i;
+  public:
+  friend struct theFriend;
+};
+
+int foo(){
+  (void)sizeof(theFriend::theAlias<theC>);
+}
+
+}

>From 4b2f7f7225e473cfa95f7aea58eae524dc0c845d Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Mon, 4 Dec 2023 08:51:55 -0800
Subject: [PATCH 2/2] Add/remove curleys

---
 clang/lib/Sema/SemaCXXScopeSpec.cpp |  3 +--
 clang/lib/Sema/SemaTemplate.cpp     | 18 ++++++++++--------
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 56f83be78266f..4bd96722a4b67 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -38,9 +38,8 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
         QualType Injected =
             cast<InjectedClassNameType>(ICNT)->getInjectedSpecializationType();
 
-        if (Ty == Injected->getCanonicalTypeInternal().getTypePtr()) {
+        if (Ty == Injected->getCanonicalTypeInternal().getTypePtr())
           return Record;
-        }
       }
     }
   }
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 23a175da6bc4d..a586014e0cb1b 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3990,14 +3990,16 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
     if (Inst.isInvalid())
       return QualType();
 
-    bool ForLambdaCallOperator = false;
-    if (const auto *Rec = dyn_cast<CXXRecordDecl>(Pattern->getDeclContext()))
-      ForLambdaCallOperator = Rec->isLambda();
-    Sema::ContextRAII SavedContext(*this, Pattern->getDeclContext(),
-                                   !ForLambdaCallOperator);
-    CanonType =
-        SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
-                  AliasTemplate->getLocation(), AliasTemplate->getDeclName());
+    {
+      bool ForLambdaCallOperator = false;
+      if (const auto *Rec = dyn_cast<CXXRecordDecl>(Pattern->getDeclContext()))
+        ForLambdaCallOperator = Rec->isLambda();
+      Sema::ContextRAII SavedContext(*this, Pattern->getDeclContext(),
+                                     !ForLambdaCallOperator);
+      CanonType =
+          SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
+                    AliasTemplate->getLocation(), AliasTemplate->getDeclName());
+    }
     if (CanonType.isNull()) {
       // If this was enable_if and we failed to find the nested type
       // within enable_if in a SFINAE context, dig out the specific



More information about the cfe-commits mailing list