[clang] 01710aa - [clang] Fix cast for injected types in case name lookup for dependent bases (#119024)

via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 9 01:28:30 PST 2024


Author: Vladislav Belov
Date: 2024-12-09T10:28:26+01:00
New Revision: 01710aa345f2fb26e2312dd1c62bd0044fc75bed

URL: https://github.com/llvm/llvm-project/commit/01710aa345f2fb26e2312dd1c62bd0044fc75bed
DIFF: https://github.com/llvm/llvm-project/commit/01710aa345f2fb26e2312dd1c62bd0044fc75bed.diff

LOG: [clang] Fix cast for injected types in case name lookup for dependent bases (#119024)

An assertion failure occurs in Clang when attempting to compile such an
example:

```c++
template <typename, typename, bool> struct MozPromise {
  class Private;

private:
  int mMagic4 = 42;
};

template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
struct MozPromise<ResolveValueT, RejectValueT, IsExclusive>::Private : MozPromise {
  void SetTaskPriority() { mMagic4 ; }
};
```

Output:
```
clang: llvm-project/llvm/include/llvm/Support/Casting.h:566: decltype(auto) llvm::cast(const From&) [with To = clang::RecordType; From = clang::QualType]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
```

The reason is in the incorrect way of casting types when searching for
names in base classes

```c++
return Specifier->getType()->castAs<RecordType>()->getDecl()->getCanonicalDecl() == BaseRecord;
```

It loses injected types for template class names. 

This patch provides fix for such cases

Added: 
    

Modified: 
    clang/lib/AST/CXXInheritance.cpp
    clang/test/CXX/drs/cwg5xx.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp
index 10b8d524ff8978..ee5775837d5355 100644
--- a/clang/lib/AST/CXXInheritance.cpp
+++ b/clang/lib/AST/CXXInheritance.cpp
@@ -368,8 +368,8 @@ bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
                                   const CXXRecordDecl *BaseRecord) {
   assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
          "User data for FindBaseClass is not canonical!");
-  return Specifier->getType()->castAs<RecordType>()->getDecl()
-            ->getCanonicalDecl() == BaseRecord;
+  return cast<CXXRecordDecl>(Specifier->getType()->getAsRecordDecl())
+             ->getCanonicalDecl() == BaseRecord;
 }
 
 bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
@@ -378,8 +378,8 @@ bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
   assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
          "User data for FindBaseClass is not canonical!");
   return Specifier->isVirtual() &&
-         Specifier->getType()->castAs<RecordType>()->getDecl()
-            ->getCanonicalDecl() == BaseRecord;
+         cast<CXXRecordDecl>(Specifier->getType()->getAsRecordDecl())
+                 ->getCanonicalDecl() == BaseRecord;
 }
 
 static bool isOrdinaryMember(const NamedDecl *ND) {
@@ -692,7 +692,7 @@ AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context,
            "Cannot get indirect primary bases for class with dependent bases.");
 
     const CXXRecordDecl *BaseDecl =
-      cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+        cast<CXXRecordDecl>(I.getType()->getAsRecordDecl());
 
     // Only bases with virtual bases participate in computing the
     // indirect primary virtual base classes.
@@ -714,7 +714,7 @@ CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const {
            "Cannot get indirect primary bases for class with dependent bases.");
 
     const CXXRecordDecl *BaseDecl =
-      cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+        cast<CXXRecordDecl>(I.getType()->getAsRecordDecl());
 
     // Only bases with virtual bases participate in computing the
     // indirect primary virtual base classes.

diff  --git a/clang/test/CXX/drs/cwg5xx.cpp b/clang/test/CXX/drs/cwg5xx.cpp
index 567a42b2bc7917..9219a4c857b12b 100644
--- a/clang/test/CXX/drs/cwg5xx.cpp
+++ b/clang/test/CXX/drs/cwg5xx.cpp
@@ -1209,6 +1209,11 @@ namespace cwg591 { // cwg591: 20
     };
   };
 
+  template <typename, bool> struct M {
+    class P;
+    int M;
+  };
+
   template<typename T> struct A<T>::B::C : A<T> {
     M m;
   };
@@ -1224,6 +1229,10 @@ namespace cwg591 { // cwg591: 20
     M m;
   };
 
+  template<typename T, bool B> class M<T,B>::P : M {
+    int foo() { (void) M; }
+  };
+
   template<typename T> struct A<T>::B::D : A<T*> {
     M m;
     // expected-error at -1 {{field has incomplete type 'M' (aka 'void'}}


        


More information about the cfe-commits mailing list