[cfe-commits] r92979 - /cfe/trunk/lib/Sema/SemaOverload.cpp

John McCall rjmccall at apple.com
Thu Jan 7 16:58:22 PST 2010


Author: rjmccall
Date: Thu Jan  7 18:58:21 2010
New Revision: 92979

URL: http://llvm.org/viewvc/llvm-project?rev=92979&view=rev
Log:
Reorganize PrintOverloadCandidates.  No functionality change.


Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=92979&r1=92978&r2=92979&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Jan  7 18:58:21 2010
@@ -4312,6 +4312,127 @@
   Diag(Fn->getLocation(), diag::note_ovl_candidate);
 }
 
+namespace {
+
+void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand) {
+  if (Cand->Function->isDeleted() ||
+      Cand->Function->getAttr<UnavailableAttr>()) {
+    // Deleted or "unavailable" function.
+    S.Diag(Cand->Function->getLocation(), diag::note_ovl_candidate_deleted)
+      << Cand->Function->isDeleted();
+    return;
+  } else if (FunctionTemplateDecl *FunTmpl 
+               = Cand->Function->getPrimaryTemplate()) {
+    // Function template specialization
+    // FIXME: Give a better reason!
+    S.Diag(Cand->Function->getLocation(), diag::note_ovl_template_candidate)
+      << S.getTemplateArgumentBindingsText(FunTmpl->getTemplateParameters(),
+                              *Cand->Function->getTemplateSpecializationArgs());
+    return;
+  }
+
+  // Normal function
+  bool errReported = false;
+  if (!Cand->Viable && Cand->Conversions.size() > 0) {
+    for (int i = Cand->Conversions.size()-1; i >= 0; i--) {
+      const ImplicitConversionSequence &Conversion = 
+        Cand->Conversions[i];
+      if ((Conversion.ConversionKind != 
+             ImplicitConversionSequence::BadConversion) ||
+          Conversion.ConversionFunctionSet.size() == 0)
+        continue;
+      S.Diag(Cand->Function->getLocation(), 
+             diag::note_ovl_candidate_not_viable) << (i+1);
+      errReported = true;
+      for (int j = Conversion.ConversionFunctionSet.size()-1; 
+           j >= 0; j--) {
+        FunctionDecl *Func = Conversion.ConversionFunctionSet[j];
+        S.NoteOverloadCandidate(Func);
+      }
+    }
+  }
+
+  if (!errReported)
+    S.NoteOverloadCandidate(Cand->Function);
+}
+
+void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
+  // Desugar the type of the surrogate down to a function type,
+  // retaining as many typedefs as possible while still showing
+  // the function type (and, therefore, its parameter types).
+  QualType FnType = Cand->Surrogate->getConversionType();
+  bool isLValueReference = false;
+  bool isRValueReference = false;
+  bool isPointer = false;
+  if (const LValueReferenceType *FnTypeRef =
+        FnType->getAs<LValueReferenceType>()) {
+    FnType = FnTypeRef->getPointeeType();
+    isLValueReference = true;
+  } else if (const RValueReferenceType *FnTypeRef =
+               FnType->getAs<RValueReferenceType>()) {
+    FnType = FnTypeRef->getPointeeType();
+    isRValueReference = true;
+  }
+  if (const PointerType *FnTypePtr = FnType->getAs<PointerType>()) {
+    FnType = FnTypePtr->getPointeeType();
+    isPointer = true;
+  }
+  // Desugar down to a function type.
+  FnType = QualType(FnType->getAs<FunctionType>(), 0);
+  // Reconstruct the pointer/reference as appropriate.
+  if (isPointer) FnType = S.Context.getPointerType(FnType);
+  if (isRValueReference) FnType = S.Context.getRValueReferenceType(FnType);
+  if (isLValueReference) FnType = S.Context.getLValueReferenceType(FnType);
+
+  S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
+    << FnType;
+}
+
+void NoteBuiltinOperatorCandidate(Sema &S,
+                                  const char *Opc,
+                                  SourceLocation OpLoc,
+                                  OverloadCandidate *Cand) {
+  assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary");
+  std::string TypeStr("operator");
+  TypeStr += Opc;
+  TypeStr += "(";
+  TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
+  if (Cand->Conversions.size() == 1) {
+    TypeStr += ")";
+    S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
+  } else {
+    TypeStr += ", ";
+    TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
+    TypeStr += ")";
+    S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr;
+  }
+}
+
+void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
+                                  OverloadCandidate *Cand) {
+  unsigned NoOperands = Cand->Conversions.size();
+  for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
+    const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
+    if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion ||
+        ICS.ConversionFunctionSet.empty())
+      continue;
+    if (CXXConversionDecl *Func = dyn_cast<CXXConversionDecl>(
+                     Cand->Conversions[ArgIdx].ConversionFunctionSet[0])) {
+      QualType FromTy = 
+        QualType(static_cast<Type*>(ICS.UserDefined.Before.FromTypePtr),0);
+      S.Diag(OpLoc, diag::note_ambiguous_type_conversion)
+        << FromTy << Func->getConversionType();
+    }
+    for (unsigned j = 0; j < ICS.ConversionFunctionSet.size(); j++) {
+      FunctionDecl *Func = 
+        Cand->Conversions[ArgIdx].ConversionFunctionSet[j];
+      S.NoteOverloadCandidate(Func);
+    }
+  }
+}
+
+} // end anonymous namespace
+
 /// PrintOverloadCandidates - When overload resolution fails, prints
 /// diagnostic messages containing the candidates in the candidate
 /// set. If OnlyViable is true, only viable candidates will be printed.
@@ -4320,122 +4441,32 @@
                               bool OnlyViable,
                               const char *Opc,
                               SourceLocation OpLoc) {
+  bool ReportedNonViableOperator = false;
+
   OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
                              LastCand = CandidateSet.end();
-  bool Reported = false;
   for (; Cand != LastCand; ++Cand) {
-    if (Cand->Viable || !OnlyViable) {
-      if (Cand->Function) {
-        if (Cand->Function->isDeleted() ||
-            Cand->Function->getAttr<UnavailableAttr>()) {
-          // Deleted or "unavailable" function.
-          Diag(Cand->Function->getLocation(), diag::note_ovl_candidate_deleted)
-            << Cand->Function->isDeleted();
-        } else if (FunctionTemplateDecl *FunTmpl 
-                     = Cand->Function->getPrimaryTemplate()) {
-          // Function template specialization
-          // FIXME: Give a better reason!
-          Diag(Cand->Function->getLocation(), diag::note_ovl_template_candidate)
-            << getTemplateArgumentBindingsText(FunTmpl->getTemplateParameters(),
-                              *Cand->Function->getTemplateSpecializationArgs());
-        } else {
-          // Normal function
-          bool errReported = false;
-          if (!Cand->Viable && Cand->Conversions.size() > 0) {
-            for (int i = Cand->Conversions.size()-1; i >= 0; i--) {
-              const ImplicitConversionSequence &Conversion = 
-                                                        Cand->Conversions[i];
-              if ((Conversion.ConversionKind != 
-                   ImplicitConversionSequence::BadConversion) ||
-                  Conversion.ConversionFunctionSet.size() == 0)
-                continue;
-              Diag(Cand->Function->getLocation(), 
-                   diag::note_ovl_candidate_not_viable) << (i+1);
-              errReported = true;
-              for (int j = Conversion.ConversionFunctionSet.size()-1; 
-                   j >= 0; j--) {
-                FunctionDecl *Func = Conversion.ConversionFunctionSet[j];
-                NoteOverloadCandidate(Func);
-              }
-            }
-          }
-          if (!errReported)
-            NoteOverloadCandidate(Cand->Function);
-        }
-      } else if (Cand->IsSurrogate) {
-        // Desugar the type of the surrogate down to a function type,
-        // retaining as many typedefs as possible while still showing
-        // the function type (and, therefore, its parameter types).
-        QualType FnType = Cand->Surrogate->getConversionType();
-        bool isLValueReference = false;
-        bool isRValueReference = false;
-        bool isPointer = false;
-        if (const LValueReferenceType *FnTypeRef =
-              FnType->getAs<LValueReferenceType>()) {
-          FnType = FnTypeRef->getPointeeType();
-          isLValueReference = true;
-        } else if (const RValueReferenceType *FnTypeRef =
-                     FnType->getAs<RValueReferenceType>()) {
-          FnType = FnTypeRef->getPointeeType();
-          isRValueReference = true;
-        }
-        if (const PointerType *FnTypePtr = FnType->getAs<PointerType>()) {
-          FnType = FnTypePtr->getPointeeType();
-          isPointer = true;
-        }
-        // Desugar down to a function type.
-        FnType = QualType(FnType->getAs<FunctionType>(), 0);
-        // Reconstruct the pointer/reference as appropriate.
-        if (isPointer) FnType = Context.getPointerType(FnType);
-        if (isRValueReference) FnType = Context.getRValueReferenceType(FnType);
-        if (isLValueReference) FnType = Context.getLValueReferenceType(FnType);
-
-        Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
-          << FnType;
-      } else if (OnlyViable) {
-        assert(Cand->Conversions.size() <= 2 && 
-               "builtin-binary-operator-not-binary");
-        std::string TypeStr("operator");
-        TypeStr += Opc;
-        TypeStr += "(";
-        TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
-        if (Cand->Conversions.size() == 1) {
-          TypeStr += ")";
-          Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
-        }
-        else {
-          TypeStr += ", ";
-          TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
-          TypeStr += ")";
-          Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr;
-        }
-      }
-      else if (!Cand->Viable && !Reported) {
-        // Non-viability might be due to ambiguous user-defined conversions,
-        // needed for built-in operators. Report them as well, but only once
-        // as we have typically many built-in candidates.
-        unsigned NoOperands = Cand->Conversions.size();
-        for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
-          const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
-          if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion ||
-              ICS.ConversionFunctionSet.empty())
-            continue;
-          if (CXXConversionDecl *Func = dyn_cast<CXXConversionDecl>(
-                         Cand->Conversions[ArgIdx].ConversionFunctionSet[0])) {
-            QualType FromTy = 
-              QualType(
-                     static_cast<Type*>(ICS.UserDefined.Before.FromTypePtr),0);
-            Diag(OpLoc,diag::note_ambiguous_type_conversion)
-                  << FromTy << Func->getConversionType();
-          }
-          for (unsigned j = 0; j < ICS.ConversionFunctionSet.size(); j++) {
-            FunctionDecl *Func = 
-              Cand->Conversions[ArgIdx].ConversionFunctionSet[j];
-            NoteOverloadCandidate(Func);
-          }
-        }
-        Reported = true;
-      }
+    if (OnlyViable && !Cand->Viable)
+      continue;
+
+    if (Cand->Function)
+      NoteFunctionCandidate(*this, Cand);
+    else if (Cand->IsSurrogate)
+      NoteSurrogateCandidate(*this, Cand);
+
+    // This a builtin candidate.  We do not, in general, want to list
+    // every possible builtin candidate.
+
+    // If 'OnlyViable' is true, there were viable candidates.
+    // This must be one of them because of the header condition.  List it.
+    else if (OnlyViable)
+      NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand);
+
+    // Otherwise, non-viability might be due to ambiguous user-defined
+    // conversions.  Report them exactly once.
+    else if (!Cand->Viable && !ReportedNonViableOperator) {
+      NoteAmbiguousUserConversions(*this, OpLoc, Cand);
+      ReportedNonViableOperator = true;
     }
   }
 }





More information about the cfe-commits mailing list