r294266 - P0091R3: Implement basic parsing support for C++17 deduction-guides.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 6 17:37:31 PST 2017


Author: rsmith
Date: Mon Feb  6 19:37:30 2017
New Revision: 294266

URL: http://llvm.org/viewvc/llvm-project?rev=294266&view=rev
Log:
P0091R3: Implement basic parsing support for C++17 deduction-guides.

We model deduction-guides as functions with a new kind of name that identifies
the template whose deduction they guide; the bulk of this patch is adding the
new name kind. This gives us a clean way to attach an extensible list of guides
to a class template in a way that doesn't require any special handling in AST
files etc (and we're going to need these functions we come to performing
deduction).

Added:
    cfe/trunk/test/CXX/temp/temp.deduct.guide/
    cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp
    cfe/trunk/test/CXX/temp/temp.deduct.guide/p2.cpp
    cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclarationName.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/Ownership.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclarationName.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/MicrosoftMangle.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseOpenMP.cpp
    cfe/trunk/lib/Parse/ParseStmtAsm.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.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=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Feb  6 19:37:30 2017
@@ -1931,6 +1931,12 @@ 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/DeclarationName.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclarationName.h?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclarationName.h (original)
+++ cfe/trunk/include/clang/AST/DeclarationName.h Mon Feb  6 19:37:30 2017
@@ -23,6 +23,7 @@ namespace llvm {
 
 namespace clang {
   class ASTContext;
+  class CXXDeductionGuideNameExtra;
   class CXXLiteralOperatorIdName;
   class CXXOperatorIdName;
   class CXXSpecialName;
@@ -32,6 +33,7 @@ namespace clang {
   enum OverloadedOperatorKind : int;
   struct PrintingPolicy;
   class QualType;
+  class TemplateDecl;
   class Type;
   class TypeSourceInfo;
   class UsingDirectiveDecl;
@@ -56,6 +58,7 @@ public:
     CXXConstructorName,
     CXXDestructorName,
     CXXConversionFunctionName,
+    CXXDeductionGuideName,
     CXXOperatorName,
     CXXLiteralOperatorName,
     CXXUsingDirective
@@ -118,42 +121,36 @@ private:
   CXXSpecialName *getAsCXXSpecialName() const {
     NameKind Kind = getNameKind();
     if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName)
-      return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
+      return reinterpret_cast<CXXSpecialName *>(getExtra());
+    return nullptr;
+  }
+
+  /// If the stored pointer is actually a CXXDeductionGuideNameExtra, returns a
+  /// pointer to it. Otherwise, returns a NULL pointer.
+  CXXDeductionGuideNameExtra *getAsCXXDeductionGuideNameExtra() const {
+    if (getNameKind() == CXXDeductionGuideName)
+      return reinterpret_cast<CXXDeductionGuideNameExtra *>(getExtra());
     return nullptr;
   }
 
   /// getAsCXXOperatorIdName
   CXXOperatorIdName *getAsCXXOperatorIdName() const {
     if (getNameKind() == CXXOperatorName)
-      return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
+      return reinterpret_cast<CXXOperatorIdName *>(getExtra());
     return nullptr;
   }
 
   CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
     if (getNameKind() == CXXLiteralOperatorName)
-      return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask);
+      return reinterpret_cast<CXXLiteralOperatorIdName *>(getExtra());
     return nullptr;
   }
 
   // Construct a declaration name from the name of a C++ constructor,
   // destructor, or conversion function.
-  DeclarationName(CXXSpecialName *Name)
-    : Ptr(reinterpret_cast<uintptr_t>(Name)) {
-    assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
-    Ptr |= StoredDeclarationNameExtra;
-  }
-
-  // Construct a declaration name from the name of a C++ overloaded
-  // operator.
-  DeclarationName(CXXOperatorIdName *Name)
+  DeclarationName(DeclarationNameExtra *Name)
     : Ptr(reinterpret_cast<uintptr_t>(Name)) {
-    assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
-    Ptr |= StoredDeclarationNameExtra;
-  }
-
-  DeclarationName(CXXLiteralOperatorIdName *Name)
-    : Ptr(reinterpret_cast<uintptr_t>(Name)) {
-    assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId");
+    assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra");
     Ptr |= StoredDeclarationNameExtra;
   }
 
@@ -252,6 +249,10 @@ public:
   /// type associated with that name.
   QualType getCXXNameType() const;
 
+  /// If this name is the name of a C++ deduction guide, return the
+  /// template associated with that name.
+  TemplateDecl *getCXXDeductionGuideTemplate() const;
+
   /// getCXXOverloadedOperator - If this name is the name of an
   /// overloadable operator in C++ (e.g., @c operator+), retrieve the
   /// kind of overloaded operator.
@@ -346,6 +347,7 @@ class DeclarationNameTable {
   void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
   CXXOperatorIdName *CXXOperatorNames; // Operator names
   void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
+  void *CXXDeductionGuideNames; // FoldingSet<CXXDeductionGuideNameExtra> *
 
   DeclarationNameTable(const DeclarationNameTable&) = delete;
   void operator=(const DeclarationNameTable&) = delete;
@@ -368,6 +370,9 @@ public:
   /// for the given Type.
   DeclarationName getCXXDestructorName(CanQualType Ty);
 
+  /// Returns the name of a C++ deduction guide for the given template.
+  DeclarationName getCXXDeductionGuideName(TemplateDecl *TD);
+
   /// getCXXConversionFunctionName - Returns the name of a C++
   /// conversion function for the given Type.
   DeclarationName getCXXConversionFunctionName(CanQualType Ty);

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon Feb  6 19:37:30 2017
@@ -774,6 +774,11 @@ bool RecursiveASTVisitor<Derived>::Trave
       TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc()));
     break;
 
+  case DeclarationName::CXXDeductionGuideName:
+    TRY_TO(TraverseTemplateName(
+        TemplateName(NameInfo.getName().getCXXDeductionGuideTemplate())));
+    break;
+
   case DeclarationName::Identifier:
   case DeclarationName::ObjCZeroArgSelector:
   case DeclarationName::ObjCOneArgSelector:

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Feb  6 19:37:30 2017
@@ -1207,8 +1207,9 @@ def warn_cxx98_compat_unelaborated_frien
 def err_qualified_friend_not_found : Error<
   "no function named %0 with type %1 was found in the specified scope">;
 def err_introducing_special_friend : Error<
-  "must use a qualified name when declaring a %select{constructor|"
-  "destructor|conversion operator}0 as a friend">;
+  "%plural{[0,2]:must use a qualified name when declaring|3:cannot declare}0"
+  " a %select{constructor|destructor|conversion operator|deduction guide}0 "
+  "as a friend">;
 def err_tagless_friend_type_template : Error<
   "friend type templates must use an elaborated type">;
 def err_no_matching_local_friend : Error<
@@ -1960,6 +1961,15 @@ def err_deduced_class_template_compound_
   "deduced class template specialization type">;
 def err_deduced_class_template_not_supported : Error<
   "deduction of template arguments for class templates is not yet supported">;
+def err_deduction_guide_no_trailing_return_type : Error<
+  "deduction guide declaration without trailing return type">;
+def err_deduction_guide_with_complex_decl : Error<
+  "cannot specify any part of a return type in the "
+  "declaration of a deduction guide">;
+def err_deduction_guide_name_not_class_template : Error<
+  "cannot specify deduction guide for "
+  "%select{<error>|function template|variable template|alias template|"
+  "template template parameter|dependent template name}0 %1">;
 
 // C++1y deduced return types
 def err_auto_fn_deduction_failure : Error<

Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Mon Feb  6 19:37:30 2017
@@ -818,6 +818,7 @@ public:
 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
     CXXOperator##Name,
 #include "clang/Basic/OperatorKinds.def"
+    CXXDeductionGuide,
     CXXLiteralOperator,
     CXXUsingDirective,
     NUM_EXTRA_KINDS

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Feb  6 19:37:30 2017
@@ -1967,7 +1967,7 @@ private:
   /// \brief Starting with a scope specifier, identifier, or
   /// template-id that refers to the current class, determine whether
   /// this is a constructor declarator.
-  bool isConstructorDeclarator(bool Unqualified);
+  bool isConstructorDeclarator(bool Unqualified, bool DeductionGuide = false);
 
   /// \brief Specifies the context in which type-id/expression
   /// disambiguation will occur.
@@ -2634,6 +2634,7 @@ public:
   bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
                           bool AllowDestructorName,
                           bool AllowConstructorName,
+                          bool AllowDeductionGuide,
                           ParsedType ObjectType,
                           SourceLocation& TemplateKWLoc,
                           UnqualifiedId &Result);

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Mon Feb  6 19:37:30 2017
@@ -908,7 +908,9 @@ public:
     /// \brief A template-id, e.g., f<int>.
     IK_TemplateId,
     /// \brief An implicit 'self' parameter
-    IK_ImplicitSelfParam
+    IK_ImplicitSelfParam,
+    /// \brief A deduction-guide name (a template-name)
+    IK_DeductionGuideName
   } Kind;
 
   struct OFI {
@@ -928,8 +930,8 @@ public:
   /// \brief Anonymous union that holds extra data associated with the
   /// parsed unqualified-id.
   union {
-    /// \brief When Kind == IK_Identifier, the parsed identifier, or when Kind
-    /// == IK_UserLiteralId, the identifier suffix.
+    /// \brief When Kind == IK_Identifier, the parsed identifier, or when
+    /// Kind == IK_UserLiteralId, the identifier suffix.
     IdentifierInfo *Identifier;
     
     /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator
@@ -947,6 +949,9 @@ public:
     /// \brief When Kind == IK_DestructorName, the type referred to by the
     /// class-name.
     UnionParsedType DestructorName;
+
+    /// \brief When Kind == IK_DeductionGuideName, the parsed template-name.
+    UnionParsedTemplateTy TemplateName;
     
     /// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId,
     /// the template-id annotation that contains the template name and
@@ -1085,6 +1090,18 @@ public:
   /// \p TemplateId and will free it on destruction.
   void setTemplateId(TemplateIdAnnotation *TemplateId);
 
+  /// \brief Specify that this unqualified-id was parsed as a template-name for
+  /// a deduction-guide.
+  ///
+  /// \param Template The parsed template-name.
+  /// \param TemplateLoc The location of the parsed template-name.
+  void setDeductionGuideName(ParsedTemplateTy Template,
+                             SourceLocation TemplateLoc) {
+    Kind = IK_DeductionGuideName;
+    TemplateName = Template;
+    StartLocation = EndLocation = TemplateLoc;
+  }
+  
   /// \brief Return the source range that covers this unqualified-id.
   SourceRange getSourceRange() const LLVM_READONLY { 
     return SourceRange(StartLocation, EndLocation); 
@@ -2319,6 +2336,16 @@ public:
     return true;
   }
 
+  /// \brief Determine whether a trailing return type was written (at any
+  /// level) within this declarator.
+  bool hasTrailingReturnType() const {
+    for (const auto &Chunk : type_objects())
+      if (Chunk.Kind == DeclaratorChunk::Function &&
+          Chunk.Fun.hasTrailingReturnType())
+        return true;
+    return false;
+  }
+
   /// takeAttributes - Takes attributes from the given parsed-attributes
   /// set and add them to this declarator.
   ///

Modified: cfe/trunk/include/clang/Sema/Ownership.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Ownership.h?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Ownership.h (original)
+++ cfe/trunk/include/clang/Sema/Ownership.h Mon Feb  6 19:37:30 2017
@@ -257,6 +257,7 @@ namespace clang {
 
   typedef ActionResult<Decl*> DeclResult;
   typedef OpaquePtr<TemplateName> ParsedTemplateTy;
+  typedef UnionOpaquePtr<TemplateName> UnionParsedTemplateTy;
 
   typedef MutableArrayRef<Expr*> MultiExprArg;
   typedef MutableArrayRef<Stmt*> MultiStmtArg;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Feb  6 19:37:30 2017
@@ -5619,6 +5619,8 @@ public:
   void CheckConversionDeclarator(Declarator &D, QualType &R,
                                  StorageClass& SC);
   Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
+  void CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
+                                     StorageClass &SC);
 
   void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD);
   void CheckExplicitlyDefaultedMemberExceptionSpec(CXXMethodDecl *MD,
@@ -5822,6 +5824,22 @@ public:
                                   TemplateTy &Template,
                                   bool &MemberOfUnknownSpecialization);
 
+  /// Determine whether a particular identifier might be the name in a C++1z
+  /// deduction-guide declaration.
+  bool isDeductionGuideName(Scope *S, const IdentifierInfo &Name,
+                            SourceLocation NameLoc,
+                            ParsedTemplateTy *Template = nullptr) {
+    CXXScopeSpec SS;
+    UnqualifiedId Id;
+    Id.setIdentifier(&Name, NameLoc);
+    TemplateTy TemplateFallback;
+    bool MemberOfUnknownSpecialization;
+    // FIXME: Use redeclaration lookup!
+    return isTemplateName(S, SS, false, Id, ParsedType(), false,
+                          Template ? *Template : TemplateFallback,
+                          MemberOfUnknownSpecialization) == TNK_Type_template;
+  }
+
   bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
                                    SourceLocation IILoc,
                                    Scope *S,

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Mon Feb  6 19:37:30 2017
@@ -1628,7 +1628,8 @@ namespace clang {
 
       IdentifierInfo *getIdentifier() const {
         assert(Kind == DeclarationName::Identifier ||
-               Kind == DeclarationName::CXXLiteralOperatorName);
+               Kind == DeclarationName::CXXLiteralOperatorName ||
+               Kind == DeclarationName::CXXDeductionGuideName);
         return (IdentifierInfo *)Data;
       }
       Selector getSelector() const {

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Feb  6 19:37:30 2017
@@ -2264,6 +2264,7 @@ ASTNodeImporter::ImportDeclarationNameLo
   case DeclarationName::ObjCOneArgSelector:
   case DeclarationName::ObjCMultiArgSelector:
   case DeclarationName::CXXUsingDirective:
+  case DeclarationName::CXXDeductionGuideName:
     return;
 
   case DeclarationName::CXXOperatorName: {
@@ -7448,6 +7449,14 @@ DeclarationName ASTImporter::Import(Decl
                                                ToContext.getCanonicalType(T));
   }
 
+  case DeclarationName::CXXDeductionGuideName: {
+    TemplateDecl *Template = cast_or_null<TemplateDecl>(
+        Import(FromName.getCXXDeductionGuideTemplate()));
+    if (!Template)
+      return DeclarationName();
+    return ToContext.DeclarationNames.getCXXDeductionGuideName(Template);
+  }
+
   case DeclarationName::CXXConversionFunctionName: {
     QualType T = Import(FromName.getCXXNameType());
     if (T.isNull())

Modified: cfe/trunk/lib/AST/DeclarationName.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclarationName.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclarationName.cpp (original)
+++ cfe/trunk/lib/AST/DeclarationName.cpp Mon Feb  6 19:37:30 2017
@@ -14,6 +14,7 @@
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeOrdering.h"
@@ -43,6 +44,22 @@ public:
   }
 };
 
+/// Contains extra information for the name of a C++ deduction guide.
+class CXXDeductionGuideNameExtra : public DeclarationNameExtra,
+                                   public llvm::FoldingSetNode {
+public:
+  /// The template named by the deduction guide.
+  TemplateDecl *Template;
+
+  /// FETokenInfo - Extra information associated with this operator
+  /// name that can be used by the front end.
+  void *FETokenInfo;
+
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    ID.AddPointer(Template);
+  }
+};
+
 /// CXXOperatorIdName - Contains extra information for the name of an
 /// overloaded operator in C++, such as "operator+.
 class CXXOperatorIdName : public DeclarationNameExtra {
@@ -122,7 +139,13 @@ int DeclarationName::compare(Declaration
     if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
       return 1;
     return 0;
-              
+
+  case DeclarationName::CXXDeductionGuideName:
+    // We never want to compare deduction guide names for templates from
+    // different scopes, so just compare the template-name.
+    return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(),
+                   RHS.getCXXDeductionGuideTemplate()->getDeclName());
+
   case DeclarationName::CXXOperatorName:
     return compareInt(LHS.getCXXOverloadedOperator(),
                       RHS.getCXXOverloadedOperator());
@@ -179,6 +202,9 @@ void DeclarationName::print(raw_ostream
     return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
   }
 
+  case DeclarationName::CXXDeductionGuideName:
+    return getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);
+
   case DeclarationName::CXXOperatorName: {
     static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
       nullptr,
@@ -243,6 +269,9 @@ DeclarationName::NameKind DeclarationNam
     case DeclarationNameExtra::CXXDestructor:
       return CXXDestructorName;
 
+    case DeclarationNameExtra::CXXDeductionGuide:
+      return CXXDeductionGuideName;
+
     case DeclarationNameExtra::CXXConversionFunction:
       return CXXConversionFunctionName;
 
@@ -268,7 +297,15 @@ DeclarationName::NameKind DeclarationNam
 
 bool DeclarationName::isDependentName() const {
   QualType T = getCXXNameType();
-  return !T.isNull() && T->isDependentType();
+  if (!T.isNull() && T->isDependentType())
+    return true;
+
+  // A class-scope deduction guide in a dependent context has a dependent name.
+  auto *TD = getCXXDeductionGuideTemplate();
+  if (TD && TD->getDeclContext()->isDependentContext())
+    return true;
+
+  return false;
 }
 
 std::string DeclarationName::getAsString() const {
@@ -285,6 +322,12 @@ QualType DeclarationName::getCXXNameType
     return QualType();
 }
 
+TemplateDecl *DeclarationName::getCXXDeductionGuideTemplate() const {
+  if (auto *Guide = getAsCXXDeductionGuideNameExtra())
+    return Guide->Template;
+  return nullptr;
+}
+
 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
   if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
     unsigned value
@@ -312,6 +355,9 @@ void *DeclarationName::getFETokenInfoAsV
   case CXXConversionFunctionName:
     return getAsCXXSpecialName()->FETokenInfo;
 
+  case CXXDeductionGuideName:
+    return getAsCXXDeductionGuideNameExtra()->FETokenInfo;
+
   case CXXOperatorName:
     return getAsCXXOperatorIdName()->FETokenInfo;
 
@@ -335,6 +381,10 @@ void DeclarationName::setFETokenInfo(voi
     getAsCXXSpecialName()->FETokenInfo = T;
     break;
 
+  case CXXDeductionGuideName:
+    getAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
+    break;
+
   case CXXOperatorName:
     getAsCXXOperatorIdName()->FETokenInfo = T;
     break;
@@ -366,6 +416,7 @@ LLVM_DUMP_METHOD void DeclarationName::d
 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
   CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
   CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
+  CXXDeductionGuideNames = new llvm::FoldingSet<CXXDeductionGuideNameExtra>;
 
   // Initialize the overloaded operator names.
   CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
@@ -377,14 +428,18 @@ DeclarationNameTable::DeclarationNameTab
 }
 
 DeclarationNameTable::~DeclarationNameTable() {
-  llvm::FoldingSet<CXXSpecialName> *SpecialNames =
-    static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
-  llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
-    = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
-        (CXXLiteralOperatorNames);
+  auto *SpecialNames =
+      static_cast<llvm::FoldingSet<CXXSpecialName> *>(CXXSpecialNamesImpl);
+  auto *LiteralNames =
+      static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName> *>(
+          CXXLiteralOperatorNames);
+  auto *DeductionGuideNames =
+      static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>(
+          CXXDeductionGuideNames);
 
   delete SpecialNames;
   delete LiteralNames;
+  delete DeductionGuideNames;
 }
 
 DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
@@ -398,6 +453,30 @@ DeclarationName DeclarationNameTable::ge
 }
 
 DeclarationName
+DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
+  Template = cast<TemplateDecl>(Template->getCanonicalDecl());
+
+  auto *DeductionGuideNames =
+      static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>(
+          CXXDeductionGuideNames);
+
+  llvm::FoldingSetNodeID ID;
+  ID.AddPointer(Template);
+
+  void *InsertPos = nullptr;
+  if (auto *Name = DeductionGuideNames->FindNodeOrInsertPos(ID, InsertPos))
+    return DeclarationName(Name);
+
+  auto *Name = new (Ctx) CXXDeductionGuideNameExtra;
+  Name->ExtraKindOrNumArgs = DeclarationNameExtra::CXXDeductionGuide;
+  Name->Template = Template;
+  Name->FETokenInfo = nullptr;
+
+  DeductionGuideNames->InsertNode(Name, InsertPos);
+  return DeclarationName(Name);
+}
+
+DeclarationName
 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
   return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
 }
@@ -477,6 +556,7 @@ DeclarationNameTable::getCXXLiteralOpera
 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
   switch (Name.getNameKind()) {
   case DeclarationName::Identifier:
+  case DeclarationName::CXXDeductionGuideName:
     break;
   case DeclarationName::CXXConstructorName:
   case DeclarationName::CXXDestructorName:
@@ -509,6 +589,7 @@ bool DeclarationNameInfo::containsUnexpa
   case DeclarationName::CXXOperatorName:
   case DeclarationName::CXXLiteralOperatorName:
   case DeclarationName::CXXUsingDirective:
+  case DeclarationName::CXXDeductionGuideName:
     return false;
 
   case DeclarationName::CXXConstructorName:
@@ -531,6 +612,7 @@ bool DeclarationNameInfo::isInstantiatio
   case DeclarationName::CXXOperatorName:
   case DeclarationName::CXXLiteralOperatorName:
   case DeclarationName::CXXUsingDirective:
+  case DeclarationName::CXXDeductionGuideName:
     return false;
     
   case DeclarationName::CXXConstructorName:
@@ -560,6 +642,7 @@ void DeclarationNameInfo::printName(raw_
   case DeclarationName::CXXOperatorName:
   case DeclarationName::CXXLiteralOperatorName:
   case DeclarationName::CXXUsingDirective:
+  case DeclarationName::CXXDeductionGuideName:
     OS << Name;
     return;
 
@@ -585,6 +668,7 @@ void DeclarationNameInfo::printName(raw_
 SourceLocation DeclarationNameInfo::getEndLoc() const {
   switch (Name.getNameKind()) {
   case DeclarationName::Identifier:
+  case DeclarationName::CXXDeductionGuideName:
     return NameLoc;
 
   case DeclarationName::CXXOperatorName: {

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Feb  6 19:37:30 2017
@@ -1190,6 +1190,8 @@ void CXXNameMangler::mangleUnresolvedNam
       llvm_unreachable("Can't mangle a constructor name!");
     case DeclarationName::CXXUsingDirective:
       llvm_unreachable("Can't mangle a using directive name!");
+    case DeclarationName::CXXDeductionGuideName:
+      llvm_unreachable("Can't mangle a deduction guide name!");
     case DeclarationName::ObjCMultiArgSelector:
     case DeclarationName::ObjCOneArgSelector:
     case DeclarationName::ObjCZeroArgSelector:
@@ -1419,6 +1421,9 @@ void CXXNameMangler::mangleUnqualifiedNa
     writeAbiTags(ND, AdditionalAbiTags);
     break;
 
+  case DeclarationName::CXXDeductionGuideName:
+    llvm_unreachable("Can't mangle a deduction guide name!");
+
   case DeclarationName::CXXUsingDirective:
     llvm_unreachable("Can't mangle a using directive name!");
   }
@@ -1997,6 +2002,7 @@ void CXXNameMangler::mangleOperatorName(
   switch (Name.getNameKind()) {
   case DeclarationName::CXXConstructorName:
   case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXDeductionGuideName:
   case DeclarationName::CXXUsingDirective:
   case DeclarationName::Identifier:
   case DeclarationName::ObjCMultiArgSelector:

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Mon Feb  6 19:37:30 2017
@@ -942,6 +942,9 @@ void MicrosoftCXXNameMangler::mangleUnqu
       break;
     }
 
+    case DeclarationName::CXXDeductionGuideName:
+      llvm_unreachable("Can't mangle a deduction guide name!");
+
     case DeclarationName::CXXUsingDirective:
       llvm_unreachable("Can't mangle a using directive name!");
   }

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Feb  6 19:37:30 2017
@@ -3025,6 +3025,16 @@ void Parser::ParseDeclarationSpecifiers(
           isConstructorDeclarator(/*Unqualified*/true))
         goto DoneWithDeclSpec;
 
+      // Likewise, if this is a context where the identifier could be a template
+      // name, check whether this is a deduction guide declaration.
+      if (getLangOpts().CPlusPlus1z &&
+          (DSContext == DSC_class || DSContext == DSC_top_level) &&
+          Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),
+                                       Tok.getLocation()) &&
+          isConstructorDeclarator(/*Unqualified*/ true,
+                                  /*DeductionGuide*/ true))
+        goto DoneWithDeclSpec;
+
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
                                      DiagID, TypeRep, Policy);
       if (isInvalid)
@@ -4644,7 +4654,7 @@ bool Parser::isDeclarationSpecifier(bool
   }
 }
 
-bool Parser::isConstructorDeclarator(bool IsUnqualified) {
+bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) {
   TentativeParsingAction TPA(*this);
 
   // Parse the C++ scope specifier.
@@ -4732,6 +4742,11 @@ bool Parser::isConstructorDeclarator(boo
 
     case tok::r_paren:
       // C(X   )
+      if (DeductionGuide) {
+        // C(X) -> ... is a deduction guide.
+        IsConstructor = NextToken().is(tok::arrow);
+        break;
+      }
       if (NextToken().is(tok::colon) || NextToken().is(tok::kw_try)) {
         // Assume these were meant to be constructors:
         //   C(X)   :    (the name of a bit-field cannot be parenthesized).
@@ -4749,7 +4764,7 @@ bool Parser::isConstructorDeclarator(boo
         //
         // FIXME: We can actually do this whether or not the name is qualified,
         // because if it is qualified in this context it must be being used as
-        // a constructor name. However, we do not implement that rule correctly
+        // a constructor name.
         // currently, so we're somewhat conservative here.
         IsConstructor = IsUnqualified;
       }
@@ -5280,21 +5295,29 @@ void Parser::ParseDirectDeclarator(Decla
       // We found something that indicates the start of an unqualified-id.
       // Parse that unqualified-id.
       bool AllowConstructorName;
-      if (D.getDeclSpec().hasTypeSpecifier())
+      bool AllowDeductionGuide;
+      if (D.getDeclSpec().hasTypeSpecifier()) {
         AllowConstructorName = false;
-      else if (D.getCXXScopeSpec().isSet())
+        AllowDeductionGuide = false;
+      } else if (D.getCXXScopeSpec().isSet()) {
         AllowConstructorName =
           (D.getContext() == Declarator::FileContext ||
            D.getContext() == Declarator::MemberContext);
-      else
+        AllowDeductionGuide = false;
+      } else {
         AllowConstructorName = (D.getContext() == Declarator::MemberContext);
+        AllowDeductionGuide = 
+          (D.getContext() == Declarator::FileContext ||
+           D.getContext() == Declarator::MemberContext);
+      }
 
       SourceLocation TemplateKWLoc;
       bool HadScope = D.getCXXScopeSpec().isValid();
       if (ParseUnqualifiedId(D.getCXXScopeSpec(),
                              /*EnteringContext=*/true,
                              /*AllowDestructorName=*/true, AllowConstructorName,
-                             nullptr, TemplateKWLoc, D.getName()) ||
+                             AllowDeductionGuide, nullptr, TemplateKWLoc,
+                             D.getName()) ||
           // Once we're past the identifier, if the scope was bad, mark the
           // whole declarator bad.
           D.getCXXScopeSpec().isInvalid()) {

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Feb  6 19:37:30 2017
@@ -576,6 +576,7 @@ bool Parser::ParseUsingDeclarator(unsign
             /*AllowDestructorName=*/true,
             /*AllowConstructorName=*/!(Tok.is(tok::identifier) &&
                                        NextToken().is(tok::equal)),
+            /*AllowDeductionGuide=*/false,
             nullptr, D.TemplateKWLoc, D.Name))
       return true;
   }
@@ -2426,8 +2427,8 @@ Parser::ParseCXXClassMemberDeclaration(A
       // Try to parse an unqualified-id.
       SourceLocation TemplateKWLoc;
       UnqualifiedId Name;
-      if (ParseUnqualifiedId(SS, false, true, true, nullptr, TemplateKWLoc,
-                             Name)) {
+      if (ParseUnqualifiedId(SS, false, true, true, false, nullptr,
+                             TemplateKWLoc, Name)) {
         SkipUntil(tok::semi);
         return nullptr;
       }

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Feb  6 19:37:30 2017
@@ -1693,6 +1693,7 @@ Parser::ParsePostfixExpressionSuffix(Exp
                                     /*AllowDestructorName=*/true,
                                     /*AllowConstructorName=*/
                                       getLangOpts().MicrosoftExt, 
+                                    /*AllowDeductionGuide=*/false,
                                     ObjectType, TemplateKWLoc, Name)) {
         (void)Actions.CorrectDelayedTyposInExpr(LHS);
         LHS = ExprError();

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Mon Feb  6 19:37:30 2017
@@ -546,6 +546,7 @@ ExprResult Parser::tryParseCXXIdExpressi
                          /*EnteringContext=*/false,
                          /*AllowDestructorName=*/false,
                          /*AllowConstructorName=*/false,
+                         /*AllowDeductionGuide=*/false,
                          /*ObjectType=*/nullptr, TemplateKWLoc, Name))
     return ExprError();
 
@@ -2429,6 +2430,8 @@ bool Parser::ParseUnqualifiedIdOperator(
 ///
 /// \param AllowConstructorName whether we allow parsing a constructor name.
 ///
+/// \param AllowDeductionGuide whether we allow parsing a deduction guide name.
+///
 /// \param ObjectType if this unqualified-id occurs within a member access
 /// expression, the type of the base object whose member is being accessed.
 ///
@@ -2438,6 +2441,7 @@ bool Parser::ParseUnqualifiedIdOperator(
 bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
                                 bool AllowDestructorName,
                                 bool AllowConstructorName,
+                                bool AllowDeductionGuide,
                                 ParsedType ObjectType,
                                 SourceLocation& TemplateKWLoc,
                                 UnqualifiedId &Result) {
@@ -2466,6 +2470,7 @@ bool Parser::ParseUnqualifiedId(CXXScope
       return false;
     }
 
+    ParsedTemplateTy TemplateName;
     if (AllowConstructorName && 
         Actions.isCurrentClassName(*Id, getCurScope(), &SS)) {
       // We have parsed a constructor name.
@@ -2474,6 +2479,12 @@ bool Parser::ParseUnqualifiedId(CXXScope
                                           /*IsCtorOrDtorName=*/true,
                                           /*NonTrivialTypeSourceInfo=*/true);
       Result.setConstructorName(Ty, IdLoc, IdLoc);
+    } else if (getLangOpts().CPlusPlus1z &&
+               AllowDeductionGuide && SS.isEmpty() &&
+               Actions.isDeductionGuideName(getCurScope(), *Id, IdLoc,
+                                            &TemplateName)) {
+      // We have parsed a template-name naming a deduction guide.
+      Result.setDeductionGuideName(TemplateName, IdLoc);
     } else {
       // We have parsed an identifier.
       Result.setIdentifier(Id, IdLoc);      

Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Mon Feb  6 19:37:30 2017
@@ -1053,7 +1053,7 @@ bool Parser::ParseOpenMPSimpleVarList(
       IsCorrect = false;
       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                 StopBeforeMatch);
-    } else if (ParseUnqualifiedId(SS, false, false, false, nullptr,
+    } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
                                   TemplateKWLoc, Name)) {
       IsCorrect = false;
       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
@@ -1557,8 +1557,9 @@ static bool ParseReductionId(Parser &P,
   }
   return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
                               /*AllowDestructorName*/ false,
-                              /*AllowConstructorName*/ false, nullptr,
-                              TemplateKWLoc, ReductionId);
+                              /*AllowConstructorName*/ false,
+                              /*AllowDeductionGuide*/ false,
+                              nullptr, TemplateKWLoc, ReductionId);
 }
 
 /// Parses clauses with list.

Modified: cfe/trunk/lib/Parse/ParseStmtAsm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmtAsm.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmtAsm.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmtAsm.cpp Mon Feb  6 19:37:30 2017
@@ -224,6 +224,7 @@ ExprResult Parser::ParseMSAsmIdentifier(
                                  /*EnteringContext=*/false,
                                  /*AllowDestructorName=*/false,
                                  /*AllowConstructorName=*/false,
+                                 /*AllowDeductionGuide=*/false,
                                  /*ObjectType=*/nullptr, TemplateKWLoc, Id);
     // Perform the lookup.
     Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Feb  6 19:37:30 2017
@@ -1966,8 +1966,10 @@ bool Parser::ParseMicrosoftIfExistsCondi
 
   // Parse the unqualified-id.
   SourceLocation TemplateKWLoc; // FIXME: parsed, but unused.
-  if (ParseUnqualifiedId(Result.SS, false, true, true, nullptr, TemplateKWLoc,
-                         Result.Name)) {
+  if (ParseUnqualifiedId(
+          Result.SS, /*EnteringContext*/false, /*AllowDestructorName*/true,
+          /*AllowConstructorName*/true, /*AllowDeductionGuide*/false, nullptr,
+          TemplateKWLoc, Result.Name)) {
     T.skipToEnd();
     return true;
   }

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Mon Feb  6 19:37:30 2017
@@ -2585,6 +2585,7 @@ static void AddTypedNameChunk(ASTContext
                       Result.getAllocator().CopyString(ND->getNameAsString()));
     break;
       
+  case DeclarationName::CXXDeductionGuideName:
   case DeclarationName::CXXUsingDirective:
   case DeclarationName::ObjCZeroArgSelector:
   case DeclarationName::ObjCOneArgSelector:

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Feb  6 19:37:30 2017
@@ -4675,6 +4675,34 @@ Sema::GetNameFromUnqualifiedId(const Unq
     NameInfo.setLoc(Name.StartLocation);
     return NameInfo;
 
+  case UnqualifiedId::IK_DeductionGuideName: {
+    // C++ [temp.deduct.guide]p3:
+    //   The simple-template-id shall name a class template specialization.
+    //   The template-name shall be the same identifier as the template-name
+    //   of the simple-template-id.
+    // These together intend to imply that the template-name shall name a
+    // class template.
+    // FIXME: template<typename T> struct X {};
+    //        template<typename T> using Y = X<T>;
+    //        Y(int) -> Y<int>;
+    //   satisfies these rules but does not name a class template.
+    TemplateName TN = Name.TemplateName.get().get();
+    auto *Template = TN.getAsTemplateDecl();
+    if (!Template || !isa<ClassTemplateDecl>(Template)) {
+      Diag(Name.StartLocation,
+           diag::err_deduction_guide_name_not_class_template)
+        << (int)getTemplateNameKindForDiagnostics(TN) << TN;
+      if (Template)
+        Diag(Template->getLocation(), diag::note_template_decl_here);
+      return DeclarationNameInfo();
+    }
+
+    NameInfo.setName(
+        Context.DeclarationNames.getCXXDeductionGuideName(Template));
+    NameInfo.setLoc(Name.StartLocation);
+    return NameInfo;
+  }
+
   case UnqualifiedId::IK_OperatorFunctionId:
     NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
                                            Name.OperatorFunctionId.Operator));
@@ -7621,6 +7649,15 @@ static FunctionDecl* CreateNewFunctionDe
                                      R, TInfo, isInline, isExplicit,
                                      isConstexpr, SourceLocation());
 
+  } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
+    SemaRef.CheckDeductionGuideDeclarator(D, R, SC);
+
+    // We don't need to store any extra information for a deduction guide, so
+    // just model it as a plain FunctionDecl.
+    return FunctionDecl::Create(SemaRef.Context, DC,
+                                D.getLocStart(),
+                                NameInfo, R, TInfo, SC, isInline,
+                                true/*HasPrototype*/, isConstexpr);
   } 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.
@@ -8109,7 +8146,7 @@ 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()) {
+    if (isExplicit && !NewFD->isInvalidDecl() && !NewFD->isDeductionGuide()) {
       if (!CurContext->isRecord()) {
         // 'explicit' was specified outside of the class.
         Diag(D.getDeclSpec().getExplicitSpecLoc(),

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Feb  6 19:37:30 2017
@@ -8033,6 +8033,15 @@ Decl *Sema::ActOnConversionDeclarator(CX
   return Conversion;
 }
 
+/// Check the validity of a declarator that we parsed for a deduction-guide.
+/// These aren't actually declarators in the grammar, so we need to check that
+/// the user didn't specify any pieces that are not part of the deduction-guide
+/// grammar.
+void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
+                                         StorageClass &SC) {
+  // FIXME: Implement
+}
+
 //===----------------------------------------------------------------------===//
 // Namespace Handling
 //===----------------------------------------------------------------------===//
@@ -8613,6 +8622,9 @@ Decl *Sema::ActOnUsingDeclaration(Scope
     Diag(Name.getLocStart(), diag::err_using_decl_template_id)
       << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
     return nullptr;
+
+  case UnqualifiedId::IK_DeductionGuideName:
+    llvm_unreachable("cannot parse qualified deduction guide name");
   }
 
   DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
@@ -13747,6 +13759,9 @@ NamedDecl *Sema::ActOnFriendFunctionDecl
     case UnqualifiedId::IK_ConversionFunctionId:
       DiagArg = 2;
       break;
+    case UnqualifiedId::IK_DeductionGuideName:
+      DiagArg = 3;
+      break;
     case UnqualifiedId::IK_Identifier:
     case UnqualifiedId::IK_ImplicitSelfParam:
     case UnqualifiedId::IK_LiteralOperatorId:

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Mon Feb  6 19:37:30 2017
@@ -321,6 +321,7 @@ bool Sema::DiagnoseUnexpandedParameterPa
   case DeclarationName::CXXOperatorName:
   case DeclarationName::CXXLiteralOperatorName:
   case DeclarationName::CXXUsingDirective:
+  case DeclarationName::CXXDeductionGuideName:
     return false;
 
   case DeclarationName::CXXConstructorName:

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Feb  6 19:37:30 2017
@@ -2733,6 +2733,17 @@ static QualType GetDeclSpecTypeForDeclar
                      D.getDeclSpec().getAttributes().getList());
     break;
 
+  case UnqualifiedId::IK_DeductionGuideName:
+    // Deduction guides have a trailing return type and no type in their
+    // decl-specifier sequence.
+    T = SemaRef.Context.getAutoDeductType();
+    if (!D.hasTrailingReturnType()) {
+      SemaRef.Diag(D.getName().getLocStart(),
+                   diag::err_deduction_guide_no_trailing_return_type);
+      D.setInvalidType(true);
+    }
+    break;
+
   case UnqualifiedId::IK_ConversionFunctionId:
     // The result type of a conversion function is the type that it
     // converts to.
@@ -2884,20 +2895,10 @@ static QualType GetDeclSpecTypeForDeclar
     // better diagnostics.
     // We don't support '__auto_type' with trailing return types.
     // FIXME: Should we only do this for 'auto' and not 'decltype(auto)'?
-    if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType) {
-      for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
-        unsigned chunkIndex = e - i - 1;
-        state.setCurrentChunkIndex(chunkIndex);
-        DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
-        if (DeclType.Kind == DeclaratorChunk::Function) {
-          const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
-          if (FTI.hasTrailingReturnType()) {
-            HaveTrailing = true;
-            Error = -1;
-            break;
-          }
-        }
-      }
+    if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType &&
+        D.hasTrailingReturnType()) {
+      HaveTrailing = true;
+      Error = -1;
     }
 
     SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
@@ -4176,16 +4177,22 @@ static TypeSourceInfo *GetFullTypeForDec
         } else if (FTI.hasTrailingReturnType()) {
           // T must be exactly 'auto' at this point. See CWG issue 681.
           if (isa<ParenType>(T)) {
-            S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+            S.Diag(D.getLocStart(),
                  diag::err_trailing_return_in_parens)
-              << T << D.getDeclSpec().getSourceRange();
+              << T << D.getSourceRange();
             D.setInvalidType(true);
           } else if (D.getContext() != Declarator::LambdaExprContext &&
                      (T.hasQualifiers() || !isa<AutoType>(T) ||
-                      cast<AutoType>(T)->getKeyword() != AutoTypeKeyword::Auto)) {
-            S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
-                 diag::err_trailing_return_without_auto)
-              << T << D.getDeclSpec().getSourceRange();
+                      cast<AutoType>(T)->getKeyword() !=
+                          AutoTypeKeyword::Auto)) {
+            if (D.getName().getKind() == UnqualifiedId::IK_DeductionGuideName)
+              S.Diag(D.getDeclSpec().getLocStart(),
+                     diag::err_deduction_guide_with_complex_decl)
+                  << D.getSourceRange();
+            else
+              S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+                     diag::err_trailing_return_without_auto)
+                  << T << D.getDeclSpec().getSourceRange();
             D.setInvalidType(true);
           }
           T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo);

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Feb  6 19:37:30 2017
@@ -3617,6 +3617,19 @@ TreeTransform<Derived>
   case DeclarationName::CXXUsingDirective:
     return NameInfo;
 
+  case DeclarationName::CXXDeductionGuideName: {
+    TemplateDecl *OldTemplate = Name.getCXXDeductionGuideTemplate();
+    TemplateDecl *NewTemplate = cast_or_null<TemplateDecl>(
+        getDerived().TransformDecl(NameInfo.getLoc(), OldTemplate));
+    if (!NewTemplate)
+      return DeclarationNameInfo();
+
+    DeclarationNameInfo NewNameInfo(NameInfo);
+    NewNameInfo.setName(
+        SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(NewTemplate));
+    return NewNameInfo;
+  }
+
   case DeclarationName::CXXConstructorName:
   case DeclarationName::CXXDestructorName:
   case DeclarationName::CXXConversionFunctionName: {

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Feb  6 19:37:30 2017
@@ -944,6 +944,10 @@ DeclarationNameKey::DeclarationNameKey(D
   case DeclarationName::CXXLiteralOperatorName:
     Data = (uint64_t)Name.getCXXLiteralIdentifier();
     break;
+  case DeclarationName::CXXDeductionGuideName:
+    Data = (uint64_t)Name.getCXXDeductionGuideTemplate()
+               ->getDeclName().getAsIdentifierInfo();
+    break;
   case DeclarationName::CXXConstructorName:
   case DeclarationName::CXXDestructorName:
   case DeclarationName::CXXConversionFunctionName:
@@ -960,6 +964,7 @@ unsigned DeclarationNameKey::getHash() c
   switch (Kind) {
   case DeclarationName::Identifier:
   case DeclarationName::CXXLiteralOperatorName:
+  case DeclarationName::CXXDeductionGuideName:
     ID.AddString(((IdentifierInfo*)Data)->getName());
     break;
   case DeclarationName::ObjCZeroArgSelector:
@@ -1003,6 +1008,8 @@ ASTDeclContextNameLookupTrait::ReadKey(c
   uint64_t Data;
   switch (Kind) {
   case DeclarationName::Identifier:
+  case DeclarationName::CXXLiteralOperatorName:
+  case DeclarationName::CXXDeductionGuideName:
     Data = (uint64_t)Reader.getLocalIdentifier(
         F, endian::readNext<uint32_t, little, unaligned>(d));
     break;
@@ -1017,10 +1024,6 @@ ASTDeclContextNameLookupTrait::ReadKey(c
   case DeclarationName::CXXOperatorName:
     Data = *d++; // OverloadedOperatorKind
     break;
-  case DeclarationName::CXXLiteralOperatorName:
-    Data = (uint64_t)Reader.getLocalIdentifier(
-        F, endian::readNext<uint32_t, little, unaligned>(d));
-    break;
   case DeclarationName::CXXConstructorName:
   case DeclarationName::CXXDestructorName:
   case DeclarationName::CXXConversionFunctionName:
@@ -7992,6 +7995,10 @@ ASTReader::ReadDeclarationName(ModuleFil
     return Context.DeclarationNames.getCXXDestructorName(
                           Context.getCanonicalType(readType(F, Record, Idx)));
 
+  case DeclarationName::CXXDeductionGuideName:
+    return Context.DeclarationNames.getCXXDeductionGuideName(
+                          ReadDeclAs<TemplateDecl>(F, Record, Idx));
+
   case DeclarationName::CXXConversionFunctionName:
     return Context.DeclarationNames.getCXXConversionFunctionName(
                           Context.getCanonicalType(readType(F, Record, Idx)));
@@ -8039,6 +8046,7 @@ void ASTReader::ReadDeclarationNameLoc(M
   case DeclarationName::ObjCOneArgSelector:
   case DeclarationName::ObjCMultiArgSelector:
   case DeclarationName::CXXUsingDirective:
+  case DeclarationName::CXXDeductionGuideName:
     break;
   }
 }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Feb  6 19:37:30 2017
@@ -3600,6 +3600,7 @@ public:
     case DeclarationName::ObjCOneArgSelector:
     case DeclarationName::ObjCMultiArgSelector:
     case DeclarationName::CXXLiteralOperatorName:
+    case DeclarationName::CXXDeductionGuideName:
       KeyLen += 4;
       break;
     case DeclarationName::CXXOperatorName:
@@ -3629,6 +3630,7 @@ public:
     switch (Name.getKind()) {
     case DeclarationName::Identifier:
     case DeclarationName::CXXLiteralOperatorName:
+    case DeclarationName::CXXDeductionGuideName:
       LE.write<uint32_t>(Writer.getIdentifierRef(Name.getIdentifier()));
       return;
     case DeclarationName::ObjCZeroArgSelector:
@@ -5273,6 +5275,10 @@ void ASTRecordWriter::AddDeclarationName
     AddTypeRef(Name.getCXXNameType());
     break;
 
+  case DeclarationName::CXXDeductionGuideName:
+    AddDeclRef(Name.getCXXDeductionGuideTemplate());
+    break;
+
   case DeclarationName::CXXOperatorName:
     Record->push_back(Name.getCXXOverloadedOperator());
     break;
@@ -5334,6 +5340,7 @@ void ASTRecordWriter::AddDeclarationName
   case DeclarationName::ObjCOneArgSelector:
   case DeclarationName::ObjCMultiArgSelector:
   case DeclarationName::CXXUsingDirective:
+  case DeclarationName::CXXDeductionGuideName:
     break;
   }
 }

Added: cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp?rev=294266&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp Mon Feb  6 19:37:30 2017
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s -DCLASS
+
+#ifdef CLASS
+struct Outer {
+#endif
+
+template<typename> struct A {};
+
+// Valid forms.
+A(int(&)[1]) -> A<int>;
+explicit A(int(&)[2]) -> A<int>;
+
+// Declarator pieces are not OK.
+*A(int(&)[3]) -> A<int>; // expected-error {{cannot specify any part of a return type in the declaration of a deduction guide}}
+&A(int(&)[4]) -> A<int>; // expected-error {{cannot specify any part of a return type in the declaration of a deduction guide}}
+A(int(&)[5])[3] -> A<int>;
+#ifdef CLASS // FIXME: These diagnostics are both pretty bad.
+// expected-error at -2 {{deduction guide declaration without trailing return type}} expected-error at -2 {{array of 'auto'}} expected-error at -2 {{';'}}
+#else
+// expected-error at -4 {{expected function body after function declarator}}
+#endif
+
+// (Pending DR) attributes and parens around the declarator-id are OK.
+[[deprecated]] A(int(&)[6]) [[]] -> A<int> [[]];
+A [[]] (int(&)[7]) -> A<int>; // FIXME: expected-error 2{{expected}} expected-note {{to match}}
+(A)(int(&)[8]) -> A<int>;
+
+// ... but the trailing-return-type is part of the function-declarator as normal
+(A(int(&)[9])) -> A<int>;
+#ifdef CLASS // FIXME: These diagnostics are both pretty bad.
+// expected-error at -2 {{deduction guide declaration without trailing return type}} expected-error at -2 {{';'}}
+#else
+// expected-error at -4 {{expected function body after function declarator}}
+#endif
+(A(int(&)[10]) -> A<int>); // expected-error {{trailing return type may not be nested within parentheses}}
+
+// A trailing-return-type is mandatory.
+A(int(&)[11]); // expected-error {{deduction guide declaration without trailing return type}}
+
+// No type specifier is permitted; we don't even parse such cases as a deduction-guide.
+int A(int) -> A<int>; // expected-error {{function with trailing return type must specify return type 'auto', not 'int'}}
+template<typename T> struct B {}; // expected-note {{here}}
+auto B(int) -> B<int>; // expected-error {{redefinition of 'B' as different kind of symbol}}
+
+// FIXME: No storage class specifier, function specifier, ...
+friend A(int(&)[20]) -> A<int>;
+#ifdef CLASS
+// expected-error at -2 {{cannot declare a deduction guide as a friend}}
+#else
+// expected-error at -4 {{'friend' used outside of class}}
+#endif
+typedef A(int(&)[21]) -> A<int>; // FIXME: Bad diagnostic: expected-error {{typedef name must be an identifier}}
+constexpr A(int(&)[22]) -> A<int>;
+inline A(int(&)[23]) -> A<int>;
+static A(int(&)[24]) -> A<int>;
+thread_local A(int(&)[25]) -> A<int>; // expected-error {{'thread_local' is only allowed on variable declarations}}
+extern A(int(&)[26]) -> A<int>;
+#ifdef CLASS
+// expected-error at -2 {{storage class specified for a member}}
+#endif
+mutable A(int(&)[27]) -> A<int>; // expected-error-re {{{{'mutable' cannot be applied to|illegal storage class on}} function}}
+virtual A(int(&)[28]) -> A<int>; // expected-error {{'virtual' can only appear on non-static member functions}}
+
+// FIXME: No definition is allowed.
+A(int(&)[30]) -> A<int> {}
+A(int(&)[31]) -> A<int> = default; // expected-error {{only special member functions may be defaulted}}
+A(int(&)[32]) -> A<int> = delete;
+A(int(&)[33]) -> A<int> try {} catch (...) {}
+
+#ifdef CLASS
+};
+#endif

Added: cfe/trunk/test/CXX/temp/temp.deduct.guide/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.deduct.guide/p2.cpp?rev=294266&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.deduct.guide/p2.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.deduct.guide/p2.cpp Mon Feb  6 19:37:30 2017
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+namespace std_example {
+  template<typename T, typename U = int> struct S {
+    T data;
+  };
+  template<typename U> S(U) -> S<typename U::type>;
+
+  struct A {
+    using type = short;
+    operator type();
+  };
+  S x{A()}; // expected-error {{not yet supported}}
+}

Added: cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp?rev=294266&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp Mon Feb  6 19:37:30 2017
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -std=c++1z %s -verify
+
+// The same restrictions apply to the parameter-declaration-clause of a
+// deduction guide as in a function declaration.
+template<typename T> struct A {};
+A(void) -> A<int>; // ok
+A(void, int) -> A<int>; // expected-error {{'void' must be the first and only parameter if specified}}
+
+// We interpret this as also extending to the validity of redeclarations. It's
+// a bit of a stretch (OK, a lot of a stretch) but it gives desirable answers.
+A() -> A<int>; // ok, redeclaration
+
+A() -> A<int>; // expected-note {{previous}}
+A() -> A<float>; // FIXME: "functions" is a poor term. expected-error {{functions that differ only in their return type cannot be overloaded}}
+
+template<typename T> A(T) -> A<typename T::foo>;
+template<typename T> A(T) -> A<typename T::bar>; // ok, can overload on return type (SFINAE applies)
+
+A(long) -> A<int>;
+template<typename T = int> A(long) -> A<char>; // ok, non-template beats template as usual
+
+// (Pending DR) The template-name shall name a class template.
+template<typename T> using B = A<T>; // expected-note {{template}}
+B() -> B<int>; // expected-error {{cannot specify deduction guide for alias template 'B'}}
+// FIXME: expected-error at -1 {{declarator requires an identifier}}
+template<typename T> int C;
+C() -> int; // expected-error {{requires a type specifier}}
+template<typename T> void D();
+D() -> int; // expected-error {{requires a type specifier}}
+template<template<typename> typename TT> struct E { // expected-note 2{{template}}
+  // FIXME: Should only diagnose this once!
+  TT(int) -> TT<int>; // expected-error 2{{cannot specify deduction guide for template template parameter 'TT'}} expected-error {{requires an identifier}}
+};
+
+// FIXME: Even if the DR is applied as we hope, we should still warn if the
+// trailing-return-type can obviously never produce a specialization of the
+// named template.
+A(int) -> int;
+template<typename T> A(T) -> T*;
+
+// A deduction-guide shall be declared in the same scope as the corresponding
+// class template.
+namespace WrongScope {
+  namespace {
+    template<typename T> struct AnonNS1 {};
+    AnonNS1(float) -> AnonNS1<float>; // ok
+  }
+  AnonNS1(int) -> AnonNS1<int>; // FIXME
+  template<typename T> struct AnonNS2 {};
+  namespace {
+    AnonNS1(char) -> AnonNS1<char>; // ok
+    AnonNS2(int) -> AnonNS2<int>; // FIXME
+  }
+  namespace N {
+    template<typename T> struct NamedNS1 {};
+    template<typename T> struct NamedNS2 {};
+  }
+  using N::NamedNS1;
+  NamedNS1(int) -> NamedNS1<int>; // FIXME
+  using namespace N;
+  NamedNS2(int) -> NamedNS2<int>; // FIXME
+  struct ClassMemberA {
+    template<typename T> struct X {};
+  };
+  struct ClassMemberB : ClassMemberA {
+    X(int) -> X<int>; // FIXME
+  };
+  template<typename T> struct Local {};
+  void f() {
+    Local(int) -> Local<int>; // expected-error 2{{expected}} expected-note {{to match}}
+    using WrongScope::Local;
+    Local(int) -> Local<int>; // expected-error 2{{expected}} expected-note {{to match}}
+  }
+}

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=294266&r1=294265&r2=294266&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Mon Feb  6 19:37:30 2017
@@ -1265,10 +1265,11 @@ bool CursorVisitor::VisitDeclarationName
   switch (Name.getName().getNameKind()) {
   case clang::DeclarationName::Identifier:
   case clang::DeclarationName::CXXLiteralOperatorName:
+  case clang::DeclarationName::CXXDeductionGuideName:
   case clang::DeclarationName::CXXOperatorName:
   case clang::DeclarationName::CXXUsingDirective:
     return false;
-      
+
   case clang::DeclarationName::CXXConstructorName:
   case clang::DeclarationName::CXXDestructorName:
   case clang::DeclarationName::CXXConversionFunctionName:




More information about the cfe-commits mailing list