зеркало из https://github.com/microsoft/clang-1.git
Implement C++ DR299, which allows an implicit conversion from a class
type to an integral or enumeration type in the size of an array new expression, e.g., new int[ConvertibleToInt(10)]; This is a GNU and C++0x extension. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107229 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
f186b54cc6
Коммит
6bc574daab
|
@ -2327,6 +2327,19 @@ def err_placement_new_non_placement_delete : Error<
|
|||
"'operator delete'">;
|
||||
def err_array_size_not_integral : Error<
|
||||
"array size expression must have integral or enumerated type, not %0">;
|
||||
def err_array_size_incomplete_type : Error<
|
||||
"array size expression has incomplete class type %0">;
|
||||
def err_array_size_explicit_conversion : Error<
|
||||
"array size expression of type %0 requires explicit conversion to type %1">;
|
||||
def note_array_size_conversion : Note<
|
||||
"conversion to %select{integral|enumeration}0 type %1 declared here">;
|
||||
def err_array_size_ambiguous_conversion : Error<
|
||||
"ambiguous conversion of array size expression of type %0 to an integral or "
|
||||
"enumeration type">;
|
||||
def ext_array_size_conversion : Extension<
|
||||
"implicit conversion from array size expression of type %0 to "
|
||||
"%select{integral|enumeration}1 type %2 is a C++0x extension">;
|
||||
|
||||
def err_default_init_const : Error<
|
||||
"default initialization of an object of const type %0"
|
||||
"%select{| requires a user-provided default constructor}1">;
|
||||
|
|
|
@ -1195,7 +1195,8 @@ public:
|
|||
const PartialDiagnostic &ExplicitConvDiag,
|
||||
const PartialDiagnostic &ExplicitConvNote,
|
||||
const PartialDiagnostic &AmbigDiag,
|
||||
const PartialDiagnostic &AmbigNote);
|
||||
const PartialDiagnostic &AmbigNote,
|
||||
const PartialDiagnostic &ConvDiag);
|
||||
|
||||
bool PerformObjectMemberConversion(Expr *&From,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
|
|
|
@ -721,12 +721,29 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
// or enumeration type with a non-negative value."
|
||||
Expr *ArraySize = (Expr *)ArraySizeE.get();
|
||||
if (ArraySize && !ArraySize->isTypeDependent()) {
|
||||
|
||||
QualType SizeType = ArraySize->getType();
|
||||
|
||||
OwningExprResult ConvertedSize
|
||||
= ConvertToIntegralOrEnumerationType(StartLoc, move(ArraySizeE),
|
||||
PDiag(diag::err_array_size_not_integral),
|
||||
PDiag(diag::err_array_size_incomplete_type)
|
||||
<< ArraySize->getSourceRange(),
|
||||
PDiag(diag::err_array_size_explicit_conversion),
|
||||
PDiag(diag::note_array_size_conversion),
|
||||
PDiag(diag::err_array_size_ambiguous_conversion),
|
||||
PDiag(diag::note_array_size_conversion),
|
||||
PDiag(getLangOptions().CPlusPlus0x? 0
|
||||
: diag::ext_array_size_conversion));
|
||||
if (ConvertedSize.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
ArraySize = ConvertedSize.takeAs<Expr>();
|
||||
ArraySizeE = Owned(ArraySize);
|
||||
SizeType = ArraySize->getType();
|
||||
if (!SizeType->isIntegralOrEnumerationType())
|
||||
return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
|
||||
diag::err_array_size_not_integral)
|
||||
<< SizeType << ArraySize->getSourceRange());
|
||||
return ExprError();
|
||||
|
||||
// Let's see if this is a constant < 0. If so, we reject it out of hand.
|
||||
// We don't care about special rules, so we tell the machinery it's not
|
||||
// evaluated - it gives us a result in more cases.
|
||||
|
|
|
@ -3075,10 +3075,35 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
|
|||
/// integral or enumeration type, if that class type only has a single
|
||||
/// conversion to an integral or enumeration type.
|
||||
///
|
||||
/// \param From The expression we're converting from.
|
||||
/// \param Loc The source location of the construct that requires the
|
||||
/// conversion.
|
||||
///
|
||||
/// \returns The expression converted to an integral or enumeration type,
|
||||
/// if successful, or an invalid expression.
|
||||
/// \param FromE The expression we're converting from.
|
||||
///
|
||||
/// \param NotIntDiag The diagnostic to be emitted if the expression does not
|
||||
/// have integral or enumeration type.
|
||||
///
|
||||
/// \param IncompleteDiag The diagnostic to be emitted if the expression has
|
||||
/// incomplete class type.
|
||||
///
|
||||
/// \param ExplicitConvDiag The diagnostic to be emitted if we're calling an
|
||||
/// explicit conversion function (because no implicit conversion functions
|
||||
/// were available). This is a recovery mode.
|
||||
///
|
||||
/// \param ExplicitConvNote The note to be emitted with \p ExplicitConvDiag,
|
||||
/// showing which conversion was picked.
|
||||
///
|
||||
/// \param AmbigDiag The diagnostic to be emitted if there is more than one
|
||||
/// conversion function that could convert to integral or enumeration type.
|
||||
///
|
||||
/// \param AmbigNote The note to be emitted with \p AmbigDiag for each
|
||||
/// usable conversion function.
|
||||
///
|
||||
/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion
|
||||
/// function, which may be an extension in this case.
|
||||
///
|
||||
/// \returns The expression, converted to an integral or enumeration type if
|
||||
/// successful.
|
||||
Sema::OwningExprResult
|
||||
Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
|
||||
const PartialDiagnostic &NotIntDiag,
|
||||
|
@ -3086,7 +3111,8 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
|
|||
const PartialDiagnostic &ExplicitConvDiag,
|
||||
const PartialDiagnostic &ExplicitConvNote,
|
||||
const PartialDiagnostic &AmbigDiag,
|
||||
const PartialDiagnostic &AmbigNote) {
|
||||
const PartialDiagnostic &AmbigNote,
|
||||
const PartialDiagnostic &ConvDiag) {
|
||||
Expr *From = static_cast<Expr *>(FromE.get());
|
||||
|
||||
// We can't perform any more checking for type-dependent expressions.
|
||||
|
@ -3111,7 +3137,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
|
|||
|
||||
// We must have a complete class type.
|
||||
if (RequireCompleteType(Loc, T, IncompleteDiag))
|
||||
return ExprError();
|
||||
return move(FromE);
|
||||
|
||||
// Look for a conversion to an integral or enumeration type.
|
||||
UnresolvedSet<4> ViableConversions;
|
||||
|
@ -3174,6 +3200,19 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
|
|||
// Apply this conversion.
|
||||
DeclAccessPair Found = ViableConversions[0];
|
||||
CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
|
||||
|
||||
CXXConversionDecl *Conversion
|
||||
= cast<CXXConversionDecl>(Found->getUnderlyingDecl());
|
||||
QualType ConvTy
|
||||
= Conversion->getConversionType().getNonReferenceType();
|
||||
if (ConvDiag.getDiagID()) {
|
||||
if (isSFINAEContext())
|
||||
return ExprError();
|
||||
|
||||
Diag(Loc, ConvDiag)
|
||||
<< T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange();
|
||||
}
|
||||
|
||||
From = BuildCXXMemberCallExpr(FromE.takeAs<Expr>(), Found,
|
||||
cast<CXXConversionDecl>(Found->getUnderlyingDecl()));
|
||||
FromE = Owned(From);
|
||||
|
|
|
@ -435,7 +435,8 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ExprArg Cond,
|
|||
PDiag(diag::err_switch_explicit_conversion),
|
||||
PDiag(diag::note_switch_conversion),
|
||||
PDiag(diag::err_switch_multiple_conversions),
|
||||
PDiag(diag::note_switch_conversion));
|
||||
PDiag(diag::note_switch_conversion),
|
||||
PDiag(0));
|
||||
if (ConvertedCond.isInvalid())
|
||||
return StmtError();
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s
|
||||
|
||||
struct ValueInt
|
||||
{
|
||||
ValueInt(int v = 0) : ValueLength(v) {}
|
||||
operator int () const { return ValueLength; } // expected-note 3{{conversion to integral type 'int' declared here}}
|
||||
private:
|
||||
int ValueLength;
|
||||
};
|
||||
|
||||
enum E { e };
|
||||
struct ValueEnum {
|
||||
operator E() const; // expected-note{{conversion to enumeration type 'E' declared here}}
|
||||
};
|
||||
|
||||
struct ValueBoth : ValueInt, ValueEnum { };
|
||||
|
||||
struct IndirectValueInt : ValueInt { };
|
||||
struct TwoValueInts : ValueInt, IndirectValueInt { };
|
||||
|
||||
void test() {
|
||||
(void)new int[ValueInt(10)]; // expected-warning{{implicit conversion from array size expression of type 'ValueInt' to integral type 'int' is a C++0x extension}}
|
||||
(void)new int[ValueEnum()]; // expected-warning{{implicit conversion from array size expression of type 'ValueEnum' to enumeration type 'E' is a C++0x extension}}
|
||||
(void)new int[ValueBoth()]; // expected-error{{ambiguous conversion of array size expression of type 'ValueBoth' to an integral or enumeration type}}
|
||||
|
||||
(void)new int[TwoValueInts()]; // expected-error{{ambiguous conversion of array size expression of type 'TwoValueInts' to an integral or enumeration type}}
|
||||
}
|
|
@ -287,3 +287,4 @@ void test(S1* s1, S2* s2) {
|
|||
(void)new S2(); // expected-error {{is a private member}}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче