mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 04:36:44 +00:00
[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
This commit is contained in:
parent
98b694b660
commit
01710aa345
@ -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.
|
||||
|
@ -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@-1 {{field has incomplete type 'M' (aka 'void'}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user