r182406 - Refactor places which perform contextual implicit conversions to go through a
David Blaikie
dblaikie at gmail.com
Tue May 21 14:01:44 PDT 2013
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.
> 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)
> 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
>
>
>>
>>
>>> 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/f7588043/attachment.html>
More information about the cfe-commits
mailing list