Skip to content

[clang] Substitute alias templates from correct context #75069

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,9 @@ Bug Fixes in This Version
(`#62157 <https://github.com/llvm/llvm-project/issues/62157>`_) and
(`#64885 <https://github.com/llvm/llvm-project/issues/64885>`_) and
(`#65568 <https://github.com/llvm/llvm-project/issues/65568>`_)
- 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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8738,7 +8738,7 @@ class Sema final {
SourceLocation IILoc,
bool DeducedTSTContext = true);


bool RebuildingTypesInCurrentInstantiation = false;
TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
SourceLocation Loc,
DeclarationName Name);
Expand Down
24 changes: 20 additions & 4 deletions clang/lib/Sema/SemaCXXScopeSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,33 @@ 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() ||
Record->isCurrentInstantiation(CurContext))
return Record;

return nullptr;
} else if (isa<InjectedClassNameType>(Ty))
return cast<InjectedClassNameType>(Ty)->getDecl();
else
return nullptr;
}

if (auto *ICNT = dyn_cast<InjectedClassNameType>(Ty))
return ICNT->getDecl();

return nullptr;
}

/// Compute the DeclContext that is associated with the given type.
Expand Down
14 changes: 11 additions & 3 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/SaveAndRestore.h"

#include <iterator>
#include <optional>
Expand Down Expand Up @@ -3990,9 +3991,14 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
if (Inst.isInvalid())
return QualType();

CanonType = SubstType(Pattern->getUnderlyingType(),
TemplateArgLists, AliasTemplate->getLocation(),
AliasTemplate->getDeclName());
{
Sema::ContextRAII SavedContext(*this, Pattern->getDeclContext());
if (RebuildingTypesInCurrentInstantiation)
SavedContext.pop();
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
Expand Down Expand Up @@ -11392,6 +11398,8 @@ TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
if (!T || !T->getType()->isInstantiationDependentType())
return T;

llvm::SaveAndRestore DisableContextSwitchForTypeAliases(
RebuildingTypesInCurrentInstantiation, true);
CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name);
return Rebuilder.TransformType(T);
}
Expand Down
5 changes: 3 additions & 2 deletions clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
65 changes: 65 additions & 0 deletions clang/test/SemaCXX/alias-template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,68 @@ 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 {
// No errors when a type alias defined in a class or a friend of a class
// accesses private members of the same class.
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>);
}

// Test case that regressed with the first iteration of the fix for GH41693.
template <typename T> class SP {
T* data;
};

template <typename T> class A {
static SP<A> foo();
};

template<typename T> using TRet = SP<A<T>>;

template<typename T> TRet<T> A<T>::foo() { return TRet<T>{};};

}