r182406 - Refactor places which perform contextual implicit conversions to go through a
Richard Smith
richard at metafoo.co.uk
Tue May 21 14:09:44 PDT 2013
On Tue, May 21, 2013 at 2:01 PM, David Blaikie <dblaikie at gmail.com> wrote:
>
>
>
> On Tue, May 21, 2013 at 12:47 PM, Richard Smith <richard at metafoo.co.uk>wrote:
>
>> On Tue, May 21, 2013 at 12:38 PM, David Blaikie <dblaikie at gmail.com>wrote:
>>
>>> 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?
>>>
>>
>> A runtime check is definitely possible -- we can store a flag in
>> SemaDiagnosticBuilder to indicate that it owns some context notes, copy and
>> clear the flag when its ownership is transferred to another
>> SemaDiagnosticBuilder, and assert in the destructor if the flag is set but
>> the object is not active. But a compile-time check would be better.
>>
>> A deleted conversion function to the base class seems exactly what we
>> want here, except that such a conversion function wouldn't actually ever be
>> used...
>>
>
> I couldn't quite find the particular case that was the original problem in
> your patch, so I'm not sure what you mean by "such a conversion function
> wouldn't ever be used" - I guess you mean that the code went through
> something like:
>
> SDB x...
> DB &y = x;
> DB z(y);
>
> & thus the ctor call wouldn't've failed in the presence of DB(SDB&) =
> delete.
>
I was talking about a conversion function, not a converting constructor.
"SDB::operator DB() = delete" would never be called, because DB is a base
class. We shouldn't add "DB(SDB&) = delete" because that would be a
layering violation.
> and we don't want the base class to know about SemaDiagnosticBuilder so
>> we can't put a deleted constructor there.
>>
>
> Fair enough (could do it as a conversion operator from
> SemadiagnosticBuilder to DiagnosticBuilder, perhaps)
>
:) See above.
>
>
>> Now that we've provided a forwarding operator<< for
>> SemaDiagnosticBuilder, we could possibly switch from using
>> DiagnosticBuilder as a (public) base class to either a private base or a
>> data member.
>>
>
> If this is possible, I don't see why the = delete option wouldn't be, but
> in any case I'm OK with that (encapsulation is nicer anyway - leaks less
> than inheritance).
>
> I tried a quick go at this & hit a couple of issues:
> 1) op bool from DiagnosticBuilder required in SemaDiagnosticBuilder -
> trivial to add
> 2) some other pieces of infrastructure, like ActionResult, are used
> frequently & produce implicit conversions from SemaDiagnosticBuilder& to
> DiagnosticBuilder& - I haven't tried to fix/workaround that as yet
>
We could add an operator ActionResult<T> to SDB, perhaps.
>
>
>>
>>
>>>
>>>
>>>> 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/38e8d1b4/attachment.html>
More information about the cfe-commits
mailing list