]> granicus.if.org Git - clang/commitdiff
Revert "DR1391: Check for implicit conversion sequences for non-dependent function...
authorRenato Golin <renato.golin@linaro.org>
Mon, 2 Jan 2017 11:15:42 +0000 (11:15 +0000)
committerRenato Golin <renato.golin@linaro.org>
Mon, 2 Jan 2017 11:15:42 +0000 (11:15 +0000)
This reverts commit r290808, as it broken all ARM and AArch64 test-suite
test: MultiSource/UnitTests/C++11/frame_layout

Also, please, next time, try to write a commit message in according to
our guidelines:

http://llvm.org/docs/DeveloperPolicy.html#commit-messages

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@290811 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Overload.h
include/clang/Sema/Sema.h
lib/Sema/SemaOverload.cpp
lib/Sema/SemaTemplateDeduction.cpp
test/CXX/drs/dr13xx.cpp
test/Misc/diag-template-diffing.cpp
test/SemaCXX/overload-call.cpp
test/SemaCXX/overload-member-call.cpp
www/cxx_dr_status.html

index 0d74816dfd068311c30a9a910f87c1b643067b3e..376db92d03bd5265cae79cdea7f4f40c1481fba1 100644 (file)
@@ -531,13 +531,6 @@ namespace clang {
       Ambiguous.construct();
     }
 
-    void setAsIdentityConversion(QualType T) {
-      setStandard();
-      Standard.setAsIdentityConversion();
-      Standard.setFromType(T);
-      Standard.setAllToTypes(T);
-    }
-
     /// \brief Whether the target is really a std::initializer_list, and the
     /// sequence only represents the worst element conversion.
     bool isStdInitializerListElement() const {
@@ -610,11 +603,6 @@ namespace clang {
     ovl_fail_ext_disabled,
   };
 
-  /// A list of implicit conversion sequences for the arguments of an
-  /// OverloadCandidate.
-  typedef llvm::MutableArrayRef<ImplicitConversionSequence>
-      ConversionSequenceList;
-
   /// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
   struct OverloadCandidate {
     /// Function - The actual function that this candidate
@@ -639,13 +627,18 @@ namespace clang {
     /// is a surrogate, but only if IsSurrogate is true.
     CXXConversionDecl *Surrogate;
 
-    /// The conversion sequences used to convert the function arguments
-    /// to the function parameters.
-    ConversionSequenceList Conversions;
+    /// Conversions - The conversion sequences used to convert the
+    /// function arguments to the function parameters, the pointer points to a
+    /// fixed size array with NumConversions elements. The memory is owned by
+    /// the OverloadCandidateSet.
+    ImplicitConversionSequence *Conversions;
 
     /// The FixIt hints which can be used to fix the Bad candidate.
     ConversionFixItGenerator Fix;
 
+    /// NumConversions - The number of elements in the Conversions array.
+    unsigned NumConversions;
+
     /// Viable - True to indicate that this overload candidate is viable.
     bool Viable;
 
@@ -684,9 +677,9 @@ namespace clang {
     /// hasAmbiguousConversion - Returns whether this overload
     /// candidate requires an ambiguous conversion or not.
     bool hasAmbiguousConversion() const {
-      for (auto &C : Conversions) {
-        if (!C.isInitialized()) return false;
-        if (C.isAmbiguous()) return true;
+      for (unsigned i = 0, e = NumConversions; i != e; ++i) {
+        if (!Conversions[i].isInitialized()) return false;
+        if (Conversions[i].isAmbiguous()) return true;
       }
       return false;
     }
@@ -735,7 +728,7 @@ namespace clang {
     SmallVector<OverloadCandidate, 16> Candidates;
     llvm::SmallPtrSet<Decl *, 16> Functions;
 
-    // Allocator for ConversionSequenceLists. We store the first few
+    // Allocator for OverloadCandidate::Conversions. We store the first few
     // elements inline to avoid allocation for small sets.
     llvm::BumpPtrAllocator ConversionSequenceAllocator;
 
@@ -776,45 +769,30 @@ namespace clang {
     size_t size() const { return Candidates.size(); }
     bool empty() const { return Candidates.empty(); }
 
-    /// \brief Allocate storage for conversion sequences for NumConversions
-    /// conversions.
-    ConversionSequenceList
-    allocateConversionSequences(unsigned NumConversions) {
-      ImplicitConversionSequence *Conversions;
+    /// \brief Add a new candidate with NumConversions conversion sequence slots
+    /// to the overload set.
+    OverloadCandidate &addCandidate(unsigned NumConversions = 0) {
+      Candidates.push_back(OverloadCandidate());
+      OverloadCandidate &C = Candidates.back();
 
       // Assign space from the inline array if there are enough free slots
       // available.
       if (NumConversions + NumInlineSequences <= 16) {
         ImplicitConversionSequence *I =
             (ImplicitConversionSequence *)InlineSpace.buffer;
-        Conversions = &I[NumInlineSequences];
+        C.Conversions = &I[NumInlineSequences];
         NumInlineSequences += NumConversions;
       } else {
         // Otherwise get memory from the allocator.
-        Conversions =
-            ConversionSequenceAllocator.Allocate<ImplicitConversionSequence>(
-                NumConversions);
+        C.Conversions = ConversionSequenceAllocator
+                          .Allocate<ImplicitConversionSequence>(NumConversions);
       }
 
       // Construct the new objects.
-      for (unsigned I = 0; I != NumConversions; ++I)
-        new (&Conversions[I]) ImplicitConversionSequence();
-
-      return ConversionSequenceList(Conversions, NumConversions);
-    }
-
-    /// \brief Add a new candidate with NumConversions conversion sequence slots
-    /// to the overload set.
-    OverloadCandidate &addCandidate(unsigned NumConversions = 0,
-                                    ConversionSequenceList Conversions = None) {
-      assert((Conversions.empty() || Conversions.size() == NumConversions) &&
-             "preallocated conversion sequence has wrong length");
+      for (unsigned i = 0; i != NumConversions; ++i)
+        new (&C.Conversions[i]) ImplicitConversionSequence();
 
-      Candidates.push_back(OverloadCandidate());
-      OverloadCandidate &C = Candidates.back();
-      C.Conversions = Conversions.empty()
-                          ? allocateConversionSequences(NumConversions)
-                          : Conversions;
+      C.NumConversions = NumConversions;
       return C;
     }
 
index a7e563d3b86b8ffb46a8bf09e358d417671bc310..82caaeb24ae72ff2d579ebc58ca87d26831d0c98 100644 (file)
@@ -119,7 +119,6 @@ namespace clang {
   class FunctionProtoType;
   class FunctionTemplateDecl;
   class ImplicitConversionSequence;
-  typedef MutableArrayRef<ImplicitConversionSequence> ConversionSequenceList;
   class InitListExpr;
   class InitializationKind;
   class InitializationSequence;
@@ -2511,11 +2510,10 @@ public:
   void AddOverloadCandidate(FunctionDecl *Function,
                             DeclAccessPair FoundDecl,
                             ArrayRef<Expr *> Args,
-                            OverloadCandidateSet &CandidateSet,
+                            OverloadCandidateSetCandidateSet,
                             bool SuppressUserConversions = false,
                             bool PartialOverloading = false,
-                            bool AllowExplicit = false,
-                            ConversionSequenceList EarlyConversions = None);
+                            bool AllowExplicit = false);
   void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
                       ArrayRef<Expr *> Args,
                       OverloadCandidateSet &CandidateSet,
@@ -2535,8 +2533,7 @@ public:
                           ArrayRef<Expr *> Args,
                           OverloadCandidateSet& CandidateSet,
                           bool SuppressUserConversions = false,
-                          bool PartialOverloading = false,
-                          ConversionSequenceList EarlyConversions = None);
+                          bool PartialOverloading = false);
   void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
                                   DeclAccessPair FoundDecl,
                                   CXXRecordDecl *ActingContext,
@@ -2554,15 +2551,6 @@ public:
                                     OverloadCandidateSet& CandidateSet,
                                     bool SuppressUserConversions = false,
                                     bool PartialOverloading = false);
-  bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate,
-                                    ArrayRef<Expr *> Args,
-                                    OverloadCandidateSet &CandidateSet,
-                                    ConversionSequenceList &Conversions,
-                                    bool SuppressUserConversions,
-                                    CXXRecordDecl *ActingContext = nullptr,
-                                    QualType ObjectType = QualType(),
-                                    Expr::Classification
-                                        ObjectClassification = {});
   void AddConversionCandidate(CXXConversionDecl *Conversion,
                               DeclAccessPair FoundDecl,
                               CXXRecordDecl *ActingContext,
@@ -6591,8 +6579,6 @@ public:
     /// \brief The arguments included an overloaded function name that could
     /// not be resolved to a suitable function.
     TDK_FailedOverloadResolution,
-    /// \brief Checking non-dependent argument conversions failed.
-    TDK_NonDependentConversionFailure,
     /// \brief Deduction failed; that's all we know.
     TDK_MiscellaneousDeductionFailure,
     /// \brief CUDA Target attributes do not match.
@@ -6630,14 +6616,14 @@ public:
     QualType OriginalArgType;
   };
 
-  TemplateDeductionResult FinishTemplateArgumentDeduction(
-      FunctionTemplateDecl *FunctionTemplate,
-      SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-      unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
-      sema::TemplateDeductionInfo &Info,
-      SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
-      bool PartialOverloading = false,
-      llvm::function_ref<bool()> CheckNonDependent = []{ return false; });
+  TemplateDeductionResult
+  FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+                      SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                  unsigned NumExplicitlySpecified,
+                                  FunctionDecl *&Specialization,
+                                  sema::TemplateDeductionInfo &Info,
+           SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
+                                  bool PartialOverloading = false);
 
   TemplateDeductionResult
   DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
@@ -6645,8 +6631,7 @@ public:
                           ArrayRef<Expr *> Args,
                           FunctionDecl *&Specialization,
                           sema::TemplateDeductionInfo &Info,
-                          bool PartialOverloading,
-                          llvm::function_ref<bool()> CheckNonDependent);
+                          bool PartialOverloading = false);
 
   TemplateDeductionResult
   DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
index a2ee2b00ecfc6c4778e33f5384f039f900829cb3..47e3df20d9111fb36ec02aeff13fe8d84b98b318 100644 (file)
@@ -589,6 +589,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
   Result.Result = static_cast<unsigned>(TDK);
   Result.HasDiagnostic = false;
   switch (TDK) {
+  case Sema::TDK_Success:
   case Sema::TDK_Invalid:
   case Sema::TDK_InstantiationDepth:
   case Sema::TDK_TooManyArguments:
@@ -647,10 +648,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
   case Sema::TDK_FailedOverloadResolution:
     Result.Data = Info.Expression;
     break;
-
-  case Sema::TDK_Success:
-  case Sema::TDK_NonDependentConversionFailure:
-    llvm_unreachable("not a deduction failure");
   }
 
   return Result;
@@ -667,7 +664,6 @@ void DeductionFailureInfo::Destroy() {
   case Sema::TDK_InvalidExplicitArguments:
   case Sema::TDK_FailedOverloadResolution:
   case Sema::TDK_CUDATargetMismatch:
-  case Sema::TDK_NonDependentConversionFailure:
     break;
 
   case Sema::TDK_Inconsistent:
@@ -711,7 +707,6 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
   case Sema::TDK_CUDATargetMismatch:
-  case Sema::TDK_NonDependentConversionFailure:
     return TemplateParameter();
 
   case Sema::TDK_Incomplete:
@@ -744,7 +739,6 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
   case Sema::TDK_CUDATargetMismatch:
-  case Sema::TDK_NonDependentConversionFailure:
     return nullptr;
 
   case Sema::TDK_DeducedMismatch:
@@ -773,7 +767,6 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
   case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_FailedOverloadResolution:
   case Sema::TDK_CUDATargetMismatch:
-  case Sema::TDK_NonDependentConversionFailure:
     return nullptr;
 
   case Sema::TDK_Inconsistent:
@@ -802,7 +795,6 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
   case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_FailedOverloadResolution:
   case Sema::TDK_CUDATargetMismatch:
-  case Sema::TDK_NonDependentConversionFailure:
     return nullptr;
 
   case Sema::TDK_Inconsistent:
@@ -837,8 +829,8 @@ llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() {
 
 void OverloadCandidateSet::destroyCandidates() {
   for (iterator i = begin(), e = end(); i != e; ++i) {
-    for (auto &C : i->Conversions)
-      C.~ImplicitConversionSequence();
+    for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
+      i->Conversions[ii].~ImplicitConversionSequence();
     if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction)
       i->DeductionFailure.Destroy();
   }
@@ -5845,8 +5837,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
                            OverloadCandidateSet &CandidateSet,
                            bool SuppressUserConversions,
                            bool PartialOverloading,
-                           bool AllowExplicit,
-                           ConversionSequenceList EarlyConversions) {
+                           bool AllowExplicit) {
   const FunctionProtoType *Proto
     = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
   assert(Proto && "Functions without a prototype cannot be overloaded");
@@ -5865,7 +5856,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
       AddMethodCandidate(Method, FoundDecl, Method->getParent(),
                          QualType(), Expr::Classification::makeSimpleLValue(),
                          Args, CandidateSet, SuppressUserConversions,
-                         PartialOverloading, EarlyConversions);
+                         PartialOverloading);
       return;
     }
     // We treat a constructor like a non-member function, since its object
@@ -5898,8 +5889,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
 
   // Add this candidate
-  OverloadCandidate &Candidate =
-      CandidateSet.addCandidate(Args.size(), EarlyConversions);
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
   Candidate.FoundDecl = FoundDecl;
   Candidate.Function = Function;
   Candidate.Viable = true;
@@ -5963,10 +5953,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
   // Determine the implicit conversion sequences for each of the
   // arguments.
   for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
-    if (Candidate.Conversions[ArgIdx].isInitialized()) {
-      // We already formed a conversion sequence for this parameter during
-      // template argument deduction.
-    } else if (ArgIdx < NumParams) {
+    if (ArgIdx < NumParams) {
       // (C++ 13.3.2p3): for F to be a viable function, there shall
       // exist for each argument an implicit conversion sequence
       // (13.3.3.1) that converts that argument to the corresponding
@@ -6275,8 +6262,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
                          ArrayRef<Expr *> Args,
                          OverloadCandidateSet &CandidateSet,
                          bool SuppressUserConversions,
-                         bool PartialOverloading,
-                         ConversionSequenceList EarlyConversions) {
+                         bool PartialOverloading) {
   const FunctionProtoType *Proto
     = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
   assert(Proto && "Methods without a prototype cannot be overloaded");
@@ -6297,8 +6283,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
 
   // Add this candidate
-  OverloadCandidate &Candidate =
-      CandidateSet.addCandidate(Args.size() + 1, EarlyConversions);
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1);
   Candidate.FoundDecl = FoundDecl;
   Candidate.Function = Method;
   Candidate.IsSurrogate = false;
@@ -6360,10 +6345,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
   // Determine the implicit conversion sequences for each of the
   // arguments.
   for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
-    if (Candidate.Conversions[ArgIdx + 1].isInitialized()) {
-      // We already formed a conversion sequence for this parameter during
-      // template argument deduction.
-    } else if (ArgIdx < NumParams) {
+    if (ArgIdx < NumParams) {
       // (C++ 13.3.2p3): for F to be a viable function, there shall
       // exist for each argument an implicit conversion sequence
       // (13.3.3.1) that converts that argument to the corresponding
@@ -6424,30 +6406,19 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
   //   functions.
   TemplateDeductionInfo Info(CandidateSet.getLocation());
   FunctionDecl *Specialization = nullptr;
-  ConversionSequenceList Conversions;
-  if (TemplateDeductionResult Result = DeduceTemplateArguments(
-          MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info,
-          PartialOverloading, [&]() {
-            return CheckNonDependentConversions(
-                MethodTmpl, Args, CandidateSet, Conversions,
-                SuppressUserConversions, ActingContext, ObjectType,
-                ObjectClassification);
-          })) {
-    OverloadCandidate &Candidate =
-        CandidateSet.addCandidate(Conversions.size(), Conversions);
+  if (TemplateDeductionResult Result
+      = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args,
+                                Specialization, Info, PartialOverloading)) {
+    OverloadCandidate &Candidate = CandidateSet.addCandidate();
     Candidate.FoundDecl = FoundDecl;
     Candidate.Function = MethodTmpl->getTemplatedDecl();
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_deduction;
     Candidate.IsSurrogate = false;
     Candidate.IgnoreObjectArgument = false;
     Candidate.ExplicitCallArguments = Args.size();
-    if (Result == TDK_NonDependentConversionFailure)
-      Candidate.FailureKind = ovl_fail_bad_conversion;
-    else {
-      Candidate.FailureKind = ovl_fail_bad_deduction;
-      Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
-                                                            Info);
-    }
+    Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+                                                          Info);
     return;
   }
 
@@ -6458,8 +6429,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
          "Specialization is not a member function?");
   AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
                      ActingContext, ObjectType, ObjectClassification, Args,
-                     CandidateSet, SuppressUserConversions, PartialOverloading,
-                     Conversions);
+                     CandidateSet, SuppressUserConversions, PartialOverloading);
 }
 
 /// \brief Add a C++ function template specialization as a candidate
@@ -6487,29 +6457,19 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
   //   functions.
   TemplateDeductionInfo Info(CandidateSet.getLocation());
   FunctionDecl *Specialization = nullptr;
-  ConversionSequenceList Conversions;
-  if (TemplateDeductionResult Result = DeduceTemplateArguments(
-          FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info,
-          PartialOverloading, [&]() {
-            return CheckNonDependentConversions(FunctionTemplate, Args,
-                                                CandidateSet, Conversions,
-                                                SuppressUserConversions);
-          })) {
-    OverloadCandidate &Candidate =
-        CandidateSet.addCandidate(Conversions.size(), Conversions);
+  if (TemplateDeductionResult Result
+        = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args,
+                                  Specialization, Info, PartialOverloading)) {
+    OverloadCandidate &Candidate = CandidateSet.addCandidate();
     Candidate.FoundDecl = FoundDecl;
     Candidate.Function = FunctionTemplate->getTemplatedDecl();
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_deduction;
     Candidate.IsSurrogate = false;
     Candidate.IgnoreObjectArgument = false;
     Candidate.ExplicitCallArguments = Args.size();
-    if (Result == TDK_NonDependentConversionFailure)
-      Candidate.FailureKind = ovl_fail_bad_conversion;
-    else {
-      Candidate.FailureKind = ovl_fail_bad_deduction;
-      Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
-                                                            Info);
-    }
+    Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+                                                          Info);
     return;
   }
 
@@ -6517,64 +6477,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
   // deduction as a candidate.
   assert(Specialization && "Missing function template specialization?");
   AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
-                       SuppressUserConversions, PartialOverloading,
-                       /*AllowExplicit*/false, Conversions);
-}
-
-/// Check that implicit conversion sequences can be formed for each argument
-/// whose corresponding parameter has a non-dependent type, per DR1391's
-/// [temp.deduct.call]p10.
-bool Sema::CheckNonDependentConversions(
-    FunctionTemplateDecl *FunctionTemplate, ArrayRef<Expr *> Args,
-    OverloadCandidateSet &CandidateSet, ConversionSequenceList &Conversions,
-    bool SuppressUserConversions, CXXRecordDecl *ActingContext,
-    QualType ObjectType, Expr::Classification ObjectClassification) {
-  // FIXME: The cases in which we allow explicit conversions for constructor
-  // arguments never consider calling a constructor template. It's not clear
-  // that is correct.
-  const bool AllowExplicit = false;
-
-  auto *FD = FunctionTemplate->getTemplatedDecl();
-  auto *Method = dyn_cast<CXXMethodDecl>(FD);
-  bool HasThisConversion = Method && !isa<CXXConstructorDecl>(Method);
-  unsigned ThisConversions = HasThisConversion ? 1 : 0;
-
-  Conversions =
-      CandidateSet.allocateConversionSequences(ThisConversions + Args.size());
-
-  // Overload resolution is always an unevaluated context.
-  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
-
-  // For a method call, check the 'this' conversion here too. DR1391 doesn't
-  // require that, but this check should never result in a hard error, and
-  // overload resolution is permitted to sidestep instantiations.
-  if (HasThisConversion && !cast<CXXMethodDecl>(FD)->isStatic() &&
-      !ObjectType.isNull()) {
-    Conversions[0] = TryObjectArgumentInitialization(
-        *this, CandidateSet.getLocation(), ObjectType, ObjectClassification,
-        Method, ActingContext);
-    if (Conversions[0].isBad())
-      return true;
-  }
-
-
-  for (unsigned I = 0, N = std::min<unsigned>(FD->getNumParams(), Args.size());
-       I != N; ++I) {
-    QualType ParamType = FD->getParamDecl(I)->getType();
-    if (!ParamType->isDependentType()) {
-      Conversions[ThisConversions + I]
-        = TryCopyInitialization(*this, Args[I], ParamType,
-                                SuppressUserConversions,
-                                /*InOverloadResolution=*/true,
-                                /*AllowObjCWritebackConversion=*/
-                                  getLangOpts().ObjCAutoRefCount,
-                                AllowExplicit);
-      if (Conversions[ThisConversions + I].isBad())
-        return true;
-    }
-  }
-
-  return false;
+                       SuppressUserConversions, PartialOverloading);
 }
 
 /// Determine whether this is an allowable conversion from the result
@@ -8813,8 +8716,8 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
 
   // Define functions that don't require ill-formed conversions for a given
   // argument to be better candidates than functions that do.
-  unsigned NumArgs = Cand1.Conversions.size();
-  assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch");
+  unsigned NumArgs = Cand1.NumConversions;
+  assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
   bool HasBetterConversion = false;
   for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
     bool Cand1Bad = IsIllFormedConversion(Cand1.Conversions[ArgIdx]);
@@ -10021,7 +9924,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
 
   case ovl_fail_bad_conversion: {
     unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
-    for (unsigned N = Cand->Conversions.size(); I != N; ++I)
+    for (unsigned N = Cand->NumConversions; I != N; ++I)
       if (Cand->Conversions[I].isBad())
         return DiagnoseBadConversion(S, Cand, I, TakingCandidateAddress);
 
@@ -10084,12 +9987,12 @@ static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
 static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc,
                                          SourceLocation OpLoc,
                                          OverloadCandidate *Cand) {
-  assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary");
+  assert(Cand->NumConversions <= 2 && "builtin operator is not binary");
   std::string TypeStr("operator");
   TypeStr += Opc;
   TypeStr += "(";
   TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
-  if (Cand->Conversions.size() == 1) {
+  if (Cand->NumConversions == 1) {
     TypeStr += ")";
     S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
   } else {
@@ -10102,7 +10005,9 @@ static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc,
 
 static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
                                          OverloadCandidate *Cand) {
-  for (const ImplicitConversionSequence &ICS : Cand->Conversions) {
+  unsigned NoOperands = Cand->NumConversions;
+  for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
+    const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
     if (ICS.isBad()) break; // all meaningless after first invalid
     if (!ICS.isAmbiguous()) continue;
 
@@ -10122,8 +10027,7 @@ static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
 static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
   switch ((Sema::TemplateDeductionResult)DFI.Result) {
   case Sema::TDK_Success:
-  case Sema::TDK_NonDependentConversionFailure:
-    llvm_unreachable("non-deduction failure while diagnosing bad deduction");
+    llvm_unreachable("TDK_success while diagnosing bad deduction");
 
   case Sema::TDK_Invalid:
   case Sema::TDK_Incomplete:
@@ -10226,11 +10130,11 @@ struct CompareOverloadCandidatesForDisplay {
 
         // If there's any ordering between the defined conversions...
         // FIXME: this might not be transitive.
-        assert(L->Conversions.size() == R->Conversions.size());
+        assert(L->NumConversions == R->NumConversions);
 
         int leftBetter = 0;
         unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
-        for (unsigned E = L->Conversions.size(); I != E; ++I) {
+        for (unsigned E = L->NumConversions; I != E; ++I) {
           switch (CompareImplicitConversionSequences(S, Loc,
                                                      L->Conversions[I],
                                                      R->Conversions[I])) {
@@ -10279,8 +10183,7 @@ struct CompareOverloadCandidatesForDisplay {
 }
 
 /// CompleteNonViableCandidate - Normally, overload resolution only
-/// computes up to the first bad conversion. Produces the FixIt set if
-/// possible.
+/// computes up to the first. Produces the FixIt set if possible.
 static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
                                        ArrayRef<Expr *> Args) {
   assert(!Cand->Viable);
@@ -10293,24 +10196,30 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
   // Use a implicit copy initialization to check conversion fixes.
   Cand->Fix.setConversionChecker(TryCopyInitialization);
 
-  // Attempt to fix the bad conversion.
-  unsigned ConvCount = Cand->Conversions.size();
-  for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); /**/;
-       ++ConvIdx) {
+  // Skip forward to the first bad conversion.
+  unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
+  unsigned ConvCount = Cand->NumConversions;
+  while (true) {
     assert(ConvIdx != ConvCount && "no bad conversion in candidate");
-    if (Cand->Conversions[ConvIdx].isInitialized() &&
-        Cand->Conversions[ConvIdx].isBad()) {
-      Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
+    ConvIdx++;
+    if (Cand->Conversions[ConvIdx - 1].isBad()) {
+      Unfixable = !Cand->TryToFixBadConversion(ConvIdx - 1, S);
       break;
     }
   }
 
+  if (ConvIdx == ConvCount)
+    return;
+
+  assert(!Cand->Conversions[ConvIdx].isInitialized() &&
+         "remaining conversion is initialized?");
+
   // FIXME: this should probably be preserved from the overload
   // operation somehow.
   bool SuppressUserConversions = false;
 
-  const FunctionProtoType *Proto;
-  unsigned ArgIdx = 0;
+  const FunctionProtoTypeProto;
+  unsigned ArgIdx = ConvIdx;
 
   if (Cand->IsSurrogate) {
     QualType ConvType
@@ -10318,56 +10227,40 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
     if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
       ConvType = ConvPtrType->getPointeeType();
     Proto = ConvType->getAs<FunctionProtoType>();
-    ArgIdx = 1;
+    ArgIdx--;
   } else if (Cand->Function) {
     Proto = Cand->Function->getType()->getAs<FunctionProtoType>();
     if (isa<CXXMethodDecl>(Cand->Function) &&
         !isa<CXXConstructorDecl>(Cand->Function))
-      ArgIdx = 1;
+      ArgIdx--;
   } else {
     // Builtin binary operator with a bad first conversion.
     assert(ConvCount <= 3);
-    for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
-         ConvIdx != ConvCount; ++ConvIdx) {
-      if (Cand->Conversions[ConvIdx].isInitialized())
-        continue;
-      if (Cand->BuiltinTypes.ParamTypes[ConvIdx]->isDependentType())
-        Cand->Conversions[ConvIdx].setAsIdentityConversion(
-            Args[ConvIdx]->getType());
-      else
-        Cand->Conversions[ConvIdx] = TryCopyInitialization(
-            S, Args[ConvIdx], Cand->BuiltinTypes.ParamTypes[ConvIdx],
-            SuppressUserConversions,
-            /*InOverloadResolution*/ true,
-            /*AllowObjCWritebackConversion=*/
-            S.getLangOpts().ObjCAutoRefCount);
-      // FIXME: If the conversion is bad, try to fix it.
-    }
+    for (; ConvIdx != ConvCount; ++ConvIdx)
+      Cand->Conversions[ConvIdx]
+        = TryCopyInitialization(S, Args[ConvIdx],
+                                Cand->BuiltinTypes.ParamTypes[ConvIdx],
+                                SuppressUserConversions,
+                                /*InOverloadResolution*/ true,
+                                /*AllowObjCWritebackConversion=*/
+                                  S.getLangOpts().ObjCAutoRefCount);
     return;
   }
 
   // Fill in the rest of the conversions.
   unsigned NumParams = Proto->getNumParams();
-  for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
-       ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
-    if (Cand->Conversions[ConvIdx].isInitialized()) {
-      // Found the bad conversion.
-    } else if (ArgIdx < NumParams) {
-      if (Proto->getParamType(ArgIdx)->isDependentType())
-        Cand->Conversions[ConvIdx].setAsIdentityConversion(
-            Args[ArgIdx]->getType());
-      else {
-        Cand->Conversions[ConvIdx] =
-            TryCopyInitialization(S, Args[ArgIdx], Proto->getParamType(ArgIdx),
-                                  SuppressUserConversions,
-                                  /*InOverloadResolution=*/true,
-                                  /*AllowObjCWritebackConversion=*/
-                                  S.getLangOpts().ObjCAutoRefCount);
-        // Store the FixIt in the candidate if it exists.
-        if (!Unfixable && Cand->Conversions[ConvIdx].isBad())
-          Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
-      }
-    } else
+  for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
+    if (ArgIdx < NumParams) {
+      Cand->Conversions[ConvIdx] = TryCopyInitialization(
+          S, Args[ArgIdx], Proto->getParamType(ArgIdx), SuppressUserConversions,
+          /*InOverloadResolution=*/true,
+          /*AllowObjCWritebackConversion=*/
+          S.getLangOpts().ObjCAutoRefCount);
+      // Store the FixIt in the candidate if it exists.
+      if (!Unfixable && Cand->Conversions[ConvIdx].isBad())
+        Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
+    }
+    else
       Cand->Conversions[ConvIdx].setEllipsis();
   }
 }
index dc291836fb94db78415070c1afda0cbf2bd351c6..0bc85a2f2635bd68c05ce96d5f6638a9a0ae9605 100644 (file)
@@ -2849,13 +2849,14 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
 ///
 /// \param OriginalCallArgs If non-NULL, the original call arguments against
 /// which the deduced argument types should be compared.
-Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
-    FunctionTemplateDecl *FunctionTemplate,
-    SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-    unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
-    TemplateDeductionInfo &Info,
-    SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
-    bool PartialOverloading, llvm::function_ref<bool()> CheckNonDependent) {
+Sema::TemplateDeductionResult
+Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+                       SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                      unsigned NumExplicitlySpecified,
+                                      FunctionDecl *&Specialization,
+                                      TemplateDeductionInfo &Info,
+        SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
+                                      bool PartialOverloading) {
   // Unevaluated SFINAE context.
   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
   SFINAETrap Trap(*this);
@@ -2882,18 +2883,6 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
           PartialOverloading))
     return Result;
 
-  // C++ [temp.deduct.call]p10: [DR1391]
-  //   If deduction succeeds for all parameters that contain
-  //   template-parameters that participate in template argument deduction,
-  //   and all template arguments are explicitly specified, deduced, or
-  //   obtained from default template arguments, remaining parameters are then
-  //   compared with the corresponding arguments. For each remaining parameter
-  //   P with a type that was non-dependent before substitution of any
-  //   explicitly-specified template arguments, if the corresponding argument
-  //   A cannot be implicitly converted to P, deduction fails.
-  if (CheckNonDependent())
-    return TDK_NonDependentConversionFailure;
-
   // Form the template argument list from the deduced template arguments.
   TemplateArgumentList *DeducedArgumentList
     = TemplateArgumentList::CreateCopy(Context, Builder);
@@ -3318,17 +3307,12 @@ DeduceTemplateArgumentByListElement(Sema &S,
 /// \param Info the argument will be updated to provide additional information
 /// about template argument deduction.
 ///
-/// \param CheckNonDependent A callback to invoke to check conversions for
-/// non-dependent parameters, between deduction and substitution, per DR1391.
-/// If this returns true, substitution will be skipped and we return
-/// TDK_NonDependentConversionFailure.
-///
 /// \returns the result of template argument deduction.
 Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
     FunctionTemplateDecl *FunctionTemplate,
     TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
     FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
-    bool PartialOverloading, llvm::function_ref<bool()> CheckNonDependent) {
+    bool PartialOverloading) {
   if (FunctionTemplate->isInvalidDecl())
     return TDK_Invalid;
 
@@ -3512,7 +3496,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
   return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
                                          NumExplicitlySpecified, Specialization,
                                          Info, &OriginalCallArgs,
-                                         PartialOverloading, CheckNonDependent);
+                                         PartialOverloading);
 }
 
 QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
index b9be5ca821c5c5f6380c4227254ed77912fcd839..28bebcbb607e64228b677117c85b8c95cb45d8e0 100644 (file)
@@ -174,81 +174,3 @@ namespace dr1359 { // dr1359: 3.5
   constexpr Y y = Y(); // expected-error {{no matching}}
 #endif
 }
-
-namespace dr1391 { // dr1391: partial
-  struct A {}; struct B : A {};
-  template<typename T> struct C { C(int); typename T::error error; }; // expected-error 2{{'::'}}
-  template<typename T> struct D {};
-
-  // No deduction is performed for parameters with no deducible template-parameters, therefore types do not need to match.
-  template<typename T> void a(T, int T::*);
-  void test_a(int A::*p) { a(A(), p); } // ok, type of second parameter does not need to match
-
-  namespace dr_example_1 {
-    template<typename T, typename U> void f(C<T>);
-    template<typename T> void f(D<T>);
-
-    void g(D<int> d) {
-      f(d); // ok, first 'f' eliminated by deduction failure
-      f<int>(d); // ok, first 'f' eliminated because 'U' cannot be deduced
-    }
-  }
-
-  namespace dr_example_2 {
-    template<typename T> typename C<T>::error f(int, T);
-    template<typename T> T f(T, T);
-
-    void g(A a) {
-      f(a, a); // ok, no conversion from A to int for first parameter of first candidate
-    }
-  }
-
-  namespace std_example {
-    template<typename T> struct Z {
-      typedef typename T::x xx;
-    };
-    template<typename T> typename Z<T>::xx f(void *, T);
-    template<typename T> void f(int, T);
-    struct A {} a;
-    void g() { f(1, a); }
-  }
-
-  template<typename T> void b(C<int> ci, T *p);
-  void b(...);
-  void test_b() {
-    b(0, 0); // ok, deduction fails prior to forming a conversion sequence and instantiating C<int>
-    // FIXME: The "while substituting" note should point at the overload candidate.
-    b<int>(0, 0); // expected-note {{instantiation of}} expected-note {{while substituting}}
-  }
-
-  template<typename T> struct Id { typedef T type; };
-  template<typename T> void c(T, typename Id<C<T> >::type);
-  void test_c() {
-    // Implicit conversion sequences for dependent types are checked later.
-    c(0.0, 0); // expected-note {{instantiation of}}
-  }
-
-  namespace partial_ordering {
-    // FIXME: Second template should be considered more specialized because non-dependent parameter is ignored.
-    template<typename T> int a(T, short) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}}
-    template<typename T> int a(T*, char); // expected-note {{candidate}}
-    int test_a = a((int*)0, 0); // FIXME: expected-error {{ambiguous}}
-
-    // FIXME: Second template should be considered more specialized:
-    // deducing #1 from #2 ignores the second P/A pair, so deduction succeeds,
-    // deducing #2 from #1 fails to deduce T, so deduction fails.
-    template<typename T> int b(T, int) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}}
-    template<typename T, typename U> int b(T*, U); // expected-note {{candidate}}
-    int test_b = b((int*)0, 0); // FIXME: expected-error {{ambiguous}}
-
-    // Unintended consequences: because partial ordering does not consider
-    // explicit template arguments, and deduction from a non-dependent type
-    // vacuously succeeds, a non-dependent template is less specialized than
-    // anything else!
-    // According to DR1391, this is ambiguous!
-    template<typename T> int c(int);
-    template<typename T> int c(T);
-    int test_c1 = c(0); // ok
-    int test_c2 = c<int>(0); // FIXME: apparently ambiguous
-  }
-}
index 2192223191bb5131edc383564fc06aa7b56064f2..78083989928244430bd0148ae261ba002789b23f 100644 (file)
@@ -1401,7 +1401,7 @@ void run() {
   f(1, integral_constant<bool, true>{});
 }
 // CHECK-ELIDE-NOTREE: error: no matching function for call to 'f'
-// CHECK-ELIDE-NOTREE: note: candidate function not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument
+// CHECK-ELIDE-NOTREE: note: candidate function [with T = int] not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument
 }
 
 namespace ZeroArgs {
index 0e3a9ee50bb241a0daac3f0231bf00ee303e3e13..3a01bf24b31afd78f325d8deea881076313bdb4b 100644 (file)
@@ -338,7 +338,7 @@ namespace PR5756 {
 
 // Tests the exact text used to note the candidates
 namespace test1 {
-  template <class T> void foo(T t, unsigned N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
+  template <class T> void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
   void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}} 
   void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}}
   void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}
index 6e64b25d6b532e1aa3c312bbb8472b703eaa624e..e0f34d937f6f1989bee57c91b984058fa8058574 100644 (file)
@@ -70,7 +70,7 @@ void test_X2(X2 *x2p, const X2 *cx2p) {
 // Tests the exact text used to note the candidates
 namespace test1 {
   class A {
-    template <class T> void foo(T t, unsigned N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
+    template <class T> void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
     void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}} 
     void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}}
     void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}
index 90176314403f69fc6b6ef038bbe8dd7aef25d323..b4936eed3b3562968c420a7e8ef4bb76cae60c9f 100644 (file)
@@ -8161,7 +8161,7 @@ and <I>POD class</I></td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1391">1391</a></td>
     <td>DRWP</td>
     <td>Conversions to parameter types with non-deduced template arguments</td>
-    <td class="partial" align="center">Partial</td>
+    <td class="none" align="center">Unknown</td>
   </tr>
   <tr id="1392">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1392">1392</a></td>