Author: rsmith Date: Fri Feb 17 14:05:37 2017 New Revision: 295491 URL: http://llvm.org/viewvc/llvm-project?rev=295491&view=rev Log: 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. Modified: cfe/trunk/include/clang/AST/Decl.h cfe/trunk/include/clang/AST/DeclCXX.h cfe/trunk/include/clang/AST/RecursiveASTVisitor.h cfe/trunk/include/clang/Basic/DeclNodes.td cfe/trunk/include/clang/Serialization/ASTBitCodes.h cfe/trunk/lib/AST/DeclBase.cpp cfe/trunk/lib/AST/DeclCXX.cpp cfe/trunk/lib/CodeGen/CGDecl.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/lib/Serialization/ASTCommon.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp cfe/trunk/tools/libclang/CIndex.cpp Modified: cfe/trunk/include/clang/AST/Decl.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Decl.h (original) +++ cfe/trunk/include/clang/AST/Decl.h Fri Feb 17 14:05:37 2017 @@ -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; Modified: cfe/trunk/include/clang/AST/DeclCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclCXX.h (original) +++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Feb 17 14:05:37 2017 @@ -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 CXXMeth 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; } Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Fri Feb 17 14:05:37 2017 @@ -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(). Modified: cfe/trunk/include/clang/Basic/DeclNodes.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DeclNodes.td (original) +++ cfe/trunk/include/clang/Basic/DeclNodes.td Fri Feb 17 14:05:37 2017 @@ -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>; Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original) +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Feb 17 14:05:37 2017 @@ -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. Modified: cfe/trunk/lib/AST/DeclBase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclBase.cpp (original) +++ cfe/trunk/lib/AST/DeclBase.cpp Fri Feb 17 14:05:37 2017 @@ -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: Modified: cfe/trunk/lib/AST/DeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclCXX.cpp (original) +++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Feb 17 14:05:37 2017 @@ -1472,6 +1472,23 @@ bool CXXRecordDecl::mayBeAbstract() cons 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 { Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Feb 17 14:05:37 2017 @@ -50,6 +50,7 @@ void CodeGenFunction::EmitDecl(const Dec case Decl::TemplateTypeParm: case Decl::UnresolvedUsingValue: case Decl::NonTypeTemplateParm: + case Decl::CXXDeductionGuide: case Decl::CXXMethod: case Decl::CXXConstructor: case Decl::CXXDestructor: Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Feb 17 14:05:37 2017 @@ -7658,14 +7658,9 @@ static FunctionDecl* CreateNewFunctionDe } 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, // 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(Scop } 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; } Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Feb 17 14:05:37 2017 @@ -650,10 +650,11 @@ bool Sema::MergeCXXFunctionDecl(Function // 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); } Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Feb 17 14:05:37 2017 @@ -3036,6 +3036,9 @@ ExprResult Sema::BuildDeclarationNameExp break; } + case Decl::CXXDeductionGuide: + llvm_unreachable("building reference to deduction guide"); + case Decl::MSProperty: valueKind = VK_LValue; break; Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Feb 17 14:05:37 2017 @@ -8296,10 +8296,10 @@ QualType Sema::DeduceTemplateSpecializat 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::DeduceTemplateSpecializat // 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::DeduceTemplateSpecializat 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::DeduceTemplateSpecializat // 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; Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Feb 17 14:05:37 2017 @@ -8992,12 +8992,10 @@ bool clang::isBetterOverloadCandidate(Se } // -- 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, Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Feb 17 14:05:37 2017 @@ -1438,7 +1438,8 @@ struct ConvertConstructorToDeductionGuid 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 ConvertConstructorToDeductionGuid 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 ConvertConstructorToDeductionGuid 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::DeclareImplicitDeductionGuide 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(); } Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Fri Feb 17 14:05:37 2017 @@ -968,10 +968,10 @@ bool Sema::isSameOrCompatibleFunctionTyp /// 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. Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Feb 17 14:05:37 2017 @@ -1599,21 +1599,22 @@ Decl *TemplateDeclInstantiator::VisitFun 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::VisitFun 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(So } // 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())) Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTCommon.cpp (original) +++ cfe/trunk/lib/Serialization/ASTCommon.cpp Fri Feb 17 14:05:37 2017 @@ -251,6 +251,7 @@ bool serialization::isRedeclarableDeclKi case Decl::VarTemplateSpecialization: case Decl::VarTemplatePartialSpecialization: case Decl::Function: + case Decl::CXXDeductionGuide: case Decl::CXXMethod: case Decl::CXXConstructor: case Decl::CXXDestructor: Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Feb 17 14:05:37 2017 @@ -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(CX return Redecl; } +void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { + VisitFunctionDecl(D); +} + void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { VisitFunctionDecl(D); @@ -3371,6 +3376,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID I 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; Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Feb 17 14:05:37 2017 @@ -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(Fu 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? Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=295491&r1=295490&r2=295491&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Fri Feb 17 14:05:37 2017 @@ -5782,6 +5782,7 @@ CXCursor clang_getCursorDefinition(CXCur 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: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits