diff options
author | Vladislav Belov <vladislav.belov@syntacore.com> | 2024-11-26 14:56:46 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-26 12:56:46 +0100 |
commit | 486644723038555a224fd09d462bb5099e64809e (patch) | |
tree | 64aad1f60eeb056f228ae84c6e0f5baf6c0882ec /clang/lib/AST/CXXInheritance.cpp | |
parent | 4a7b56e6e7dd0f83c379ad06b6e81450bc691ba6 (diff) | |
download | llvm-486644723038555a224fd09d462bb5099e64809e.zip llvm-486644723038555a224fd09d462bb5099e64809e.tar.gz llvm-486644723038555a224fd09d462bb5099e64809e.tar.bz2 |
[Clang] Fix name lookup for dependent bases (#114978)
Currently the following example is a compilation failure:
```cpp
template<typename T> struct A {
typedef int M;
struct B {
typedef void M;
struct C;
};
};
template<typename T> struct A<T>::B::C : A<T> {
M m; // void or int ?
};
```
According to the point 13.8.3.2
```
A dependent base class is a base class that is a dependent type and is not the current instantiation.
Note 2 : A base class can be the current instantiation in the case of a nested class naming an enclosing class as a base.
```
The base class `A` is the current instantiation, because `C` is a nested
class for an enclosing class `A<T>`, it's is the not-dependent base
class and we need to search the names through its scope.
This patch makes this example compile
Diffstat (limited to 'clang/lib/AST/CXXInheritance.cpp')
-rw-r--r-- | clang/lib/AST/CXXInheritance.cpp | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index aefc06e..10b8d52 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -134,7 +134,7 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const { return false; CXXRecordDecl *Base = - cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition()); + cast_if_present<CXXRecordDecl>(Ty->getDecl()->getDefinition()); if (!Base || (Base->isDependentContext() && !Base->isCurrentInstantiation(Record))) { @@ -169,13 +169,21 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, QualType BaseType = Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType(); + bool isCurrentInstantiation = isa<InjectedClassNameType>(BaseType); + if (!isCurrentInstantiation) { + if (auto *BaseRecord = cast_if_present<CXXRecordDecl>( + BaseSpec.getType()->getAsRecordDecl())) + isCurrentInstantiation = BaseRecord->isDependentContext() && + BaseRecord->isCurrentInstantiation(Record); + } // C++ [temp.dep]p3: // In the definition of a class template or a member of a class template, // if a base class of the class template depends on a template-parameter, // the base class scope is not examined during unqualified name lookup // either at the point of definition of the class template or member or // during an instantiation of the class tem- plate or member. - if (!LookupInDependent && BaseType->isDependentType()) + if (!LookupInDependent && + (BaseType->isDependentType() && !isCurrentInstantiation)) continue; // Determine whether we need to visit this base class at all, @@ -243,9 +251,8 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, return FoundPath; } } else if (VisitBase) { - CXXRecordDecl *BaseRecord; + CXXRecordDecl *BaseRecord = nullptr; if (LookupInDependent) { - BaseRecord = nullptr; const TemplateSpecializationType *TST = BaseSpec.getType()->getAs<TemplateSpecializationType>(); if (!TST) { @@ -264,8 +271,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, BaseRecord = nullptr; } } else { - BaseRecord = cast<CXXRecordDecl>( - BaseSpec.getType()->castAs<RecordType>()->getDecl()); + BaseRecord = cast<CXXRecordDecl>(BaseSpec.getType()->getAsRecordDecl()); } if (BaseRecord && lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) { |