r295491 - Add an explicit derived class of FunctionDecl to model deduction guides rather

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 17 12:05:38 PST 2017


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:




More information about the cfe-commits mailing list