[clang] Substitute alias templates from correct context (#74335)
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
This commit is contained in:
committed by
GitHub
parent
6ed7a8eae6
commit
6b1aa31975
@@ -658,6 +658,9 @@ Bug Fixes in This Version
|
||||
Fixes (`#64467 <https://github.com/llvm/llvm-project/issues/64467>`_)
|
||||
- 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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -30,6 +30,20 @@ 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 +51,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.
|
||||
|
||||
@@ -3990,9 +3990,16 @@ 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
|
||||
|
||||
@@ -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@-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;
|
||||
|
||||
|
||||
@@ -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>);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user