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

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


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Mariya Podchishchaeva (Fznamznon)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/74335.diff


5 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+3) 
- (modified) clang/lib/Sema/SemaCXXScopeSpec.cpp (+20-3) 
- (modified) clang/lib/Sema/SemaTemplate.cpp (+8-3) 
- (modified) clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp (+3-2) 
- (modified) clang/test/SemaCXX/alias-template.cpp (+50) 


``````````diff
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>);
+}
+
+}

``````````

</details>


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


More information about the cfe-commits mailing list