forked from OSchip/llvm-project
Implement the lvalue-to-rvalue conversion where needed. The
lvalue-to-rvalue conversion adjusts lvalues of qualified, non-class type to rvalue expressions of the unqualified variant of that type. For example, given: const int i; (void)(i + 17); the lvalue-to-rvalue conversion for the subexpression "i" will turn it from an lvalue expression (a DeclRefExpr) with type 'const int' into an rvalue expression with type 'int'. Both C and C++ mandate this conversion, and somehow we've slid through without implementing it. We now have both DefaultFunctionArrayConversion and DefaultFunctionArrayLvalueConversion, and which gets used depends on whether we do the lvalue-to-rvalue conversion or not. Generally, we do the lvalue-to-rvalue conversion, but there are a few notable exceptions: - the left-hand side of a '.' operator - the left-hand side of an assignment - a C++ throw expression - a subscript expression that's subscripting a vector Making this change exposed two issues with blocks: - we were deducing const-qualified return types of non-class type from a block return, which doesn't fit well - we weren't always setting the known return type of a block when it was provided with the ^return-type syntax Fixes the current Clang-on-Clang compile failure and PR6076. llvm-svn: 95167
This commit is contained in:
parent
d111bd518d
commit
b92a1565c3
|
@ -3617,6 +3617,11 @@ public:
|
|||
// to their respective pointers (C99 6.3.2.1).
|
||||
void DefaultFunctionArrayConversion(Expr *&expr);
|
||||
|
||||
// DefaultFunctionArrayLvalueConversion - converts functions and
|
||||
// arrays to their respective pointers and performs the
|
||||
// lvalue-to-rvalue conversion.
|
||||
void DefaultFunctionArrayLvalueConversion(Expr *&expr);
|
||||
|
||||
// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
|
||||
// do not have a prototype. Integer promotions are performed on each
|
||||
// argument, and arguments that have type float are promoted to double.
|
||||
|
|
|
@ -388,7 +388,7 @@ void
|
|||
CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
||||
const SourceRange &OpRange, const SourceRange &DestRange) {
|
||||
if (!DestType->isLValueReferenceType())
|
||||
Self.DefaultFunctionArrayConversion(SrcExpr);
|
||||
Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
|
||||
|
||||
unsigned msg = diag::err_bad_cxx_cast_generic;
|
||||
if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
|
||||
|
@ -407,7 +407,7 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
|||
const SourceRange &OpRange, const SourceRange &DestRange,
|
||||
CastExpr::CastKind &Kind) {
|
||||
if (!DestType->isLValueReferenceType())
|
||||
Self.DefaultFunctionArrayConversion(SrcExpr);
|
||||
Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
|
||||
|
||||
unsigned msg = diag::err_bad_cxx_cast_generic;
|
||||
if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange,
|
||||
|
@ -434,7 +434,7 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
|||
}
|
||||
|
||||
if (!DestType->isLValueReferenceType() && !DestType->isRecordType())
|
||||
Self.DefaultFunctionArrayConversion(SrcExpr);
|
||||
Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
|
||||
|
||||
unsigned msg = diag::err_bad_cxx_cast_generic;
|
||||
if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
|
||||
|
@ -1197,7 +1197,7 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
|
|||
return false;
|
||||
|
||||
if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
|
||||
DefaultFunctionArrayConversion(CastExpr);
|
||||
DefaultFunctionArrayLvalueConversion(CastExpr);
|
||||
|
||||
// C++ [expr.cast]p5: The conversions performed by
|
||||
// - a const_cast,
|
||||
|
|
|
@ -2978,7 +2978,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
|
|||
|
||||
// If necessary, apply function/array conversion to the receiver.
|
||||
// C99 6.7.5.3p[7,8].
|
||||
DefaultFunctionArrayConversion(RecExpr);
|
||||
DefaultFunctionArrayLvalueConversion(RecExpr);
|
||||
QualType ReceiverType = RecExpr->getType();
|
||||
|
||||
if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType()) {
|
||||
|
|
|
@ -200,6 +200,28 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) {
|
|||
}
|
||||
}
|
||||
|
||||
void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
|
||||
DefaultFunctionArrayConversion(E);
|
||||
|
||||
QualType Ty = E->getType();
|
||||
assert(!Ty.isNull() && "DefaultFunctionArrayLvalueConversion - missing type");
|
||||
if (!Ty->isDependentType() && Ty.hasQualifiers() &&
|
||||
(!getLangOptions().CPlusPlus || !Ty->isRecordType()) &&
|
||||
E->isLvalue(Context) == Expr::LV_Valid) {
|
||||
// C++ [conv.lval]p1:
|
||||
// [...] If T is a non-class type, the type of the rvalue is the
|
||||
// cv-unqualified version of T. Otherwise, the type of the
|
||||
// rvalue is T
|
||||
//
|
||||
// C99 6.3.2.1p2:
|
||||
// If the lvalue has qualified type, the value has the unqualified
|
||||
// version of the type of the lvalue; otherwise, the value has the
|
||||
// type of the lvalue.
|
||||
ImpCastExprToType(E, Ty.getUnqualifiedType(), CastExpr::CK_NoOp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// UsualUnaryConversions - Performs various conversions that are common to most
|
||||
/// operators (C99 6.3). The conversions of array and function types are
|
||||
/// sometimes surpressed. For example, the array->pointer conversion doesn't
|
||||
|
@ -233,7 +255,7 @@ Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
|
|||
return Expr;
|
||||
}
|
||||
|
||||
DefaultFunctionArrayConversion(Expr);
|
||||
DefaultFunctionArrayLvalueConversion(Expr);
|
||||
return Expr;
|
||||
}
|
||||
|
||||
|
@ -2033,8 +2055,9 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
|
|||
Expr *RHSExp = static_cast<Expr*>(Idx.get());
|
||||
|
||||
// Perform default conversions.
|
||||
DefaultFunctionArrayConversion(LHSExp);
|
||||
DefaultFunctionArrayConversion(RHSExp);
|
||||
if (!LHSExp->getType()->getAs<VectorType>())
|
||||
DefaultFunctionArrayLvalueConversion(LHSExp);
|
||||
DefaultFunctionArrayLvalueConversion(RHSExp);
|
||||
|
||||
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
|
||||
|
||||
|
@ -2076,7 +2099,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
|
|||
ResultType = VTy->getElementType();
|
||||
} else if (LHSTy->isArrayType()) {
|
||||
// If we see an array that wasn't promoted by
|
||||
// DefaultFunctionArrayConversion, it must be an array that
|
||||
// DefaultFunctionArrayLvalueConversion, it must be an array that
|
||||
// wasn't promoted because of the C90 rule that doesn't
|
||||
// allow promoting non-lvalue arrays. Warn, then
|
||||
// force the promotion here.
|
||||
|
@ -3777,7 +3800,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
|
|||
return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle,
|
||||
ConversionDecl);
|
||||
|
||||
DefaultFunctionArrayConversion(castExpr);
|
||||
DefaultFunctionArrayLvalueConversion(castExpr);
|
||||
|
||||
// C99 6.5.4p2: the cast type needs to be void or scalar and the expression
|
||||
// type needs to be scalar.
|
||||
|
@ -4814,7 +4837,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
|
|||
//
|
||||
// Suppress this for references: C++ 8.5.3p5.
|
||||
if (!lhsType->isReferenceType())
|
||||
DefaultFunctionArrayConversion(rExpr);
|
||||
DefaultFunctionArrayLvalueConversion(rExpr);
|
||||
|
||||
Sema::AssignConvertType result =
|
||||
CheckAssignmentConstraints(lhsType, rExpr->getType());
|
||||
|
@ -5777,7 +5800,9 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
|
|||
// C99 6.5.17
|
||||
QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) {
|
||||
// Comma performs lvalue conversion (C99 6.3.2.1), but not unary conversions.
|
||||
DefaultFunctionArrayConversion(RHS);
|
||||
// C++ does not perform this conversion (C++ [expr.comma]p1).
|
||||
if (!getLangOptions().CPlusPlus)
|
||||
DefaultFunctionArrayLvalueConversion(RHS);
|
||||
|
||||
// FIXME: Check that RHS type is complete in C mode (it's legal for it to be
|
||||
// incomplete in C++).
|
||||
|
@ -6383,7 +6408,7 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
resultType = CheckAddressOfOperand(Input, OpLoc);
|
||||
break;
|
||||
case UnaryOperator::Deref:
|
||||
DefaultFunctionArrayConversion(Input);
|
||||
DefaultFunctionArrayLvalueConversion(Input);
|
||||
resultType = CheckIndirectionOperand(Input, OpLoc);
|
||||
break;
|
||||
case UnaryOperator::Plus:
|
||||
|
@ -6420,7 +6445,7 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
break;
|
||||
case UnaryOperator::LNot: // logical negation
|
||||
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
|
||||
DefaultFunctionArrayConversion(Input);
|
||||
DefaultFunctionArrayLvalueConversion(Input);
|
||||
resultType = Input->getType();
|
||||
if (resultType->isDependentType())
|
||||
break;
|
||||
|
@ -6590,7 +6615,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
|
|||
|
||||
// Promote the array so it looks more like a normal array subscript
|
||||
// expression.
|
||||
DefaultFunctionArrayConversion(Res);
|
||||
DefaultFunctionArrayLvalueConversion(Res);
|
||||
|
||||
// C99 6.5.2.1p1
|
||||
Expr *Idx = static_cast<Expr*>(OC.U.E);
|
||||
|
@ -6767,6 +6792,8 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
|
|||
diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
|
||||
return;
|
||||
}
|
||||
|
||||
CurBlock->ReturnType = RetTy;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -7385,7 +7412,7 @@ bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) {
|
|||
DiagnoseAssignmentAsCondition(E);
|
||||
|
||||
if (!E->isTypeDependent()) {
|
||||
DefaultFunctionArrayConversion(E);
|
||||
DefaultFunctionArrayLvalueConversion(E);
|
||||
|
||||
QualType T = E->getType();
|
||||
|
||||
|
|
|
@ -1678,8 +1678,8 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
|
|||
if (LVoid || RVoid) {
|
||||
// ... then the [l2r] conversions are performed on the second and third
|
||||
// operands ...
|
||||
DefaultFunctionArrayConversion(LHS);
|
||||
DefaultFunctionArrayConversion(RHS);
|
||||
DefaultFunctionArrayLvalueConversion(LHS);
|
||||
DefaultFunctionArrayLvalueConversion(RHS);
|
||||
LTy = LHS->getType();
|
||||
RTy = RHS->getType();
|
||||
|
||||
|
@ -1765,8 +1765,8 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
|
|||
// C++0x 5.16p6
|
||||
// LValue-to-rvalue, array-to-pointer, and function-to-pointer standard
|
||||
// conversions are performed on the second and third operands.
|
||||
DefaultFunctionArrayConversion(LHS);
|
||||
DefaultFunctionArrayConversion(RHS);
|
||||
DefaultFunctionArrayLvalueConversion(LHS);
|
||||
DefaultFunctionArrayLvalueConversion(RHS);
|
||||
LTy = LHS->getType();
|
||||
RTy = RHS->getType();
|
||||
|
||||
|
|
|
@ -492,7 +492,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
|
|||
|
||||
// If necessary, apply function/array conversion to the receiver.
|
||||
// C99 6.7.5.3p[7,8].
|
||||
DefaultFunctionArrayConversion(RExpr);
|
||||
DefaultFunctionArrayLvalueConversion(RExpr);
|
||||
|
||||
QualType returnType;
|
||||
QualType ReceiverCType =
|
||||
|
|
|
@ -873,7 +873,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
|
|||
<< FirstType << First->getSourceRange();
|
||||
}
|
||||
if (Second) {
|
||||
DefaultFunctionArrayConversion(Second);
|
||||
DefaultFunctionArrayLvalueConversion(Second);
|
||||
QualType SecondType = Second->getType();
|
||||
if (!SecondType->isObjCObjectPointerType())
|
||||
Diag(ForLoc, diag::err_collection_expr_type)
|
||||
|
@ -947,7 +947,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
|
|||
if (RetValExp) {
|
||||
// Don't call UsualUnaryConversions(), since we don't want to do
|
||||
// integer promotions here.
|
||||
DefaultFunctionArrayConversion(RetValExp);
|
||||
DefaultFunctionArrayLvalueConversion(RetValExp);
|
||||
CurBlock->ReturnType = RetValExp->getType();
|
||||
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
|
||||
// We have to remove a 'const' added to copied-in variable which was
|
||||
|
@ -1258,7 +1258,7 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
|
|||
}
|
||||
}
|
||||
|
||||
DefaultFunctionArrayConversion(Exprs[i]);
|
||||
DefaultFunctionArrayLvalueConversion(Exprs[i]);
|
||||
|
||||
InputConstraintInfos.push_back(Info);
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ void foo6() {
|
|||
|
||||
void foo7()
|
||||
{
|
||||
const int (^BB) (void) = ^{ const int i = 1; return i; }; // OK
|
||||
const int (^BB) (void) = ^{ const int i = 1; return i; }; // expected-error{{incompatible block pointer types initializing 'int (^)(void)', expected 'int const (^)(void)'}}
|
||||
const int (^CC) (void) = ^const int{ const int i = 1; return i; }; // OK
|
||||
|
||||
int i;
|
||||
|
@ -123,9 +123,8 @@ void foo7()
|
|||
__block const int k;
|
||||
const int cint = 100;
|
||||
|
||||
int (^MM) (void) = ^{ return k; }; // expected-error {{incompatible block pointer types initializing 'int const (^)(void)', expected 'int (^)(void)'}}
|
||||
int (^NN) (void) = ^{ return cint; }; // expected-error {{incompatible block pointer types initializing 'int const (^)(void)', expected 'int (^)(void)'}}
|
||||
|
||||
int (^MM) (void) = ^{ return k; };
|
||||
int (^NN) (void) = ^{ return cint; };
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
// PR6076
|
||||
void f();
|
||||
void (&g)() = (void(), f);
|
||||
|
||||
int a[1];
|
||||
int (&b)[1] = (void(), a);
|
|
@ -67,3 +67,7 @@ namespace PR6061 {
|
|||
enum { id };
|
||||
};
|
||||
}
|
||||
|
||||
namespace Conditional {
|
||||
enum a { A }; a x(const enum a x) { return 1?x:A; }
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ void constness()
|
|||
// Invalid: T1 const* -> T2*
|
||||
(void)reinterpret_cast<int*>(icp); // expected-error {{reinterpret_cast from 'int const *' to 'int *' casts away constness}}
|
||||
// Invalid: T1*** -> T2 const* const**
|
||||
int const *const **icpcpp = reinterpret_cast<int const* const**>(ipppc); // expected-error {{reinterpret_cast from 'int ***const' to 'int const *const **' casts away constness}}
|
||||
int const *const **icpcpp = reinterpret_cast<int const* const**>(ipppc); // expected-error {{reinterpret_cast from 'int ***' to 'int const *const **' casts away constness}}
|
||||
// Valid: T1* -> T2*
|
||||
int *ip = reinterpret_cast<int*>(icpcpp);
|
||||
// Valid: T* -> T const*
|
||||
|
|
Loading…
Reference in New Issue