mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-16 13:08:42 +00:00
Add an explicit derived class of FunctionDecl to model deduction guides rather
than just treating them as FunctionDecls with a funny name. No functionality change intended. llvm-svn: 295491
This commit is contained in:
parent
e6c6a945ca
commit
bc491203c7
@ -1608,7 +1608,11 @@ private:
|
||||
unsigned SClass : 2;
|
||||
unsigned IsInline : 1;
|
||||
unsigned IsInlineSpecified : 1;
|
||||
protected:
|
||||
// This is shared by CXXConstructorDecl, CXXConversionDecl, and
|
||||
// CXXDeductionGuideDecl.
|
||||
unsigned IsExplicitSpecified : 1;
|
||||
private:
|
||||
unsigned IsVirtualAsWritten : 1;
|
||||
unsigned IsPure : 1;
|
||||
unsigned HasInheritedPrototype : 1;
|
||||
@ -1855,19 +1859,6 @@ public:
|
||||
bool isVirtualAsWritten() const { return IsVirtualAsWritten; }
|
||||
void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; }
|
||||
|
||||
/// Whether this function is marked as explicit explicitly.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
void setExplicitSpecified() {
|
||||
assert((getKind() == CXXConstructor || getKind() == CXXConversion ||
|
||||
isDeductionGuide()) && "cannot be explicit");
|
||||
IsExplicitSpecified = true;
|
||||
}
|
||||
|
||||
/// Whether this function is explicit.
|
||||
bool isExplicit() const {
|
||||
return getFirstDecl()->isExplicitSpecified();
|
||||
}
|
||||
|
||||
/// Whether this virtual function is pure, i.e. makes the containing class
|
||||
/// abstract.
|
||||
bool isPure() const { return IsPure; }
|
||||
@ -1946,12 +1937,6 @@ public:
|
||||
bool isDeletedAsWritten() const { return IsDeleted && !IsDefaulted; }
|
||||
void setDeletedAsWritten(bool D = true) { IsDeleted = D; }
|
||||
|
||||
/// \brief Determines whether this function is a deduction guide.
|
||||
bool isDeductionGuide() const {
|
||||
return getDeclName().getNameKind() ==
|
||||
DeclarationName::CXXDeductionGuideName;
|
||||
}
|
||||
|
||||
/// \brief Determines whether this function is "main", which is the
|
||||
/// entry point into an executable program.
|
||||
bool isMain() const;
|
||||
|
@ -1738,6 +1738,58 @@ public:
|
||||
friend class ASTWriter;
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ deduction guide declaration.
|
||||
///
|
||||
/// \code
|
||||
/// template<typename T> struct A { A(); A(T); };
|
||||
/// A() -> A<int>;
|
||||
/// \endcode
|
||||
///
|
||||
/// In this example, there will be an explicit deduction guide from the
|
||||
/// second line, and implicit deduction guide templates synthesized from
|
||||
/// the constructors of \c A.
|
||||
class CXXDeductionGuideDecl : public FunctionDecl {
|
||||
void anchor() override;
|
||||
private:
|
||||
CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
bool IsExplicit, const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
SourceLocation EndLocation)
|
||||
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, false, false) {
|
||||
if (EndLocation.isValid())
|
||||
setRangeEnd(EndLocation);
|
||||
IsExplicitSpecified = IsExplicit;
|
||||
}
|
||||
|
||||
public:
|
||||
static CXXDeductionGuideDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, bool IsExplicit,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
SourceLocation EndLocation);
|
||||
|
||||
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
/// Whether this deduction guide is explicit.
|
||||
bool isExplicit() const { return IsExplicitSpecified; }
|
||||
|
||||
/// Whether this deduction guide was declared with the 'explicit' specifier.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
|
||||
/// Get the template for which this guide performs deduction.
|
||||
TemplateDecl *getDeducedTemplate() const {
|
||||
return getDeclName().getCXXDeductionGuideTemplate();
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == CXXDeductionGuide; }
|
||||
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
};
|
||||
|
||||
/// \brief Represents a static or instance method of a struct/union/class.
|
||||
///
|
||||
/// In the terminology of the C++ Standard, these are the (static and
|
||||
@ -2181,8 +2233,7 @@ class CXXConstructorDecl final
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
if (Inherited)
|
||||
*getTrailingObjects<InheritedConstructor>() = Inherited;
|
||||
if (isExplicitSpecified)
|
||||
setExplicitSpecified();
|
||||
IsExplicitSpecified = isExplicitSpecified;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -2258,6 +2309,14 @@ public:
|
||||
CtorInitializers = Initializers;
|
||||
}
|
||||
|
||||
/// Whether this function is marked as explicit explicitly.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
|
||||
/// Whether this function is explicit.
|
||||
bool isExplicit() const {
|
||||
return getCanonicalDecl()->isExplicitSpecified();
|
||||
}
|
||||
|
||||
/// \brief Determine whether this constructor is a delegating constructor.
|
||||
bool isDelegatingConstructor() const {
|
||||
return (getNumCtorInitializers() == 1) &&
|
||||
@ -2393,7 +2452,14 @@ public:
|
||||
|
||||
void setOperatorDelete(FunctionDecl *OD);
|
||||
const FunctionDecl *getOperatorDelete() const {
|
||||
return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete;
|
||||
return getCanonicalDecl()->OperatorDelete;
|
||||
}
|
||||
|
||||
CXXDestructorDecl *getCanonicalDecl() override {
|
||||
return cast<CXXDestructorDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
const CXXDestructorDecl *getCanonicalDecl() const {
|
||||
return const_cast<CXXDestructorDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
@ -2424,8 +2490,7 @@ class CXXConversionDecl : public CXXMethodDecl {
|
||||
SourceLocation EndLocation)
|
||||
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, isConstexpr, EndLocation) {
|
||||
if (isExplicitSpecified)
|
||||
setExplicitSpecified();
|
||||
IsExplicitSpecified = isExplicitSpecified;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -2438,6 +2503,14 @@ public:
|
||||
SourceLocation EndLocation);
|
||||
static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
/// Whether this function is marked as explicit explicitly.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
|
||||
/// Whether this function is explicit.
|
||||
bool isExplicit() const {
|
||||
return getCanonicalDecl()->isExplicitSpecified();
|
||||
}
|
||||
|
||||
/// \brief Returns the type that this conversion function is converting to.
|
||||
QualType getConversionType() const {
|
||||
return getType()->getAs<FunctionType>()->getReturnType();
|
||||
@ -2447,6 +2520,13 @@ public:
|
||||
/// a lambda closure type to a block pointer.
|
||||
bool isLambdaToBlockPointerConversion() const;
|
||||
|
||||
CXXConversionDecl *getCanonicalDecl() override {
|
||||
return cast<CXXConversionDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
const CXXConversionDecl *getCanonicalDecl() const {
|
||||
return const_cast<CXXConversionDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == CXXConversion; }
|
||||
|
@ -1946,6 +1946,13 @@ DEF_TRAVERSE_DECL(FunctionDecl, {
|
||||
ReturnValue = TraverseFunctionHelper(D);
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(CXXDeductionGuideDecl, {
|
||||
// We skip decls_begin/decls_end, which are already covered by
|
||||
// TraverseFunctionHelper().
|
||||
ShouldVisitChildren = false;
|
||||
ReturnValue = TraverseFunctionHelper(D);
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(CXXMethodDecl, {
|
||||
// We skip decls_begin/decls_end, which are already covered by
|
||||
// TraverseFunctionHelper().
|
||||
|
@ -45,6 +45,7 @@ def Named : Decl<1>;
|
||||
def ObjCAtDefsField : DDecl<Field>;
|
||||
def MSProperty : DDecl<Declarator>;
|
||||
def Function : DDecl<Declarator>, DeclContext;
|
||||
def CXXDeductionGuide : DDecl<Function>;
|
||||
def CXXMethod : DDecl<Function>;
|
||||
def CXXConstructor : DDecl<CXXMethod>;
|
||||
def CXXDestructor : DDecl<CXXMethod>;
|
||||
|
@ -1123,6 +1123,8 @@ namespace clang {
|
||||
DECL_EXPORT,
|
||||
/// \brief A CXXRecordDecl record.
|
||||
DECL_CXX_RECORD,
|
||||
/// \brief A CXXDeductionGuideDecl record.
|
||||
DECL_CXX_DEDUCTION_GUIDE,
|
||||
/// \brief A CXXMethodDecl record.
|
||||
DECL_CXX_METHOD,
|
||||
/// \brief A CXXConstructorDecl record.
|
||||
|
@ -619,6 +619,7 @@ bool Decl::isWeakImported() const {
|
||||
unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
switch (DeclKind) {
|
||||
case Function:
|
||||
case CXXDeductionGuide:
|
||||
case CXXMethod:
|
||||
case CXXConstructor:
|
||||
case ConstructorUsingShadow:
|
||||
|
@ -1472,6 +1472,23 @@ bool CXXRecordDecl::mayBeAbstract() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CXXDeductionGuideDecl::anchor() { }
|
||||
|
||||
CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
|
||||
ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit,
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
SourceLocation EndLocation) {
|
||||
return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, IsExplicit,
|
||||
NameInfo, T, TInfo, EndLocation);
|
||||
}
|
||||
|
||||
CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C,
|
||||
unsigned ID) {
|
||||
return new (C, ID) CXXDeductionGuideDecl(C, nullptr, SourceLocation(), false,
|
||||
DeclarationNameInfo(), QualType(),
|
||||
nullptr, SourceLocation());
|
||||
}
|
||||
|
||||
void CXXMethodDecl::anchor() { }
|
||||
|
||||
bool CXXMethodDecl::isStatic() const {
|
||||
|
@ -50,6 +50,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
||||
case Decl::TemplateTypeParm:
|
||||
case Decl::UnresolvedUsingValue:
|
||||
case Decl::NonTypeTemplateParm:
|
||||
case Decl::CXXDeductionGuide:
|
||||
case Decl::CXXMethod:
|
||||
case Decl::CXXConstructor:
|
||||
case Decl::CXXDestructor:
|
||||
|
@ -7658,14 +7658,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
||||
} else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
|
||||
SemaRef.CheckDeductionGuideDeclarator(D, R, SC);
|
||||
|
||||
// We don't need to store much extra information for a deduction guide, so
|
||||
// just model it as a plain FunctionDecl.
|
||||
auto *FD = FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(),
|
||||
NameInfo, R, TInfo, SC, isInline,
|
||||
true /*HasPrototype*/, isConstexpr);
|
||||
if (isExplicit)
|
||||
FD->setExplicitSpecified();
|
||||
return FD;
|
||||
return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getLocStart(),
|
||||
isExplicit, NameInfo, R, TInfo,
|
||||
D.getLocEnd());
|
||||
} else if (DC->isRecord()) {
|
||||
// If the name of the function is the same as the name of the record,
|
||||
// then this must be an invalid constructor that has a return type.
|
||||
@ -8154,7 +8149,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
// The explicit specifier shall be used only in the declaration of a
|
||||
// constructor or conversion function within its class definition;
|
||||
// see 12.3.1 and 12.3.2.
|
||||
if (isExplicit && !NewFD->isInvalidDecl() && !NewFD->isDeductionGuide()) {
|
||||
if (isExplicit && !NewFD->isInvalidDecl() &&
|
||||
!isa<CXXDeductionGuideDecl>(NewFD)) {
|
||||
if (!CurContext->isRecord()) {
|
||||
// 'explicit' was specified outside of the class.
|
||||
Diag(D.getDeclSpec().getExplicitSpecLoc(),
|
||||
@ -9152,14 +9148,14 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||
} else if (CXXConversionDecl *Conversion
|
||||
= dyn_cast<CXXConversionDecl>(NewFD)) {
|
||||
ActOnConversionDeclarator(Conversion);
|
||||
} else if (NewFD->isDeductionGuide()) {
|
||||
if (auto *TD = NewFD->getDescribedFunctionTemplate())
|
||||
} else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(NewFD)) {
|
||||
if (auto *TD = Guide->getDescribedFunctionTemplate())
|
||||
CheckDeductionGuideTemplate(TD);
|
||||
|
||||
// A deduction guide is not on the list of entities that can be
|
||||
// explicitly specialized.
|
||||
if (NewFD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
Diag(NewFD->getLocStart(), diag::err_deduction_guide_specialized)
|
||||
if (Guide->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
Diag(Guide->getLocStart(), diag::err_deduction_guide_specialized)
|
||||
<< /*explicit specialization*/ 1;
|
||||
}
|
||||
|
||||
|
@ -650,10 +650,11 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
|
||||
// FIXME: It's not clear what should happen if multiple declarations of a
|
||||
// deduction guide have different explicitness. For now at least we simply
|
||||
// reject any case where the explicitness changes.
|
||||
if (New->isDeductionGuide() &&
|
||||
New->isExplicitSpecified() != Old->isExplicitSpecified()) {
|
||||
auto *NewGuide = dyn_cast<CXXDeductionGuideDecl>(New);
|
||||
if (NewGuide && NewGuide->isExplicitSpecified() !=
|
||||
cast<CXXDeductionGuideDecl>(Old)->isExplicitSpecified()) {
|
||||
Diag(New->getLocation(), diag::err_deduction_guide_explicit_mismatch)
|
||||
<< New->isExplicitSpecified();
|
||||
<< NewGuide->isExplicitSpecified();
|
||||
Diag(Old->getLocation(), diag::note_previous_declaration);
|
||||
}
|
||||
|
||||
|
@ -3036,6 +3036,9 @@ ExprResult Sema::BuildDeclarationNameExpr(
|
||||
break;
|
||||
}
|
||||
|
||||
case Decl::CXXDeductionGuide:
|
||||
llvm_unreachable("building reference to deduction guide");
|
||||
|
||||
case Decl::MSProperty:
|
||||
valueKind = VK_LValue;
|
||||
break;
|
||||
|
@ -8296,10 +8296,10 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
|
||||
if (D->isInvalidDecl())
|
||||
continue;
|
||||
|
||||
FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(D);
|
||||
FunctionDecl *FD =
|
||||
TD ? TD->getTemplatedDecl() : dyn_cast<FunctionDecl>(D);
|
||||
if (!FD)
|
||||
auto *TD = dyn_cast<FunctionTemplateDecl>(D);
|
||||
auto *GD = dyn_cast_or_null<CXXDeductionGuideDecl>(
|
||||
TD ? TD->getTemplatedDecl() : dyn_cast<FunctionDecl>(D));
|
||||
if (!GD)
|
||||
continue;
|
||||
|
||||
// C++ [over.match.ctor]p1: (non-list copy-initialization from non-class)
|
||||
@ -8309,21 +8309,21 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
|
||||
// The converting constructors of T are candidate functions.
|
||||
if (Kind.isCopyInit() && !ListInit) {
|
||||
// Only consider converting constructors.
|
||||
if (FD->isExplicit())
|
||||
if (GD->isExplicit())
|
||||
continue;
|
||||
|
||||
// When looking for a converting constructor, deduction guides that
|
||||
// could never be called with one argument are not interesting to
|
||||
// check or note.
|
||||
if (FD->getMinRequiredArguments() > 1 ||
|
||||
(FD->getNumParams() == 0 && !FD->isVariadic()))
|
||||
if (GD->getMinRequiredArguments() > 1 ||
|
||||
(GD->getNumParams() == 0 && !GD->isVariadic()))
|
||||
continue;
|
||||
}
|
||||
|
||||
// C++ [over.match.list]p1.1: (first phase list initialization)
|
||||
// Initially, the candidate functions are the initializer-list
|
||||
// constructors of the class T
|
||||
if (OnlyListConstructors && !isInitListConstructor(FD))
|
||||
if (OnlyListConstructors && !isInitListConstructor(GD))
|
||||
continue;
|
||||
|
||||
// C++ [over.match.list]p1.2: (second phase list initialization)
|
||||
@ -8345,7 +8345,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
|
||||
Inits, Candidates,
|
||||
SuppressUserConversions);
|
||||
else
|
||||
AddOverloadCandidate(FD, I.getPair(), Inits, Candidates,
|
||||
AddOverloadCandidate(GD, I.getPair(), Inits, Candidates,
|
||||
SuppressUserConversions);
|
||||
}
|
||||
return Candidates.BestViableFunction(*this, Kind.getLocation(), Best);
|
||||
@ -8416,7 +8416,8 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
|
||||
// C++ [over.match.list]p1:
|
||||
// In copy-list-initialization, if an explicit constructor is chosen, the
|
||||
// initialization is ill-formed.
|
||||
if (Kind.isCopyInit() && ListInit && Best->Function->isExplicit()) {
|
||||
if (Kind.isCopyInit() && ListInit &&
|
||||
cast<CXXDeductionGuideDecl>(Best->Function)->isExplicit()) {
|
||||
bool IsDeductionGuide = !Best->Function->isImplicit();
|
||||
Diag(Kind.getLocation(), diag::err_deduced_class_template_explicit)
|
||||
<< TemplateName << IsDeductionGuide;
|
||||
|
@ -8992,12 +8992,10 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
|
||||
}
|
||||
|
||||
// -- F1 is generated from a deduction-guide and F2 is not
|
||||
if (Cand1.Function && Cand2.Function && Cand1.Function->isDeductionGuide() &&
|
||||
Cand1.Function->isImplicit() != Cand2.Function->isImplicit()) {
|
||||
assert(Cand2.Function->isDeductionGuide() &&
|
||||
"comparing deduction guide with non-deduction-guide");
|
||||
return Cand2.Function->isImplicit();
|
||||
}
|
||||
auto *Guide1 = dyn_cast_or_null<CXXDeductionGuideDecl>(Cand1.Function);
|
||||
auto *Guide2 = dyn_cast_or_null<CXXDeductionGuideDecl>(Cand2.Function);
|
||||
if (Guide1 && Guide2 && Guide1->isImplicit() != Guide2->isImplicit())
|
||||
return Guide2->isImplicit();
|
||||
|
||||
// -- F1 is a non-template function and F2 is a function template
|
||||
// specialization, or, if not that,
|
||||
|
@ -1438,7 +1438,8 @@ struct ConvertConstructorToDeductionGuideTransform {
|
||||
unsigned Depth1IndexAdjustment = Template->getTemplateParameters()->size();
|
||||
|
||||
/// Transform a constructor declaration into a deduction guide.
|
||||
NamedDecl *transformConstructor(FunctionTemplateDecl *FTD, FunctionDecl *FD) {
|
||||
NamedDecl *transformConstructor(FunctionTemplateDecl *FTD,
|
||||
CXXConstructorDecl *CD) {
|
||||
SmallVector<TemplateArgument, 16> SubstArgs;
|
||||
|
||||
// C++ [over.match.class.deduct]p1:
|
||||
@ -1485,7 +1486,7 @@ struct ConvertConstructorToDeductionGuideTransform {
|
||||
Args.addOuterTemplateArguments(None);
|
||||
}
|
||||
|
||||
FunctionProtoTypeLoc FPTL = FD->getTypeSourceInfo()->getTypeLoc()
|
||||
FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()->getTypeLoc()
|
||||
.getAsAdjusted<FunctionProtoTypeLoc>();
|
||||
assert(FPTL && "no prototype for constructor declaration");
|
||||
|
||||
@ -1499,9 +1500,9 @@ struct ConvertConstructorToDeductionGuideTransform {
|
||||
return nullptr;
|
||||
TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType);
|
||||
|
||||
return buildDeductionGuide(TemplateParams, FD->isExplicit(), NewTInfo,
|
||||
FD->getLocStart(), FD->getLocation(),
|
||||
FD->getLocEnd());
|
||||
return buildDeductionGuide(TemplateParams, CD->isExplicit(), NewTInfo,
|
||||
CD->getLocStart(), CD->getLocation(),
|
||||
CD->getLocEnd());
|
||||
}
|
||||
|
||||
/// Build a deduction guide with the specified parameter types.
|
||||
@ -1677,17 +1678,15 @@ private:
|
||||
bool Explicit, TypeSourceInfo *TInfo,
|
||||
SourceLocation LocStart, SourceLocation Loc,
|
||||
SourceLocation LocEnd) {
|
||||
DeclarationNameInfo Name(DeductionGuideName, Loc);
|
||||
ArrayRef<ParmVarDecl *> Params =
|
||||
TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams();
|
||||
|
||||
// Build the implicit deduction guide template.
|
||||
auto *Guide = FunctionDecl::Create(SemaRef.Context, DC, LocStart, Loc,
|
||||
DeductionGuideName, TInfo->getType(),
|
||||
TInfo, SC_None);
|
||||
auto *Guide =
|
||||
CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, Explicit,
|
||||
Name, TInfo->getType(), TInfo, LocEnd);
|
||||
Guide->setImplicit();
|
||||
if (Explicit)
|
||||
Guide->setExplicitSpecified();
|
||||
Guide->setRangeEnd(LocEnd);
|
||||
Guide->setParams(Params);
|
||||
|
||||
for (auto *Param : Params)
|
||||
@ -1749,16 +1748,16 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
|
||||
D = cast<NamedDecl>(D->getCanonicalDecl());
|
||||
|
||||
auto *FTD = dyn_cast<FunctionTemplateDecl>(D);
|
||||
auto *FD = FTD ? FTD->getTemplatedDecl() : dyn_cast<FunctionDecl>(D);
|
||||
auto *CD =
|
||||
dyn_cast_or_null<CXXConstructorDecl>(FTD ? FTD->getTemplatedDecl() : D);
|
||||
// Class-scope explicit specializations (MS extension) do not result in
|
||||
// deduction guides.
|
||||
if (!FD || (!FTD && FD->isFunctionTemplateSpecialization()))
|
||||
if (!CD || (!FTD && CD->isFunctionTemplateSpecialization()))
|
||||
continue;
|
||||
|
||||
Transform.transformConstructor(FTD, FD);
|
||||
Transform.transformConstructor(FTD, CD);
|
||||
AddedAny = true;
|
||||
|
||||
CXXConstructorDecl *CD = cast<CXXConstructorDecl>(FD);
|
||||
AddedCopyOrMove |= CD->isCopyOrMoveConstructor();
|
||||
}
|
||||
|
||||
|
@ -968,10 +968,10 @@ bool Sema::isSameOrCompatibleFunctionType(CanQualType Param,
|
||||
/// the template parameter lists of a class template and a constructor template
|
||||
/// when forming an implicit deduction guide.
|
||||
static unsigned getFirstInnerIndex(FunctionTemplateDecl *FTD) {
|
||||
if (!FTD->isImplicit() || !FTD->getTemplatedDecl()->isDeductionGuide())
|
||||
auto *Guide = dyn_cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl());
|
||||
if (!Guide || !Guide->isImplicit())
|
||||
return 0;
|
||||
return FTD->getDeclName().getCXXDeductionGuideTemplate()
|
||||
->getTemplateParameters()->size();
|
||||
return Guide->getDeducedTemplate()->getTemplateParameters()->size();
|
||||
}
|
||||
|
||||
/// Determine whether a type denotes a forwarding reference.
|
||||
|
@ -1599,21 +1599,22 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
||||
TemplateArgs);
|
||||
}
|
||||
|
||||
FunctionDecl *Function =
|
||||
FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
|
||||
D->getNameInfo(), T, TInfo,
|
||||
D->getCanonicalDecl()->getStorageClass(),
|
||||
D->isInlineSpecified(), D->hasWrittenPrototype(),
|
||||
D->isConstexpr());
|
||||
Function->setRangeEnd(D->getSourceRange().getEnd());
|
||||
FunctionDecl *Function;
|
||||
if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D))
|
||||
Function = CXXDeductionGuideDecl::Create(
|
||||
SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(),
|
||||
D->getNameInfo(), T, TInfo, D->getSourceRange().getEnd());
|
||||
else {
|
||||
Function = FunctionDecl::Create(
|
||||
SemaRef.Context, DC, D->getInnerLocStart(), D->getNameInfo(), T, TInfo,
|
||||
D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(),
|
||||
D->hasWrittenPrototype(), D->isConstexpr());
|
||||
Function->setRangeEnd(D->getSourceRange().getEnd());
|
||||
}
|
||||
|
||||
if (D->isInlined())
|
||||
Function->setImplicitlyInline();
|
||||
|
||||
// A deduction-guide could be explicit.
|
||||
if (D->isExplicitSpecified())
|
||||
Function->setExplicitSpecified();
|
||||
|
||||
if (QualifierLoc)
|
||||
Function->setQualifierInfo(QualifierLoc);
|
||||
|
||||
@ -2781,6 +2782,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
|
||||
return VisitFunctionDecl(D, nullptr);
|
||||
}
|
||||
|
||||
Decl *
|
||||
TemplateDeclInstantiator::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
|
||||
return VisitFunctionDecl(D, nullptr);
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
|
||||
return VisitCXXMethodDecl(D, nullptr);
|
||||
}
|
||||
@ -4958,8 +4964,9 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
|
||||
}
|
||||
// An implicit deduction guide acts as if it's within the class template
|
||||
// specialization described by its name and first N template params.
|
||||
if (FD->isDeductionGuide() && FD->isImplicit()) {
|
||||
TemplateDecl *TD = FD->getDeclName().getCXXDeductionGuideTemplate();
|
||||
auto *Guide = dyn_cast<CXXDeductionGuideDecl>(FD);
|
||||
if (Guide && Guide->isImplicit()) {
|
||||
TemplateDecl *TD = Guide->getDeducedTemplate();
|
||||
TemplateArgumentListInfo Args(Loc, Loc);
|
||||
for (auto Arg : TemplateArgs.getInnermost().take_front(
|
||||
TD->getTemplateParameters()->size()))
|
||||
|
@ -251,6 +251,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
|
||||
case Decl::VarTemplateSpecialization:
|
||||
case Decl::VarTemplatePartialSpecialization:
|
||||
case Decl::Function:
|
||||
case Decl::CXXDeductionGuide:
|
||||
case Decl::CXXMethod:
|
||||
case Decl::CXXConstructor:
|
||||
case Decl::CXXDestructor:
|
||||
|
@ -293,6 +293,7 @@ namespace clang {
|
||||
void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
|
||||
void VisitDeclaratorDecl(DeclaratorDecl *DD);
|
||||
void VisitFunctionDecl(FunctionDecl *FD);
|
||||
void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *GD);
|
||||
void VisitCXXMethodDecl(CXXMethodDecl *D);
|
||||
void VisitCXXConstructorDecl(CXXConstructorDecl *D);
|
||||
void VisitCXXDestructorDecl(CXXDestructorDecl *D);
|
||||
@ -1786,6 +1787,10 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
|
||||
return Redecl;
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
|
||||
VisitFunctionDecl(D);
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
|
||||
VisitFunctionDecl(D);
|
||||
|
||||
@ -3371,6 +3376,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
||||
case DECL_CXX_RECORD:
|
||||
D = CXXRecordDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
case DECL_CXX_DEDUCTION_GUIDE:
|
||||
D = CXXDeductionGuideDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
case DECL_CXX_METHOD:
|
||||
D = CXXMethodDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
|
@ -86,6 +86,7 @@ namespace clang {
|
||||
void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
|
||||
void VisitDeclaratorDecl(DeclaratorDecl *D);
|
||||
void VisitFunctionDecl(FunctionDecl *D);
|
||||
void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D);
|
||||
void VisitCXXMethodDecl(CXXMethodDecl *D);
|
||||
void VisitCXXConstructorDecl(CXXConstructorDecl *D);
|
||||
void VisitCXXDestructorDecl(CXXDestructorDecl *D);
|
||||
@ -609,6 +610,11 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
Code = serialization::DECL_FUNCTION;
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
|
||||
VisitFunctionDecl(D);
|
||||
Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
||||
VisitNamedDecl(D);
|
||||
// FIXME: convert to LazyStmtPtr?
|
||||
|
@ -5782,6 +5782,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
||||
case Decl::OMPCapturedExpr:
|
||||
case Decl::Label: // FIXME: Is this right??
|
||||
case Decl::ClassScopeFunctionSpecialization:
|
||||
case Decl::CXXDeductionGuide:
|
||||
case Decl::Import:
|
||||
case Decl::OMPThreadPrivate:
|
||||
case Decl::OMPDeclareReduction:
|
||||
|
Loading…
x
Reference in New Issue
Block a user