mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-24 06:10:12 +00:00
Treat implicit deduction guides as being equivalent to their
corresponding constructor for access checking purposes.
This commit is contained in:
parent
1dfa47910a
commit
d38057f3ec
@ -1852,15 +1852,17 @@ private:
|
||||
CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
ExplicitSpecifier ES,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, SourceLocation EndLocation)
|
||||
TypeSourceInfo *TInfo, SourceLocation EndLocation,
|
||||
CXXConstructorDecl *Ctor)
|
||||
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, false, ConstexprSpecKind::Unspecified),
|
||||
ExplicitSpec(ES) {
|
||||
Ctor(Ctor), ExplicitSpec(ES) {
|
||||
if (EndLocation.isValid())
|
||||
setRangeEnd(EndLocation);
|
||||
setIsCopyDeductionCandidate(false);
|
||||
}
|
||||
|
||||
CXXConstructorDecl *Ctor;
|
||||
ExplicitSpecifier ExplicitSpec;
|
||||
void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
|
||||
|
||||
@ -1871,7 +1873,8 @@ public:
|
||||
static CXXDeductionGuideDecl *
|
||||
Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, SourceLocation EndLocation);
|
||||
TypeSourceInfo *TInfo, SourceLocation EndLocation,
|
||||
CXXConstructorDecl *Ctor = nullptr);
|
||||
|
||||
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
@ -1886,6 +1889,12 @@ public:
|
||||
return getDeclName().getCXXDeductionGuideTemplate();
|
||||
}
|
||||
|
||||
/// Get the constructor from which this deduction guide was generated, if
|
||||
/// this is an implicit deduction guide.
|
||||
CXXConstructorDecl *getCorrespondingConstructor() const {
|
||||
return Ctor;
|
||||
}
|
||||
|
||||
void setIsCopyDeductionCandidate(bool isCDC = true) {
|
||||
FunctionDeclBits.IsCopyDeductionCandidate = isCDC;
|
||||
}
|
||||
|
@ -3457,11 +3457,13 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
} else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
|
||||
ExplicitSpecifier ESpec =
|
||||
importExplicitSpecifier(Err, Guide->getExplicitSpecifier());
|
||||
CXXConstructorDecl *Ctor =
|
||||
importChecked(Err, Guide->getCorrespondingConstructor());
|
||||
if (Err)
|
||||
return std::move(Err);
|
||||
if (GetImportedOrCreateDecl<CXXDeductionGuideDecl>(
|
||||
ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, ESpec,
|
||||
NameInfo, T, TInfo, ToEndLoc))
|
||||
NameInfo, T, TInfo, ToEndLoc, Ctor))
|
||||
return ToFunction;
|
||||
cast<CXXDeductionGuideDecl>(ToFunction)
|
||||
->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate());
|
||||
|
@ -2073,19 +2073,21 @@ ExplicitSpecifier ExplicitSpecifier::getFromDecl(FunctionDecl *Function) {
|
||||
}
|
||||
}
|
||||
|
||||
CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
|
||||
ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, SourceLocation EndLocation) {
|
||||
CXXDeductionGuideDecl *
|
||||
CXXDeductionGuideDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, ExplicitSpecifier ES,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, SourceLocation EndLocation,
|
||||
CXXConstructorDecl *Ctor) {
|
||||
return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T,
|
||||
TInfo, EndLocation);
|
||||
TInfo, EndLocation, Ctor);
|
||||
}
|
||||
|
||||
CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C,
|
||||
unsigned ID) {
|
||||
return new (C, ID) CXXDeductionGuideDecl(
|
||||
C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(),
|
||||
QualType(), nullptr, SourceLocation());
|
||||
QualType(), nullptr, SourceLocation(), nullptr);
|
||||
}
|
||||
|
||||
RequiresExprBodyDecl *RequiresExprBodyDecl::Create(
|
||||
|
@ -84,6 +84,20 @@ struct EffectiveContext {
|
||||
: Inner(DC),
|
||||
Dependent(DC->isDependentContext()) {
|
||||
|
||||
// An implicit deduction guide is semantically in the context enclosing the
|
||||
// class template, but for access purposes behaves like the constructor
|
||||
// from which it was produced.
|
||||
if (auto *DGD = dyn_cast<CXXDeductionGuideDecl>(DC)) {
|
||||
if (DGD->isImplicit()) {
|
||||
DC = DGD->getCorrespondingConstructor();
|
||||
if (!DC) {
|
||||
// The copy deduction candidate doesn't have a corresponding
|
||||
// constructor.
|
||||
DC = cast<DeclContext>(DGD->getDeducedTemplate()->getTemplatedDecl());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// C++11 [class.access.nest]p1:
|
||||
// A nested class is a member and as such has the same access
|
||||
// rights as any other member.
|
||||
|
@ -2217,7 +2217,7 @@ struct ConvertConstructorToDeductionGuideTransform {
|
||||
return nullptr;
|
||||
TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType);
|
||||
|
||||
return buildDeductionGuide(TemplateParams, CD->getExplicitSpecifier(),
|
||||
return buildDeductionGuide(TemplateParams, CD, CD->getExplicitSpecifier(),
|
||||
NewTInfo, CD->getBeginLoc(), CD->getLocation(),
|
||||
CD->getEndLoc(), MaterializedTypedefs);
|
||||
}
|
||||
@ -2247,7 +2247,7 @@ struct ConvertConstructorToDeductionGuideTransform {
|
||||
Params.push_back(NewParam);
|
||||
}
|
||||
|
||||
return buildDeductionGuide(Template->getTemplateParameters(),
|
||||
return buildDeductionGuide(Template->getTemplateParameters(), nullptr,
|
||||
ExplicitSpecifier(), TSI, Loc, Loc, Loc);
|
||||
}
|
||||
|
||||
@ -2425,9 +2425,9 @@ private:
|
||||
}
|
||||
|
||||
FunctionTemplateDecl *buildDeductionGuide(
|
||||
TemplateParameterList *TemplateParams, ExplicitSpecifier ES,
|
||||
TypeSourceInfo *TInfo, SourceLocation LocStart, SourceLocation Loc,
|
||||
SourceLocation LocEnd,
|
||||
TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
|
||||
ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
|
||||
SourceLocation Loc, SourceLocation LocEnd,
|
||||
llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {}) {
|
||||
DeclarationNameInfo Name(DeductionGuideName, Loc);
|
||||
ArrayRef<ParmVarDecl *> Params =
|
||||
@ -2436,7 +2436,7 @@ private:
|
||||
// Build the implicit deduction guide template.
|
||||
auto *Guide =
|
||||
CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
|
||||
TInfo->getType(), TInfo, LocEnd);
|
||||
TInfo->getType(), TInfo, LocEnd, Ctor);
|
||||
Guide->setImplicit();
|
||||
Guide->setParams(Params);
|
||||
|
||||
|
@ -1954,6 +1954,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
|
||||
|
||||
void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
|
||||
D->setExplicitSpecifier(Record.readExplicitSpec());
|
||||
D->Ctor = readDeclAs<CXXConstructorDecl>();
|
||||
VisitFunctionDecl(D);
|
||||
D->setIsCopyDeductionCandidate(Record.readInt());
|
||||
}
|
||||
|
@ -672,6 +672,7 @@ static void addExplicitSpecifier(ExplicitSpecifier ES,
|
||||
|
||||
void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
|
||||
addExplicitSpecifier(D->getExplicitSpecifier(), Record);
|
||||
Record.AddDeclRef(D->Ctor);
|
||||
VisitFunctionDecl(D);
|
||||
Record.push_back(D->isCopyDeductionCandidate());
|
||||
Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
|
||||
|
@ -1,17 +1,46 @@
|
||||
// RUN: %clang_cc1 -std=c++17 -verify %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
namespace pr41427 {
|
||||
template <typename T> class A {
|
||||
public:
|
||||
A(void (*)(T)) {}
|
||||
};
|
||||
|
||||
|
||||
void D(int) {}
|
||||
|
||||
|
||||
void f() {
|
||||
A a(&D);
|
||||
using T = decltype(a);
|
||||
using T = A<int>;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Access {
|
||||
struct B {
|
||||
protected:
|
||||
struct type {};
|
||||
};
|
||||
template<typename T> struct D : B { // expected-note {{not viable}}
|
||||
D(T, typename T::type); // expected-note {{private member}}
|
||||
};
|
||||
D b = {B(), {}};
|
||||
|
||||
class X {
|
||||
using type = int;
|
||||
};
|
||||
D x = {X(), {}}; // expected-error {{no viable constructor or deduction guide}}
|
||||
|
||||
// Once we implement proper support for dependent nested name specifiers in
|
||||
// friends, this should still work.
|
||||
class Y {
|
||||
template <typename T> friend D<T>::D(T, typename T::type); // expected-warning {{dependent nested name specifier}}
|
||||
struct type {};
|
||||
};
|
||||
D y = {Y(), {}};
|
||||
|
||||
class Z {
|
||||
template <typename T> friend class D;
|
||||
struct type {};
|
||||
};
|
||||
D z = {Z(), {}};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user