r182406 - Refactor places which perform contextual implicit conversions to go through a

David Blaikie dblaikie at gmail.com
Tue May 21 12:38:59 PDT 2013


On Tue, May 21, 2013 at 12:05 PM, Richard Smith
<richard-llvm at metafoo.co.uk>wrote:

> Author: rsmith
> Date: Tue May 21 14:05:48 2013
> New Revision: 182406
>
> URL: http://llvm.org/viewvc/llvm-project?rev=182406&view=rev
> Log:
> Refactor places which perform contextual implicit conversions to go
> through a
> common function. The C++1y contextual implicit conversion rules themselves
> are
> not yet implemented, however.
>
> This also fixes a subtle bug where template instantiation context notes
> were
> dropped for diagnostics coming from conversions for integral constant
> expressions -- we were implicitly slicing a SemaDiagnosticBuilder into a
> DiagnosticBuilder


Are there some checks (a deleted overload or a runtime check, etc) we could
put in place to avoid making that mistake again/elsewhere?


> when producing these diagnostics, and losing their context
> notes in the process.
>
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/include/clang/Sema/Sema.h
>     cfe/trunk/lib/Sema/SemaExpr.cpp
>     cfe/trunk/lib/Sema/SemaExprCXX.cpp
>     cfe/trunk/lib/Sema/SemaOverload.cpp
>     cfe/trunk/lib/Sema/SemaStmt.cpp
>     cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp
>     cfe/trunk/test/SemaCXX/explicit.cpp
>     cfe/trunk/test/SemaCXX/new-delete.cpp
>     cfe/trunk/test/SemaCXX/switch.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 21
> 14:05:48 2013
> @@ -4759,13 +4759,17 @@ def err_default_init_const : Error<
>  def err_delete_operand : Error<"cannot delete expression of type %0">;
>  def ext_delete_void_ptr_operand : ExtWarn<
>    "cannot delete expression with pointer-to-'void' type %0">;
> -def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
> -                                         "expression of type %0 to a
> pointer">;
> +def err_ambiguous_delete_operand : Error<
> +  "ambiguous conversion of delete expression of type %0 to a pointer">;
>  def warn_delete_incomplete : Warning<
>    "deleting pointer to incomplete type %0 may cause undefined behavior">,
>    InGroup<DiagGroup<"delete-incomplete">>;
>  def err_delete_incomplete_class_type : Error<
>    "deleting incomplete class type %0; no conversions to pointer type">;
> +def err_delete_explicit_conversion : Error<
> +  "converting delete expression from type %0 to type %1 invokes an
> explicit "
> +  "conversion function">;
> +def note_delete_conversion : Note<"conversion to pointer type %0">;
>  def warn_delete_array_type : Warning<
>    "'delete' applied to a pointer-to-array type %0 treated as delete[]">;
>  def err_no_suitable_delete_member_function_found : Error<
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Tue May 21 14:05:48 2013
> @@ -906,6 +906,15 @@ public:
>        // Dispatch to Sema to emit the diagnostic.
>        SemaRef.EmitCurrentDiagnostic(DiagID);
>      }
> +
> +    /// Teach operator<< to produce an object of the correct type.
> +    template<typename T>
> +    friend const SemaDiagnosticBuilder &operator<<(
> +        const SemaDiagnosticBuilder &Diag, const T &Value) {
> +      const DiagnosticBuilder &BaseDiag = Diag;
> +      BaseDiag << Value;
> +      return Diag;
> +    }
>    };
>
>    /// \brief Emit a diagnostic.
> @@ -1928,58 +1937,83 @@ public:
>    ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
>                                                llvm::APSInt &Value,
> CCEKind CCE);
>
> -  /// \brief Abstract base class used to diagnose problems that occur
> while
> -  /// trying to convert an expression to integral or enumeration type.
> -  class ICEConvertDiagnoser {
> +  /// \brief Abstract base class used to perform a contextual implicit
> +  /// conversion from an expression to any type passing a filter.
> +  class ContextualImplicitConverter {
>    public:
>      bool Suppress;
>      bool SuppressConversion;
>
> -    ICEConvertDiagnoser(bool Suppress = false,
> -                        bool SuppressConversion = false)
> -      : Suppress(Suppress), SuppressConversion(SuppressConversion) { }
> +    ContextualImplicitConverter(bool Suppress = false,
> +                                bool SuppressConversion = false)
> +        : Suppress(Suppress), SuppressConversion(SuppressConversion) {}
> +
> +    /// \brief Determine whether the specified type is a valid
> destination type
> +    /// for this conversion.
> +    virtual bool match(QualType T) = 0;
>
>      /// \brief Emits a diagnostic complaining that the expression does
> not have
>      /// integral or enumeration type.
> -    virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
> -                                             QualType T) = 0;
> +    virtual SemaDiagnosticBuilder
> +    diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;
>
>      /// \brief Emits a diagnostic when the expression has incomplete
> class type.
> -    virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation
> Loc,
> -                                                 QualType T) = 0;
> +    virtual SemaDiagnosticBuilder
> +    diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
>
>      /// \brief Emits a diagnostic when the only matching conversion
> function
>      /// is explicit.
> -    virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
> SourceLocation Loc,
> -                                                   QualType T,
> -                                                   QualType ConvTy) = 0;
> +    virtual SemaDiagnosticBuilder diagnoseExplicitConv(
> +        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
>
>      /// \brief Emits a note for the explicit conversion function.
> -    virtual DiagnosticBuilder
> +    virtual SemaDiagnosticBuilder
>      noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) =
> 0;
>
>      /// \brief Emits a diagnostic when there are multiple possible
> conversion
>      /// functions.
> -    virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation
> Loc,
> -                                                QualType T) = 0;
> +    virtual SemaDiagnosticBuilder
> +    diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;
>
>      /// \brief Emits a note for one of the candidate conversions.
> -    virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl
> *Conv,
> -                                            QualType ConvTy) = 0;
> +    virtual SemaDiagnosticBuilder
> +    noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
>
>      /// \brief Emits a diagnostic when we picked a conversion function
>      /// (for cases when we are not allowed to pick a conversion function).
> -    virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation
> Loc,
> -                                                 QualType T,
> -                                                 QualType ConvTy) = 0;
> +    virtual SemaDiagnosticBuilder diagnoseConversion(
> +        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
>
> -    virtual ~ICEConvertDiagnoser() {}
> +    virtual ~ContextualImplicitConverter() {}
>    };
>
> -  ExprResult
> -  ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE,
> -                                     ICEConvertDiagnoser &Diagnoser,
> -                                     bool AllowScopedEnumerations);
> +  class ICEConvertDiagnoser : public ContextualImplicitConverter {
> +    bool AllowScopedEnumerations;
> +
> +  public:
> +    ICEConvertDiagnoser(bool AllowScopedEnumerations,
> +                        bool Suppress, bool SuppressConversion)
> +        : ContextualImplicitConverter(Suppress, SuppressConversion),
> +          AllowScopedEnumerations(AllowScopedEnumerations) {}
> +
> +    /// Match an integral or (possibly scoped) enumeration type.
> +    bool match(QualType T);
> +
> +    SemaDiagnosticBuilder
> +    diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) {
> +      return diagnoseNotInt(S, Loc, T);
> +    }
> +
> +    /// \brief Emits a diagnostic complaining that the expression does
> not have
> +    /// integral or enumeration type.
> +    virtual SemaDiagnosticBuilder
> +    diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0;
> +  };
> +
> +  /// Perform a contextual implicit conversion.
> +  ExprResult PerformContextualImplicitConversion(
> +      SourceLocation Loc, Expr *FromE, ContextualImplicitConverter
> &Converter);
> +
>
>    enum ObjCSubscriptKind {
>      OS_Array,
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue May 21 14:05:48 2013
> @@ -10391,112 +10391,52 @@ Sema::VerifyIntegerConstantExpression(Ex
>      //   have a single non-explicit conversion function to an integral or
>      //   unscoped enumeration type
>      ExprResult Converted;
> -    if (!Diagnoser.Suppress) {
> -      class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {
> -      public:
> -        CXX11ConvertDiagnoser() : ICEConvertDiagnoser(false, true) { }
> -
> -        virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation
> Loc,
> -                                                 QualType T) {
> -          return S.Diag(Loc, diag::err_ice_not_integral) << T;
> -        }
> -
> -        virtual DiagnosticBuilder diagnoseIncomplete(Sema &S,
> -                                                     SourceLocation Loc,
> -                                                     QualType T) {
> -          return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
> -        }
> -
> -        virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
> -                                                       SourceLocation Loc,
> -                                                       QualType T,
> -                                                       QualType ConvTy) {
> -          return S.Diag(Loc, diag::err_ice_explicit_conversion) << T <<
> ConvTy;
> -        }
> -
> -        virtual DiagnosticBuilder noteExplicitConv(Sema &S,
> -                                                   CXXConversionDecl
> *Conv,
> -                                                   QualType ConvTy) {
> -          return S.Diag(Conv->getLocation(),
> diag::note_ice_conversion_here)
> -                   << ConvTy->isEnumeralType() << ConvTy;
> -        }
> -
> -        virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S,
> SourceLocation Loc,
> -                                                    QualType T) {
> -          return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
> -        }
> -
> -        virtual DiagnosticBuilder noteAmbiguous(Sema &S,
> -                                                CXXConversionDecl *Conv,
> -                                                QualType ConvTy) {
> -          return S.Diag(Conv->getLocation(),
> diag::note_ice_conversion_here)
> -                   << ConvTy->isEnumeralType() << ConvTy;
> -        }
> -
> -        virtual DiagnosticBuilder diagnoseConversion(Sema &S,
> -                                                     SourceLocation Loc,
> -                                                     QualType T,
> -                                                     QualType ConvTy) {
> -          return DiagnosticBuilder::getEmpty();
> -        }
> -      } ConvertDiagnoser;
> -
> -      Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E,
> -                                                     ConvertDiagnoser,
> -                                             /*AllowScopedEnumerations*/
> false);
> -    } else {
> -      // The caller wants to silently enquire whether this is an ICE.
> Don't
> -      // produce any diagnostics if it isn't.
> -      class SilentICEConvertDiagnoser : public ICEConvertDiagnoser {
> -      public:
> -        SilentICEConvertDiagnoser() : ICEConvertDiagnoser(true, true) { }
> -
> -        virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation
> Loc,
> -                                                 QualType T) {
> -          return DiagnosticBuilder::getEmpty();
> -        }
> -
> -        virtual DiagnosticBuilder diagnoseIncomplete(Sema &S,
> -                                                     SourceLocation Loc,
> -                                                     QualType T) {
> -          return DiagnosticBuilder::getEmpty();
> -        }
> -
> -        virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
> -                                                       SourceLocation Loc,
> -                                                       QualType T,
> -                                                       QualType ConvTy) {
> -          return DiagnosticBuilder::getEmpty();
> -        }
> -
> -        virtual DiagnosticBuilder noteExplicitConv(Sema &S,
> -                                                   CXXConversionDecl
> *Conv,
> -                                                   QualType ConvTy) {
> -          return DiagnosticBuilder::getEmpty();
> -        }
> -
> -        virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S,
> SourceLocation Loc,
> -                                                    QualType T) {
> -          return DiagnosticBuilder::getEmpty();
> -        }
> -
> -        virtual DiagnosticBuilder noteAmbiguous(Sema &S,
> -                                                CXXConversionDecl *Conv,
> -                                                QualType ConvTy) {
> -          return DiagnosticBuilder::getEmpty();
> -        }
> -
> -        virtual DiagnosticBuilder diagnoseConversion(Sema &S,
> -                                                     SourceLocation Loc,
> -                                                     QualType T,
> -                                                     QualType ConvTy) {
> -          return DiagnosticBuilder::getEmpty();
> -        }
> -      } ConvertDiagnoser;
> -
> -      Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E,
> -                                                     ConvertDiagnoser,
> false);
> -    }
> +    class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {
> +    public:
> +      CXX11ConvertDiagnoser(bool Silent)
> +          : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
> +                                Silent, true) {}
> +
> +      virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S,
> SourceLocation Loc,
> +                                                   QualType T) {
> +        return S.Diag(Loc, diag::err_ice_not_integral) << T;
> +      }
> +
> +      virtual SemaDiagnosticBuilder diagnoseIncomplete(
> +          Sema &S, SourceLocation Loc, QualType T) {
> +        return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
> +      }
> +
> +      virtual SemaDiagnosticBuilder diagnoseExplicitConv(
> +          Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
> +        return S.Diag(Loc, diag::err_ice_explicit_conversion) << T <<
> ConvTy;
> +      }
> +
> +      virtual SemaDiagnosticBuilder noteExplicitConv(
> +          Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
> +        return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
> +                 << ConvTy->isEnumeralType() << ConvTy;
> +      }
> +
> +      virtual SemaDiagnosticBuilder diagnoseAmbiguous(
> +          Sema &S, SourceLocation Loc, QualType T) {
> +        return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
> +      }
> +
> +      virtual SemaDiagnosticBuilder noteAmbiguous(
> +          Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
> +        return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
> +                 << ConvTy->isEnumeralType() << ConvTy;
> +      }
> +
> +      virtual SemaDiagnosticBuilder diagnoseConversion(
> +          Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
> +        llvm_unreachable("conversion functions are permitted");
> +      }
> +    } ConvertDiagnoser(Diagnoser.Suppress);
> +
> +    Converted = PerformContextualImplicitConversion(DiagLoc, E,
> +                                                    ConvertDiagnoser);
>      if (Converted.isInvalid())
>        return Converted;
>      E = Converted.take();
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue May 21 14:05:48 2013
> @@ -1180,54 +1180,53 @@ Sema::BuildCXXNew(SourceRange Range, boo
>    // C++11 [expr.new]p6: The expression [...] shall be of integral or
> unscoped
>    //   enumeration type, or a class type for which a single non-explicit
>    //   conversion function to integral or unscoped enumeration type
> exists.
> +  // C++1y [expr.new]p6: The expression [...] is implicitly converted to
> +  //   std::size_t. (FIXME)
>    if (ArraySize && !ArraySize->isTypeDependent()) {
>      class SizeConvertDiagnoser : public ICEConvertDiagnoser {
>        Expr *ArraySize;
> -
> +
>      public:
>        SizeConvertDiagnoser(Expr *ArraySize)
> -        : ICEConvertDiagnoser(false, false), ArraySize(ArraySize) { }
> -
> -      virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation
> Loc,
> -                                               QualType T) {
> +          : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false,
> false),
> +            ArraySize(ArraySize) {}
> +
> +      virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S,
> SourceLocation Loc,
> +                                                   QualType T) {
>          return S.Diag(Loc, diag::err_array_size_not_integral)
>                   << S.getLangOpts().CPlusPlus11 << T;
>        }
> -
> -      virtual DiagnosticBuilder diagnoseIncomplete(Sema &S,
> SourceLocation Loc,
> -                                                   QualType T) {
> +
> +      virtual SemaDiagnosticBuilder diagnoseIncomplete(
> +          Sema &S, SourceLocation Loc, QualType T) {
>          return S.Diag(Loc, diag::err_array_size_incomplete_type)
>                   << T << ArraySize->getSourceRange();
>        }
> -
> -      virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
> -                                                     SourceLocation Loc,
> -                                                     QualType T,
> -                                                     QualType ConvTy) {
> +
> +      virtual SemaDiagnosticBuilder diagnoseExplicitConv(
> +          Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
>          return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T
> << ConvTy;
>        }
> -
> -      virtual DiagnosticBuilder noteExplicitConv(Sema &S,
> -                                                 CXXConversionDecl *Conv,
> -                                                 QualType ConvTy) {
> +
> +      virtual SemaDiagnosticBuilder noteExplicitConv(
> +          Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
>          return S.Diag(Conv->getLocation(),
> diag::note_array_size_conversion)
>                   << ConvTy->isEnumeralType() << ConvTy;
>        }
> -
> -      virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation
> Loc,
> -                                                  QualType T) {
> +
> +      virtual SemaDiagnosticBuilder diagnoseAmbiguous(
> +          Sema &S, SourceLocation Loc, QualType T) {
>          return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) <<
> T;
>        }
> -
> -      virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl
> *Conv,
> -                                              QualType ConvTy) {
> +
> +      virtual SemaDiagnosticBuilder noteAmbiguous(
> +          Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
>          return S.Diag(Conv->getLocation(),
> diag::note_array_size_conversion)
>                   << ConvTy->isEnumeralType() << ConvTy;
>        }
> -
> -      virtual DiagnosticBuilder diagnoseConversion(Sema &S,
> SourceLocation Loc,
> -                                                   QualType T,
> -                                                   QualType ConvTy) {
> +
> +      virtual SemaDiagnosticBuilder diagnoseConversion(
> +          Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
>          return S.Diag(Loc,
>                        S.getLangOpts().CPlusPlus11
>                          ? diag::warn_cxx98_compat_array_size_conversion
> @@ -1237,8 +1236,7 @@ Sema::BuildCXXNew(SourceRange Range, boo
>      } SizeDiagnoser(ArraySize);
>
>      ExprResult ConvertedSize
> -      = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize,
> SizeDiagnoser,
> -                                           /*AllowScopedEnumerations*/
> false);
> +      = PerformContextualImplicitConversion(StartLoc, ArraySize,
> SizeDiagnoser);
>      if (ConvertedSize.isInvalid())
>        return ExprError();
>
> @@ -2054,7 +2052,8 @@ Sema::ActOnCXXDelete(SourceLocation Star
>                       bool ArrayForm, Expr *ExE) {
>    // C++ [expr.delete]p1:
>    //   The operand shall have a pointer type, or a class type having a
> single
> -  //   conversion function to a pointer type. The result has type void.
> +  //   non-explicit conversion function to a pointer type. The result has
> type
> +  //   void.
>    //
>    // DR599 amends "pointer type" to "pointer to object type" in both
> cases.
>
> @@ -2071,59 +2070,65 @@ Sema::ActOnCXXDelete(SourceLocation Star
>
>      QualType Type = Ex.get()->getType();
>
> -    if (const RecordType *Record = Type->getAs<RecordType>()) {
> -      if (RequireCompleteType(StartLoc, Type,
> -                              diag::err_delete_incomplete_class_type))
> -        return ExprError();
> +    class DeleteConverter : public ContextualImplicitConverter {
> +    public:
> +      DeleteConverter() : ContextualImplicitConverter(false, true) {}
>
> -      SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions;
> +      bool match(QualType ConvType) {
> +        // FIXME: If we have an operator T* and an operator void*, we
> must pick
> +        // the operator T*.
> +        if (const PointerType *ConvPtrType =
> ConvType->getAs<PointerType>())
> +          if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())
> +            return true;
> +        return false;
> +      }
>
> -      CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
> -      std::pair<CXXRecordDecl::conversion_iterator,
> -                CXXRecordDecl::conversion_iterator>
> -        Conversions = RD->getVisibleConversionFunctions();
> -      for (CXXRecordDecl::conversion_iterator
> -             I = Conversions.first, E = Conversions.second; I != E; ++I) {
> -        NamedDecl *D = I.getDecl();
> -        if (isa<UsingShadowDecl>(D))
> -          D = cast<UsingShadowDecl>(D)->getTargetDecl();
> +      SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
> +                                            QualType T) {
> +        return S.Diag(Loc, diag::err_delete_operand) << T;
> +      }
>
> -        // Skip over templated conversion functions; they aren't
> considered.
> -        if (isa<FunctionTemplateDecl>(D))
> -          continue;
> +      SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation
> Loc,
> +                                               QualType T) {
> +        return S.Diag(Loc, diag::err_delete_incomplete_class_type) << T;
> +      }
>
> -        CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
> +      SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation
> Loc,
> +                                                 QualType T, QualType
> ConvTy) {
> +        return S.Diag(Loc, diag::err_delete_explicit_conversion) << T <<
> ConvTy;
> +      }
>
> -        QualType ConvType =
> Conv->getConversionType().getNonReferenceType();
> -        if (const PointerType *ConvPtrType =
> ConvType->getAs<PointerType>())
> -          if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())
> -            ObjectPtrConversions.push_back(Conv);
> +      SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl
> *Conv,
> +                                             QualType ConvTy) {
> +        return S.Diag(Conv->getLocation(), diag::note_delete_conversion)
> +          << ConvTy;
>        }
> -      if (ObjectPtrConversions.size() == 1) {
> -        // We have a single conversion to a pointer-to-object type.
> Perform
> -        // that conversion.
> -        // TODO: don't redo the conversion calculation.
> -        ExprResult Res =
> -          PerformImplicitConversion(Ex.get(),
> -
>  ObjectPtrConversions.front()->getConversionType(),
> -                                    AA_Converting);
> -        if (Res.isUsable()) {
> -          Ex = Res;
> -          Type = Ex.get()->getType();
> -        }
> +
> +      SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
> +                                              QualType T) {
> +        return S.Diag(Loc, diag::err_ambiguous_delete_operand) << T;
>        }
> -      else if (ObjectPtrConversions.size() > 1) {
> -        Diag(StartLoc, diag::err_ambiguous_delete_operand)
> -              << Type << Ex.get()->getSourceRange();
> -        for (unsigned i= 0; i < ObjectPtrConversions.size(); i++)
> -          NoteOverloadCandidate(ObjectPtrConversions[i]);
> -        return ExprError();
> +
> +      SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl
> *Conv,
> +                                          QualType ConvTy) {
> +        return S.Diag(Conv->getLocation(), diag::note_delete_conversion)
> +          << ConvTy;
>        }
> -    }
>
> -    if (!Type->isPointerType())
> -      return ExprError(Diag(StartLoc, diag::err_delete_operand)
> -        << Type << Ex.get()->getSourceRange());
> +      SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation
> Loc,
> +                                               QualType T, QualType
> ConvTy) {
> +        llvm_unreachable("conversion functions are permitted");
> +      }
> +    } Converter;
> +
> +    Ex = PerformContextualImplicitConversion(StartLoc, Ex.take(),
> Converter);
> +    if (Ex.isInvalid())
> +      return ExprError();
> +    Type = Ex.get()->getType();
> +    if (!Converter.match(Type))
> +      // FIXME: PerformContextualImplicitConversion should return
> ExprError
> +      //        itself in this case.
> +      return ExprError();
>
>      QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
>      QualType PointeeElem = Context.getBaseElementType(Pointee);
> @@ -2246,7 +2251,6 @@ Sema::ActOnCXXDelete(SourceLocation Star
>                        PDiag(diag::err_access_dtor) << PointeeElem);
>        }
>      }
> -
>    }
>
>    return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal,
> ArrayForm,
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue May 21 14:05:48 2013
> @@ -5116,34 +5116,31 @@ ExprResult Sema::PerformContextuallyConv
>
>  /// Determine whether the provided type is an integral type, or an
> enumeration
>  /// type of a permitted flavor.
> -static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum)
> {
> -  return AllowScopedEnum ? T->isIntegralOrEnumerationType()
> -                         : T->isIntegralOrUnscopedEnumerationType();
> +bool Sema::ICEConvertDiagnoser::match(QualType T) {
> +  return AllowScopedEnumerations ? T->isIntegralOrEnumerationType()
> +                                 :
> T->isIntegralOrUnscopedEnumerationType();
>  }
>
> -/// \brief Attempt to convert the given expression to an integral or
> -/// enumeration type.
> +/// \brief Attempt to convert the given expression to a type which is
> accepted
> +/// by the given converter.
>  ///
> -/// This routine will attempt to convert an expression of class type to an
> -/// integral or enumeration type, if that class type only has a single
> -/// conversion to an integral or enumeration type.
> +/// This routine will attempt to convert an expression of class type to a
> +/// type accepted by the specified converter. In C++11 and before, the
> class
> +/// must have a single non-explicit conversion function converting to a
> matching
> +/// type. In C++1y, there can be multiple such conversion functions, but
> only
> +/// one target type.
>  ///
>  /// \param Loc The source location of the construct that requires the
>  /// conversion.
>  ///
>  /// \param From The expression we're converting from.
>  ///
> -/// \param Diagnoser Used to output any diagnostics.
> -///
> -/// \param AllowScopedEnumerations Specifies whether conversions to scoped
> -/// enumerations should be considered.
> +/// \param Converter Used to control and diagnose the conversion process.
>  ///
>  /// \returns The expression, converted to an integral or enumeration type
> if
>  /// successful.
> -ExprResult
> -Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
> -                                         ICEConvertDiagnoser &Diagnoser,
> -                                         bool AllowScopedEnumerations) {
> +ExprResult Sema::PerformContextualImplicitConversion(
> +    SourceLocation Loc, Expr *From, ContextualImplicitConverter
> &Converter) {
>    // We can't perform any more checking for type-dependent expressions.
>    if (From->isTypeDependent())
>      return Owned(From);
> @@ -5155,34 +5152,34 @@ Sema::ConvertToIntegralOrEnumerationType
>      From = result.take();
>    }
>
> -  // If the expression already has integral or enumeration type, we're
> golden.
> +  // If the expression already has a matching type, we're golden.
>    QualType T = From->getType();
> -  if (isIntegralOrEnumerationType(T, AllowScopedEnumerations))
> +  if (Converter.match(T))
>      return DefaultLvalueConversion(From);
>
>    // FIXME: Check for missing '()' if T is a function type?
>
> -  // If we don't have a class type in C++, there's no way we can get an
> -  // expression of integral or enumeration type.
> +  // We can only perform contextual implicit conversions on objects of
> class
> +  // type.
>    const RecordType *RecordTy = T->getAs<RecordType>();
>    if (!RecordTy || !getLangOpts().CPlusPlus) {
> -    if (!Diagnoser.Suppress)
> -      Diagnoser.diagnoseNotInt(*this, Loc, T) << From->getSourceRange();
> +    if (!Converter.Suppress)
> +      Converter.diagnoseNoMatch(*this, Loc, T) << From->getSourceRange();
>      return Owned(From);
>    }
>
>    // We must have a complete class type.
>    struct TypeDiagnoserPartialDiag : TypeDiagnoser {
> -    ICEConvertDiagnoser &Diagnoser;
> +    ContextualImplicitConverter &Converter;
>      Expr *From;
> -
> -    TypeDiagnoserPartialDiag(ICEConvertDiagnoser &Diagnoser, Expr *From)
> -      : TypeDiagnoser(Diagnoser.Suppress), Diagnoser(Diagnoser),
> From(From) {}
> -
> +
> +    TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr
> *From)
> +        : TypeDiagnoser(Converter.Suppress), Converter(Converter),
> From(From) {}
> +
>      virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
> -      Diagnoser.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
> +      Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
>      }
> -  } IncompleteDiagnoser(Diagnoser, From);
> +  } IncompleteDiagnoser(Converter, From);
>
>    if (RequireCompleteType(Loc, T, IncompleteDiagnoser))
>      return Owned(From);
> @@ -5201,9 +5198,8 @@ Sema::ConvertToIntegralOrEnumerationType
>           I = Conversions.first, E = Conversions.second; I != E; ++I) {
>      if (CXXConversionDecl *Conversion
>            = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
> -      if (isIntegralOrEnumerationType(
> -            Conversion->getConversionType().getNonReferenceType(),
> -            AllowScopedEnumerations)) {
> +      if (Converter.match(
> +              Conversion->getConversionType().getNonReferenceType())) {
>          if (Conversion->isExplicit())
>            ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
>          else
> @@ -5212,9 +5208,10 @@ Sema::ConvertToIntegralOrEnumerationType
>      }
>    }
>
> +  // FIXME: Implement the C++11 rules!
>    switch (ViableConversions.size()) {
>    case 0:
> -    if (ExplicitConversions.size() == 1 && !Diagnoser.Suppress) {
> +    if (ExplicitConversions.size() == 1 && !Converter.Suppress) {
>        DeclAccessPair Found = ExplicitConversions[0];
>        CXXConversionDecl *Conversion
>          = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
> @@ -5226,12 +5223,12 @@ Sema::ConvertToIntegralOrEnumerationType
>        std::string TypeStr;
>        ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy());
>
> -      Diagnoser.diagnoseExplicitConv(*this, Loc, T, ConvTy)
> +      Converter.diagnoseExplicitConv(*this, Loc, T, ConvTy)
>          << FixItHint::CreateInsertion(From->getLocStart(),
>                                        "static_cast<" + TypeStr + ">(")
>          <<
> FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()),
>                                        ")");
> -      Diagnoser.noteExplicitConv(*this, Conversion, ConvTy);
> +      Converter.noteExplicitConv(*this, Conversion, ConvTy);
>
>        // If we aren't in a SFINAE context, build a call to the
>        // explicit conversion function.
> @@ -5262,11 +5259,11 @@ Sema::ConvertToIntegralOrEnumerationType
>        = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
>      QualType ConvTy
>        = Conversion->getConversionType().getNonReferenceType();
> -    if (!Diagnoser.SuppressConversion) {
> +    if (!Converter.SuppressConversion) {
>        if (isSFINAEContext())
>          return ExprError();
>
> -      Diagnoser.diagnoseConversion(*this, Loc, T, ConvTy)
> +      Converter.diagnoseConversion(*this, Loc, T, ConvTy)
>          << From->getSourceRange();
>      }
>
> @@ -5283,24 +5280,22 @@ Sema::ConvertToIntegralOrEnumerationType
>    }
>
>    default:
> -    if (Diagnoser.Suppress)
> +    if (Converter.Suppress)
>        return ExprError();
>
> -    Diagnoser.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange();
> +    Converter.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange();
>      for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
>        CXXConversionDecl *Conv
>          =
> cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
>        QualType ConvTy = Conv->getConversionType().getNonReferenceType();
> -      Diagnoser.noteAmbiguous(*this, Conv, ConvTy);
> +      Converter.noteAmbiguous(*this, Conv, ConvTy);
>      }
>      return Owned(From);
>    }
>
> -  if (!isIntegralOrEnumerationType(From->getType(),
> AllowScopedEnumerations) &&
> -      !Diagnoser.Suppress) {
> -    Diagnoser.diagnoseNotInt(*this, Loc, From->getType())
> +  if (!Converter.match(From->getType()) && !Converter.Suppress)
> +    Converter.diagnoseNoMatch(*this, Loc, From->getType())
>        << From->getSourceRange();
> -  }
>
>    return DefaultLvalueConversion(From);
>  }
>
> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue May 21 14:05:48 2013
> @@ -592,52 +592,50 @@ Sema::ActOnStartOfSwitchStmt(SourceLocat
>
>    public:
>      SwitchConvertDiagnoser(Expr *Cond)
> -      : ICEConvertDiagnoser(false, true), Cond(Cond) { }
> +        : ICEConvertDiagnoser(/*AllowScopedEnumerations*/true, false,
> true),
> +          Cond(Cond) {}
>
> -    virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
> -                                             QualType T) {
> +    virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation
> Loc,
> +                                                 QualType T) {
>        return S.Diag(Loc, diag::err_typecheck_statement_requires_integer)
> << T;
>      }
>
> -    virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation
> Loc,
> -                                                 QualType T) {
> +    virtual SemaDiagnosticBuilder diagnoseIncomplete(
> +        Sema &S, SourceLocation Loc, QualType T) {
>        return S.Diag(Loc, diag::err_switch_incomplete_class_type)
>                 << T << Cond->getSourceRange();
>      }
>
> -    virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
> SourceLocation Loc,
> -                                                   QualType T,
> -                                                   QualType ConvTy) {
> +    virtual SemaDiagnosticBuilder diagnoseExplicitConv(
> +        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
>        return S.Diag(Loc, diag::err_switch_explicit_conversion) << T <<
> ConvTy;
>      }
>
> -    virtual DiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl
> *Conv,
> -                                               QualType ConvTy) {
> +    virtual SemaDiagnosticBuilder noteExplicitConv(
> +        Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
>        return S.Diag(Conv->getLocation(), diag::note_switch_conversion)
>          << ConvTy->isEnumeralType() << ConvTy;
>      }
>
> -    virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation
> Loc,
> -                                                QualType T) {
> +    virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S,
> SourceLocation Loc,
> +                                                    QualType T) {
>        return S.Diag(Loc, diag::err_switch_multiple_conversions) << T;
>      }
>
> -    virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl
> *Conv,
> -                                            QualType ConvTy) {
> +    virtual SemaDiagnosticBuilder noteAmbiguous(
> +        Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
>        return S.Diag(Conv->getLocation(), diag::note_switch_conversion)
>        << ConvTy->isEnumeralType() << ConvTy;
>      }
>
> -    virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation
> Loc,
> -                                                 QualType T,
> -                                                 QualType ConvTy) {
> -      return DiagnosticBuilder::getEmpty();
> +    virtual SemaDiagnosticBuilder diagnoseConversion(
> +        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
> +      llvm_unreachable("conversion functions are permitted");
>      }
>    } SwitchDiagnoser(Cond);
>
> -  CondResult
> -    = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, SwitchDiagnoser,
> -                                         /*AllowScopedEnumerations*/
> true);
> +  CondResult =
> +      PerformContextualImplicitConversion(SwitchLoc, Cond,
> SwitchDiagnoser);
>    if (CondResult.isInvalid()) return StmtError();
>    Cond = CondResult.take();
>
>
> Modified: cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp (original)
> +++ cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp Tue May 21 14:05:48
> 2013
> @@ -2,11 +2,11 @@
>
>  // Test1
>  struct B {
> -  operator char *(); // expected-note {{candidate function}}
> +  operator char *(); // expected-note {{conversion to pointer type}}
>  };
>
>  struct D : B {
> -  operator int *(); // expected-note {{candidate function}}
> +  operator int *(); // expected-note {{conversion to pointer type}}
>  };
>
>  void f (D d)
> @@ -30,11 +30,11 @@ void f1 (D1 d)
>
>  // Test3
>  struct B2 {
> -  operator const int *();      // expected-note {{candidate function}}
> +  operator const int *(); // expected-note {{conversion to pointer type}}
>  };
>
>  struct D2 : B2 {
> -  operator int *();    // expected-note {{candidate function}}
> +  operator int *(); // expected-note {{conversion to pointer type}}
>  };
>
>  void f2 (D2 d)
> @@ -44,11 +44,11 @@ void f2 (D2 d)
>
>  // Test4
>  struct B3 {
> -  operator const int *();      // expected-note {{candidate function}}
> +  operator const int *(); // expected-note {{conversion to pointer type}}
>  };
>
>  struct A3 {
> -  operator const int *();      // expected-note {{candidate function}}
> +  operator const int *(); // expected-note {{conversion to pointer type}}
>  };
>
>  struct D3 : A3, B3 {
> @@ -78,7 +78,7 @@ void f5(X1 x) { delete x; }  // OK. In s
>
>  // Test7
>  struct Base {
> -   operator int*();
> +   operator int*();
>  };
>
>  struct Derived : Base {
> @@ -87,9 +87,9 @@ struct Derived : Base {
>  };
>
>  void foo6(const Derived cd, Derived d) {
> -       // overload resolution selects Derived::operator int*() const;
> -       delete cd;
> -       delete d;
> +  // overload resolution selects Derived::operator int*() const;
> +  delete cd;
> +  delete d;
>  }
>
>  // Test8
> @@ -104,6 +104,6 @@ struct DD : BB {
>
>  void foo7 (DD d)
>  {
> -        // OK. In selecting a conversion to pointer function, template
> convesions are skipped.
> -       delete d;
> +  // OK. In selecting a conversion to pointer function, template
> convesions are skipped.
> +  delete d;
>  }
>
> Modified: cfe/trunk/test/SemaCXX/explicit.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/explicit.cpp?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/explicit.cpp (original)
> +++ cfe/trunk/test/SemaCXX/explicit.cpp Tue May 21 14:05:48 2013
> @@ -145,14 +145,14 @@ namespace Conversion {
>        operator int*();
>      };
>      struct NotPtr {
> -      explicit operator int*();
> +      explicit operator int*(); // expected-note {{conversion}}
>      };
>
>      Ptr    p;
>      NotPtr np;
>
>      delete p;
> -    delete np; // expected-error {{cannot delete expression of type
> 'NotPtr'}}
> +    delete np; // expected-error {{converting delete expression from type
> 'NotPtr' to type 'int *' invokes an explicit conversion function}}
>    }
>
>    void testFunctionPointer()
>
> Modified: cfe/trunk/test/SemaCXX/new-delete.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/new-delete.cpp (original)
> +++ cfe/trunk/test/SemaCXX/new-delete.cpp Tue May 21 14:05:48 2013
> @@ -116,8 +116,8 @@ struct X1 {
>  };
>
>  struct X2 {
> -  operator int*(); // expected-note {{candidate function}}
> -  operator float*(); // expected-note {{candidate function}}
> +  operator int*(); // expected-note {{conversion}}
> +  operator float*(); // expected-note {{conversion}}
>  };
>
>  void test_delete_conv(X0 x0, X1 x1, X2 x2) {
>
> Modified: cfe/trunk/test/SemaCXX/switch.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/switch.cpp?rev=182406&r1=182405&r2=182406&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/switch.cpp (original)
> +++ cfe/trunk/test/SemaCXX/switch.cpp Tue May 21 14:05:48 2013
> @@ -85,3 +85,18 @@ void local_class(int n) {
>      }();
>    }
>  }
> +
> +namespace Conversion {
> +  struct S {
> +    explicit operator int(); // expected-note {{conversion}}
> +  };
> +  template<typename T> void f(T t) {
> +    switch (t) { // expected-error {{explicit conversion}}
> +    case 0:
> +      return;
> +    default:
> +      break;
> +    }
> +  }
> +  template void f(S); // expected-note {{instantiation of}}
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130521/e98ad915/attachment.html>


More information about the cfe-commits mailing list