diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index b8831b4b7ab4..12ce174308a2 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -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. diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index 57c4f9bc2a27..093700d9ef59 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -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, diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 7eeb49139163..7219e3164918 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -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()) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 20d62decf035..ec57a039a86e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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(Idx.get()); // Perform default conversions. - DefaultFunctionArrayConversion(LHSExp); - DefaultFunctionArrayConversion(RHSExp); + if (!LHSExp->getType()->getAs()) + 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(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(); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index e944f328ed98..7671995d609a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -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(); diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index ea8f4e3e890f..85956c3e7e06 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -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 = diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index a75003bf3f5d..54a892ac560e 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -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(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); } diff --git a/clang/test/Sema/block-return.c b/clang/test/Sema/block-return.c index 6416545cb7ea..2385106630d7 100644 --- a/clang/test/Sema/block-return.c +++ b/clang/test/Sema/block-return.c @@ -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; }; } diff --git a/clang/test/SemaCXX/comma.cpp b/clang/test/SemaCXX/comma.cpp new file mode 100644 index 000000000000..79ff7d1cde25 --- /dev/null +++ b/clang/test/SemaCXX/comma.cpp @@ -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); diff --git a/clang/test/SemaCXX/enum.cpp b/clang/test/SemaCXX/enum.cpp index 47ae06ab0e69..dc4a506dda21 100644 --- a/clang/test/SemaCXX/enum.cpp +++ b/clang/test/SemaCXX/enum.cpp @@ -67,3 +67,7 @@ namespace PR6061 { enum { id }; }; } + +namespace Conditional { + enum a { A }; a x(const enum a x) { return 1?x:A; } +} diff --git a/clang/test/SemaCXX/reinterpret-cast.cpp b/clang/test/SemaCXX/reinterpret-cast.cpp index da675609d123..f7ab80e67fd0 100644 --- a/clang/test/SemaCXX/reinterpret-cast.cpp +++ b/clang/test/SemaCXX/reinterpret-cast.cpp @@ -47,7 +47,7 @@ void constness() // Invalid: T1 const* -> T2* (void)reinterpret_cast(icp); // expected-error {{reinterpret_cast from 'int const *' to 'int *' casts away constness}} // Invalid: T1*** -> T2 const* const** - int const *const **icpcpp = reinterpret_cast(ipppc); // expected-error {{reinterpret_cast from 'int ***const' to 'int const *const **' casts away constness}} + int const *const **icpcpp = reinterpret_cast(ipppc); // expected-error {{reinterpret_cast from 'int ***' to 'int const *const **' casts away constness}} // Valid: T1* -> T2* int *ip = reinterpret_cast(icpcpp); // Valid: T* -> T const*