r182406 - Refactor places which perform contextual implicit conversions to go through a
Richard Smith
richard-llvm at metafoo.co.uk
Tue May 21 12:05:48 PDT 2013
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 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}}
+}
More information about the cfe-commits
mailing list